diff --git a/examples/demo/demo.py b/examples/demo/demo.py index 69f6cdc..0b1bd00 100644 --- a/examples/demo/demo.py +++ b/examples/demo/demo.py @@ -16,17 +16,15 @@ from wsme.types import File import bottle -from six import u - import logging class Person(object): id = int - firstname = unicode - lastname = unicode + firstname = str + lastname = str - hobbies = [unicode] + hobbies = [str] def __repr__(self): return "Person(%s, %s %s, %s)" % ( @@ -47,7 +45,7 @@ class DemoRoot(WSRoot): def echofile(self, afile): return afile - @expose(unicode) + @expose(str) def helloworld(self): return u"Здраво, свете (<- Hello World in Serbian !)" @@ -55,25 +53,25 @@ class DemoRoot(WSRoot): def getperson(self): p = Person() p.id = 12 - p.firstname = u'Ross' - p.lastname = u'Geler' + p.firstname = 'Ross' + p.lastname = 'Geler' p.hobbies = [] - print p + print(p) return p @expose([Person]) def listpersons(self): p = Person() p.id = 12 - p.firstname = u('Ross') - p.lastname = u('Geler') + p.firstname = 'Ross' + p.lastname = 'Geler' r = [p] p = Person() p.id = 13 - p.firstname = u('Rachel') - p.lastname = u('Green') + p.firstname = 'Rachel' + p.lastname = 'Green' r.append(p) - print r + print(r) return r @expose(Person) @@ -84,7 +82,7 @@ class DemoRoot(WSRoot): @expose([Person]) @validate([Person]) def setpersons(self, persons): - print persons + print(persons) return persons diff --git a/requirements.txt b/requirements.txt index ffb3942..cf4d31b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -six>=1.9.0 WebOb>=1.8.0 simplegeneric pytz diff --git a/tests/pecantest/test/controllers/ws.py b/tests/pecantest/test/controllers/ws.py index b35a0c6..049e380 100644 --- a/tests/pecantest/test/controllers/ws.py +++ b/tests/pecantest/test/controllers/ws.py @@ -6,8 +6,6 @@ from wsme.types import Base, text, wsattr import wsme import wsmeext.pecan -import six - class Author(Base): id = int @@ -78,7 +76,7 @@ class AuthorsController(RestController): books = BooksController() - @wsmeext.pecan.wsexpose([Author], [six.text_type], [Criterion]) + @wsmeext.pecan.wsexpose([Author], [str], [Criterion]) def get_all(self, q=None, r=None): if q: return [ diff --git a/tests/pecantest/test/tests/test_ws.py b/tests/pecantest/test/tests/test_ws.py index ae06650..3b5617e 100644 --- a/tests/pecantest/test/tests/test_ws.py +++ b/tests/pecantest/test/tests/test_ws.py @@ -1,8 +1,8 @@ -from six.moves import http_client -from test.tests import FunctionalTest +from http import client as http_client import json + import pecan -import six +from test.tests import FunctionalTest used_status_codes = [400, 401, 403, 404, 500] @@ -240,8 +240,5 @@ class TestWS(FunctionalTest): assert book['author']['id'] == 1 def test_no_content_type_if_no_return_type(self): - if six.PY3: - self.skipTest( - "This test does not work in Python 3 until https://review.openstack.org/#/c/48439/ is merged") res = self.app.delete('/authors/4') assert "Content-Type" not in res.headers, res.headers['Content-Type'] diff --git a/wsme/api.py b/wsme/api.py index b2ddf6e..b4d728a 100644 --- a/wsme/api.py +++ b/wsme/api.py @@ -1,8 +1,7 @@ -import traceback import functools import inspect import logging -import six +import traceback import wsme.exc import wsme.types @@ -26,10 +25,7 @@ def wrapfunc(f): def getargspec(f): f = getattr(f, '_wsme_original_func', f) - if six.PY2: - return inspect.getargspec(f) - else: - return inspect.getfullargspec(f) + return inspect.getfullargspec(f) class FunctionArgument(object): @@ -220,7 +216,7 @@ def format_exception(excinfo, debug=False): code = getattr(error, 'code', None) if code and utils.is_valid_code(code) and utils.is_client_error(code): faultstring = (error.faultstring if hasattr(error, 'faultstring') - else six.text_type(error)) + else str(error)) faultcode = getattr(error, 'faultcode', 'Client') r = dict(faultcode=faultcode, faultstring=faultstring) @@ -228,7 +224,7 @@ def format_exception(excinfo, debug=False): r['debuginfo'] = None return r else: - faultstring = six.text_type(error) + faultstring = str(error) debuginfo = "\n".join(traceback.format_exception(*excinfo)) log.error('Server-side error: "%s". Detail: \n%s' % ( diff --git a/wsme/exc.py b/wsme/exc.py index e70db65..f698f65 100644 --- a/wsme/exc.py +++ b/wsme/exc.py @@ -1,5 +1,3 @@ -import six - from wsme.utils import _ @@ -14,10 +12,10 @@ class ClientSideError(RuntimeError): def faultstring(self): if self.msg is None: return str(self) - elif isinstance(self.msg, six.text_type): + elif isinstance(self.msg, str): return self.msg else: - return six.u(self.msg) + return str(self.msg) class InvalidInput(ClientSideError): @@ -28,9 +26,9 @@ class InvalidInput(ClientSideError): @property def faultstring(self): - return _(six.u( - "Invalid input for field/attribute %s. Value: '%s'. %s") - ) % (self.fieldname, self.value, self.msg) + return _("Invalid input for field/attribute %s. Value: '%s'. %s") % ( + self.fieldname, self.value, self.msg, + ) class MissingArgument(ClientSideError): @@ -40,8 +38,9 @@ class MissingArgument(ClientSideError): @property def faultstring(self): - return _(six.u('Missing argument: "%s"%s')) % ( - self.argname, self.msg and ": " + self.msg or "") + return _('Missing argument: "%s"%s') % ( + self.argname, self.msg and ": " + self.msg or "", + ) class UnknownArgument(ClientSideError): @@ -51,8 +50,9 @@ class UnknownArgument(ClientSideError): @property def faultstring(self): - return _(six.u('Unknown argument: "%s"%s')) % ( - self.argname, self.msg and ": " + self.msg or "") + return _('Unknown argument: "%s"%s') % ( + self.argname, self.msg and ": " + self.msg or "", + ) class UnknownFunction(ClientSideError): @@ -62,7 +62,7 @@ class UnknownFunction(ClientSideError): @property def faultstring(self): - return _(six.u("Unknown function name: %s")) % (self.name) + return _("Unknown function name: %s") % (self.name) class UnknownAttribute(ClientSideError): diff --git a/wsme/rest/args.py b/wsme/rest/args.py index 9dc16c7..855b51a 100644 --- a/wsme/rest/args.py +++ b/wsme/rest/args.py @@ -11,8 +11,6 @@ from wsme.types import UserType, ArrayType, DictType, File from wsme.utils import parse_isodate, parse_isotime, parse_isodatetime import wsme.runtime -from six import moves - ARRAY_MAX_SIZE = 1000 @@ -116,7 +114,7 @@ def array_from_params(datatype, params, path, hit_paths): if len(value) < len(attrvalues): value[-1:] = [ datatype.item_type() - for i in moves.range(len(attrvalues) - len(value)) + for i in range(len(attrvalues) - len(value)) ] for i, attrvalue in enumerate(attrvalues): setattr( diff --git a/wsme/rest/json.py b/wsme/rest/json.py index cf8727c..f91dd1e 100644 --- a/wsme/rest/json.py +++ b/wsme/rest/json.py @@ -6,7 +6,6 @@ import decimal import json from simplegeneric import generic -import six import wsme.exc import wsme.types @@ -180,12 +179,12 @@ def dict_fromjson(datatype, value): for item in value.items())) -@fromjson.when_object(six.binary_type) +@fromjson.when_object(bytes) def str_fromjson(datatype, value): - if (isinstance(value, six.string_types) or - isinstance(value, six.integer_types) or + if (isinstance(value, str) or + isinstance(value, int) or isinstance(value, float)): - return six.text_type(value).encode('utf8') + return str(value).encode('utf8') @fromjson.when_object(wsme.types.text) @@ -195,7 +194,7 @@ def text_fromjson(datatype, value): return value -@fromjson.when_object(*six.integer_types + (float,)) +@fromjson.when_object(int, float) def numeric_fromjson(datatype, value): """Convert string object to built-in types int, long or float.""" if value is None: @@ -208,7 +207,7 @@ def bool_fromjson(datatype, value): """Convert to bool, restricting strings to just unambiguous values.""" if value is None: return None - if isinstance(value, six.integer_types + (bool,)): + if isinstance(value, (int, bool,)): return bool(value) if value in ENUM_TRUE: return True @@ -248,7 +247,7 @@ def datetime_fromjson(datatype, value): def parse(s, datatypes, bodyarg, encoding='utf8'): jload = json.load if not hasattr(s, 'read'): - if six.PY3 and isinstance(s, six.binary_type): + if isinstance(s, bytes): s = s.decode(encoding) jload = json.loads try: diff --git a/wsme/rest/xml.py b/wsme/rest/xml.py index 286afa7..60c8796 100644 --- a/wsme/rest/xml.py +++ b/wsme/rest/xml.py @@ -2,8 +2,6 @@ from __future__ import absolute_import import datetime -import six - import xml.etree.ElementTree as et from simplegeneric import generic @@ -69,7 +67,7 @@ def toxml(datatype, key, value): el.append(toxml(attrdef.datatype, attrdef.name, attrvalue)) else: - el.text = six.text_type(value) + el.text = str(value) return el @@ -213,7 +211,7 @@ def dict_fromxml(datatype, element): def unicode_fromxml(datatype, element): if element.get('nil') == 'true': return None - return wsme.types.text(element.text) if element.text else six.u('') + return wsme.types.text(element.text) if element.text else '' @fromxml.when_object(datetime.date) diff --git a/wsme/root.py b/wsme/root.py index ed89148..1d03fba 100644 --- a/wsme/root.py +++ b/wsme/root.py @@ -2,9 +2,6 @@ import logging import sys import weakref -from six import u, b -import six - import webob from wsme.exc import ClientSideError, UnknownFunction @@ -15,7 +12,7 @@ import wsme.types log = logging.getLogger(__name__) -html_body = u(""" +html_body = """ <html> <head> <style type='text/css'> @@ -26,7 +23,7 @@ html_body = u(""" %(content)s </body> </html> -""") +""" def default_prepare_response_body(request, results): @@ -34,12 +31,12 @@ def default_prepare_response_body(request, results): sep = None for value in results: if sep is None: - if isinstance(value, six.text_type): - sep = u('\n') - r = u('') + if isinstance(value, str): + sep = '\n' + r = '' else: - sep = b('\n') - r = b('') + sep = b'\n' + r = b'' else: r += sep r += value @@ -177,9 +174,9 @@ class WSRoot(object): context.path = protocol.extract_path(context) if context.path is None: - raise ClientSideError(u( + raise ClientSideError( 'The %s protocol was unable to extract a function ' - 'path from the request') % protocol.name) + 'path from the request' % protocol.name) context.func, context.funcdef, args = \ self._lookup_function(context.path) @@ -224,9 +221,9 @@ class WSRoot(object): routepath, func = self.find_route(path) if routepath: content = func() - if isinstance(content, six.text_type): + if isinstance(content, str): res.text = content - elif isinstance(content, six.binary_type): + elif isinstance(content, bytes): res.body = content res.content_type = func._cfg['content-type'] return res @@ -253,7 +250,7 @@ class WSRoot(object): res.status = error_status res.content_type = 'text/plain' try: - res.text = u(msg) + res.text = str(msg) except TypeError: res.text = msg log.error(msg) @@ -277,7 +274,7 @@ class WSRoot(object): self._do_call(protocol, context) for context in protocol.iter_calls(request))) - if isinstance(body, six.text_type): + if isinstance(body, str): res.text = body else: res.body = body @@ -365,6 +362,6 @@ class WSRoot(object): "error :\n%s" % e) return html_body % dict( css='', - content=u('<pre>%s</pre>') % - content.replace(b('>'), b('>')) - .replace(b('<'), b('<'))) + content='<pre>%s</pre>' % + content.replace(b'>', b'>') + .replace(b'<', b'<')) diff --git a/wsme/tests/protocol.py b/wsme/tests/protocol.py index 1c41f8c..4515978 100644 --- a/wsme/tests/protocol.py +++ b/wsme/tests/protocol.py @@ -1,12 +1,9 @@ # coding=utf-8 -import unittest -import warnings import datetime import decimal -import six - -from six import u, b +import unittest +import warnings from webtest import TestApp @@ -17,7 +14,7 @@ import wsme.utils warnings.filterwarnings('ignore', module='webob.dec') -binarysample = b('\x00\xff\x43') +binarysample = b'\x00\xff\x43' try: 1 / 0 @@ -88,11 +85,11 @@ class NestedOuterApi(object): class ReturnTypes(object): @expose(wsme.types.bytes) def getbytes(self): - return b("astring") + return b"astring" @expose(wsme.types.text) def gettext(self): - return u('\xe3\x81\xae') + return '\xe3\x81\xae' @expose(int) def getint(self): @@ -137,7 +134,7 @@ class ReturnTypes(object): @expose([wsme.types.bytes]) def getbytesarray(self): - return [b("A"), b("B"), b("C")] + return [b"A", b"B", b"C"] @expose([NestedOuter]) def getnestedarray(self): @@ -145,7 +142,7 @@ class ReturnTypes(object): @expose({wsme.types.bytes: NestedOuter}) def getnesteddict(self): - return {b('a'): NestedOuter(), b('b'): NestedOuter()} + return {b'a': NestedOuter(), b'b': NestedOuter()} @expose(NestedOuter) def getobjectarrayattribute(self): @@ -164,7 +161,7 @@ class ReturnTypes(object): @expose(myenumtype) def getenum(self): - return b('v2') + return b'v2' @expose(NamedAttrsObject) def getnamedattrsobj(self): @@ -254,7 +251,7 @@ class ArgTypes(object): @validate(wsme.types.binary) def setbinary(self, value): print(repr(value)) - self.assertEqual(type(value), six.binary_type) + self.assertEqual(type(value), bytes) return value @expose([wsme.types.bytes]) @@ -393,9 +390,9 @@ class ProtocolTestCase(unittest.TestCase): protocol_options = {} def assertTypedEquals(self, a, b, convert): - if isinstance(a, six.string_types): + if isinstance(a, str): a = convert(a) - if isinstance(b, six.string_types): + if isinstance(b, str): b = convert(b) self.assertEqual(a, b) @@ -433,7 +430,7 @@ class ProtocolTestCase(unittest.TestCase): except CallException as e: self.assertEqual(e.faultcode, 'Client') self.assertEqual(e.faultstring.lower(), - u('unknown function name: invalid_function')) + 'unknown function name: invalid_function') def test_serverside_error(self): try: @@ -462,11 +459,11 @@ class ProtocolTestCase(unittest.TestCase): def test_return_bytes(self): r = self.call('returntypes/getbytes', _rt=wsme.types.bytes) - self.assertEqual(r, b('astring')) + self.assertEqual(r, b'astring') def test_return_text(self): r = self.call('returntypes/gettext', _rt=wsme.types.text) - self.assertEqual(r, u('\xe3\x81\xae')) + self.assertEqual(r, '\xe3\x81\xae') def test_return_int(self): r = self.call('returntypes/getint') @@ -509,8 +506,8 @@ class ProtocolTestCase(unittest.TestCase): self.assertEqual(r, {'inner': {'aint': 0}}) def test_return_bytesarray(self): - r = self.call('returntypes/getbytesarray', _rt=[six.binary_type]) - self.assertEqual(r, [b('A'), b('B'), b('C')]) + r = self.call('returntypes/getbytesarray', _rt=[bytes]) + self.assertEqual(r, [b'A', b'B', b'C']) def test_return_nestedarray(self): r = self.call('returntypes/getnestedarray', _rt=[NestedOuter]) @@ -520,8 +517,8 @@ class ProtocolTestCase(unittest.TestCase): r = self.call('returntypes/getnesteddict', _rt={wsme.types.bytes: NestedOuter}) self.assertEqual(r, { - b('a'): {'inner': {'aint': 0}}, - b('b'): {'inner': {'aint': 0}} + b'a': {'inner': {'aint': 0}}, + b'b': {'inner': {'aint': 0}} }) def test_return_objectarrayattribute(self): @@ -543,23 +540,23 @@ class ProtocolTestCase(unittest.TestCase): def test_return_enum(self): r = self.call('returntypes/getenum', _rt=myenumtype) - self.assertEqual(r, b('v2'), r) + self.assertEqual(r, b'v2', r) def test_return_namedattrsobj(self): r = self.call('returntypes/getnamedattrsobj', _rt=NamedAttrsObject) self.assertEqual(r, {'attr.1': 5, 'attr.2': 6}) def test_setbytes(self): - assert self.call('argtypes/setbytes', value=b('astring'), - _rt=wsme.types.bytes) == b('astring') + assert self.call('argtypes/setbytes', value=b'astring', + _rt=wsme.types.bytes) == b'astring' def test_settext(self): - assert self.call('argtypes/settext', value=u('\xe3\x81\xae'), - _rt=wsme.types.text) == u('\xe3\x81\xae') + assert self.call('argtypes/settext', value='\xe3\x81\xae', + _rt=wsme.types.text) == '\xe3\x81\xae' def test_settext_empty(self): - assert self.call('argtypes/settext', value=u(''), - _rt=wsme.types.text) == u('') + assert self.call('argtypes/settext', value='', + _rt=wsme.types.text) == '' def test_settext_none(self): self.assertEqual( @@ -629,14 +626,14 @@ class ProtocolTestCase(unittest.TestCase): self.assertEqual(r, value) def test_setbytesarray(self): - value = [b("1"), b("2"), b("three")] + value = [b"1", b"2", b"three"] r = self.call('argtypes/setbytesarray', value=(value, [wsme.types.bytes]), _rt=[wsme.types.bytes]) self.assertEqual(r, value) def test_settextarray(self): - value = [u("1")] + value = [u"1"] r = self.call('argtypes/settextarray', value=(value, [wsme.types.text]), _rt=[wsme.types.text]) @@ -664,17 +661,17 @@ class ProtocolTestCase(unittest.TestCase): def test_setnesteddict(self): value = { - b('o1'): {'inner': {'aint': 54}}, - b('o2'): {'inner': {'aint': 55}}, + b'o1': {'inner': {'aint': 54}}, + b'o2': {'inner': {'aint': 55}}, } r = self.call('argtypes/setnesteddict', - value=(value, {six.binary_type: NestedOuter}), - _rt={six.binary_type: NestedOuter}) + value=(value, {bytes: NestedOuter}), + _rt={bytes: NestedOuter}) print(r) self.assertEqual(r, value) def test_setenum(self): - value = b('v1') + value = b'v1' r = self.call('argtypes/setenum', value=value, _rt=myenumtype) self.assertEqual(r, value) @@ -697,7 +694,7 @@ class ProtocolTestCase(unittest.TestCase): assert "No error raised" except CallException as e: self.assertEqual(e.faultcode, 'Client') - self.assertEqual(e.faultstring, u('Missing argument: "value"')) + self.assertEqual(e.faultstring, 'Missing argument: "value"') def test_misc_multiply(self): self.assertEqual(self.call('misc/multiply', a=5, b=2, _rt=int), 10) diff --git a/wsme/tests/test_api.py b/wsme/tests/test_api.py index 36bc2eb..e0f5a65 100644 --- a/wsme/tests/test_api.py +++ b/wsme/tests/test_api.py @@ -1,11 +1,6 @@ # encoding=utf8 -from six import b - -try: - import unittest2 as unittest -except ImportError: - import unittest +import unittest import webtest from wsme import WSRoot, expose, validate @@ -205,7 +200,7 @@ class TestController(unittest.TestCase): assert res.status_int == 406 print(res.body) assert res.body.find( - b("None of the following protocols can handle this request")) != -1 + b"None of the following protocols can handle this request") != -1 def test_return_content_type_guess(self): class DummierProto(DummyProtocol): @@ -259,19 +254,19 @@ class TestController(unittest.TestCase): 'Accept': 'application/json' }) - self.assertEqual(res.body, b('10')) + self.assertEqual(res.body, b'10') res = app.get('/mul_float?a=1.2&b=2.9', headers={ 'Accept': 'application/json' }) - self.assertEqual(res.body, b('3.48')) + self.assertEqual(res.body, b'3.48') res = app.get('/mul_string?a=hello&b=2', headers={ 'Accept': 'application/json' }) - self.assertEqual(res.body, b('"hellohello"')) + self.assertEqual(res.body, b'"hellohello"') def test_wsattr_mandatory(self): class ComplexType(object): diff --git a/wsme/tests/test_exc.py b/wsme/tests/test_exc.py index ba903fb..2406279 100644 --- a/wsme/tests/test_exc.py +++ b/wsme/tests/test_exc.py @@ -2,25 +2,24 @@ from wsme.exc import (ClientSideError, InvalidInput, MissingArgument, UnknownArgument) -from six import u def test_clientside_error(): e = ClientSideError("Test") - assert e.faultstring == u("Test") + assert e.faultstring == "Test" def test_unicode_clientside_error(): - e = ClientSideError(u("\u30d5\u30a1\u30b7\u30ea")) + e = ClientSideError("\u30d5\u30a1\u30b7\u30ea") - assert e.faultstring == u("\u30d5\u30a1\u30b7\u30ea") + assert e.faultstring == "\u30d5\u30a1\u30b7\u30ea" def test_invalidinput(): e = InvalidInput('field', 'badvalue', "error message") - assert e.faultstring == u( + assert e.faultstring == ( "Invalid input for field/attribute field. Value: 'badvalue'. " "error message" ), e.faultstring @@ -30,11 +29,11 @@ def test_missingargument(): e = MissingArgument('argname', "error message") assert e.faultstring == \ - u('Missing argument: "argname": error message'), e.faultstring + ('Missing argument: "argname": error message'), e.faultstring def test_unknownargument(): e = UnknownArgument('argname', "error message") assert e.faultstring == \ - u('Unknown argument: "argname": error message'), e.faultstring + ('Unknown argument: "argname": error message'), e.faultstring diff --git a/wsme/tests/test_restjson.py b/wsme/tests/test_restjson.py index ca80888..fa3afb6 100644 --- a/wsme/tests/test_restjson.py +++ b/wsme/tests/test_restjson.py @@ -2,6 +2,7 @@ import base64 import datetime import decimal import json +from urllib.parse import urlencode from wsme.exc import ClientSideError, InvalidInput from wsme.types import isarray, isdict, isusertype, register_type @@ -11,14 +12,6 @@ from wsme.rest.json import fromjson, tojson, parse import wsme.tests.protocol from wsme.utils import parse_isodatetime, parse_isotime, parse_isodate -import six -from six import b, u - -if six.PY3: - from urllib.parse import urlencode -else: - from urllib import urlencode # noqa - def prepare_value(value, datatype): if isinstance(datatype, list): @@ -35,10 +28,7 @@ def prepare_value(value, datatype): if datatype == decimal.Decimal: return str(value) if datatype == wsme.types.binary: - if six.PY3: - return base64.encodebytes(value).decode('ascii') - else: - return base64.encodestring(value).decode('ascii') + return base64.encodebytes(value).decode('ascii') if datatype == wsme.types.bytes: return value.decode('ascii') return value @@ -49,10 +39,7 @@ def prepare_result(value, datatype): if value is None: return None if datatype == wsme.types.binary: - if six.PY3: - return base64.decodebytes(value.encode('ascii')) - else: - return base64.decodestring(value.encode('ascii')) + return base64.decodebytes(value.encode('ascii')) if isusertype(datatype): datatype = datatype.basetype if isinstance(datatype, list): @@ -119,21 +106,21 @@ class MiniCrud(object): @validate(Obj) def create(self, data): print(repr(data)) - return CRUDResult(data, u('create')) + return CRUDResult(data, 'create') @expose(CRUDResult, method='GET', ignore_extra_args=True) @validate(Obj) def read(self, ref): print(repr(ref)) if ref.id == 1: - ref.name = u('test') - return CRUDResult(ref, u('read')) + ref.name = 'test' + return CRUDResult(ref, 'read') @expose(CRUDResult, method='POST') @validate(Obj) def update(self, data): print(repr(data)) - return CRUDResult(data, u('update')) + return CRUDResult(data, 'update') @expose(CRUDResult, wsme.types.text, body=Obj) def update_with_body(self, msg, data): @@ -145,8 +132,8 @@ class MiniCrud(object): def delete(self, ref): print(repr(ref)) if ref.id == 1: - ref.name = u('test') - return CRUDResult(ref, u('delete')) + ref.name = 'test' + return CRUDResult(ref, 'delete') wsme.tests.protocol.WSTestRoot.crud = MiniCrud() @@ -397,7 +384,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): assert e.msg == "'%s' is not a legal date value" % jdate def test_valid_str_to_builtin_fromjson(self): - types = six.integer_types + (bool, float) + types = (int, bool, float) value = '2' for t in types: for ba in True, False: @@ -430,7 +417,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): self.assertIsInstance(i['a'], float) def test_invalid_str_to_buitin_fromjson(self): - types = six.integer_types + (float, bool) + types = (int, float, bool) value = '2a' for t in types: for ba in True, False: @@ -577,7 +564,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): def test_bytes_tojson(self): assert tojson(wsme.types.bytes, None) is None - assert tojson(wsme.types.bytes, b('ascii')) == u('ascii') + assert tojson(wsme.types.bytes, b'ascii') == 'ascii' def test_encode_sample_params(self): r = wsme.rest.json.encode_sample_params( @@ -596,7 +583,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): assert r[1] == '''2''' def test_PUT(self): - data = {"id": 1, "name": u("test")} + data = {"id": 1, "name": "test"} content = json.dumps(dict(data=data)) headers = { 'Content-Type': 'application/json', @@ -610,7 +597,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" assert result['message'] == "create" def test_GET(self): @@ -625,7 +612,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" def test_GET_complex_accept(self): headers = { @@ -639,7 +626,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" def test_GET_complex_choose_xml(self): headers = { @@ -661,10 +648,11 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): headers=headers, status=406) print("Received:", res.body) - assert res.body == b("Unacceptable Accept type: " - "text/html, application/xml;q=0.9 not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") + assert res.body == ( + b"Unacceptable Accept type: " + b"text/html, application/xml;q=0.9 not in " + b"['application/json', 'text/javascript', " + b"'application/javascript', 'text/xml']") def test_GET_bad_simple_accept(self): headers = { @@ -675,9 +663,10 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): headers=headers, status=406) print("Received:", res.body) - assert res.body == b("Unacceptable Accept type: text/plain not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") + assert res.body == ( + b"Unacceptable Accept type: text/plain not in " + b"['application/json', 'text/javascript', " + b"'application/javascript', 'text/xml']") def test_POST(self): headers = { @@ -685,14 +674,14 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): } res = self.app.post( '/crud', - json.dumps(dict(data=dict(id=1, name=u('test')))), + json.dumps(dict(data=dict(id=1, name='test'))), headers=headers, expect_errors=False) print("Received:", res.body) result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" assert result['message'] == "update" def test_POST_bad_content_type(self): @@ -701,13 +690,14 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): } res = self.app.post( '/crud', - json.dumps(dict(data=dict(id=1, name=u('test')))), + json.dumps(dict(data=dict(id=1, name='test'))), headers=headers, status=415) print("Received:", res.body) - assert res.body == b("Unacceptable Content-Type: text/plain not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") + assert res.body == ( + b"Unacceptable Content-Type: text/plain not in " + b"['application/json', 'text/javascript', " + b"'application/javascript', 'text/xml']") def test_DELETE(self): res = self.app.delete( @@ -717,7 +707,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" assert result['message'] == "delete" def test_extra_arguments(self): @@ -732,7 +722,7 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" assert result['message'] == "read" def test_unexpected_extra_arg(self): @@ -768,12 +758,12 @@ class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): } res = self.app.post( '/crud/update_with_body?msg=hello', - json.dumps(dict(id=1, name=u('test'))), + json.dumps(dict(id=1, name='test')), headers=headers, expect_errors=False) print("Received:", res.body) result = json.loads(res.text) print(result) assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") + assert result['data']['name'] == "test" assert result['message'] == "hello" diff --git a/wsme/tests/test_restxml.py b/wsme/tests/test_restxml.py index 50d3d98..7bea454 100644 --- a/wsme/tests/test_restxml.py +++ b/wsme/tests/test_restxml.py @@ -1,9 +1,6 @@ -import decimal -import datetime import base64 - -from six import u, b -import six +import datetime +import decimal from wsme.rest.xml import fromxml, toxml import wsme.tests.protocol @@ -30,16 +27,13 @@ def dumpxml(key, obj, datatype=None): node.append(dumpxml('key', item[0], key_type)) node.append(dumpxml('value', item[1], value_type)) elif datatype == wsme.types.binary: - if six.PY3: - el.text = base64.encodebytes(obj).decode('ascii') - else: - el.text = base64.encodestring(obj).decode('ascii') + el.text = base64.encodebytes(obj).decode('ascii') elif isinstance(obj, wsme.types.bytes): el.text = obj.decode('ascii') elif isinstance(obj, wsme.types.text): el.text = obj elif type(obj) in (int, float, bool, decimal.Decimal): - el.text = six.text_type(obj) + el.text = str(obj) elif type(obj) in (datetime.date, datetime.time, datetime.datetime): el.text = obj.isoformat() elif isinstance(obj, type(None)): @@ -99,10 +93,7 @@ def loadxml(el, datatype): return d else: if datatype == wsme.types.binary: - if six.PY3: - return base64.decodebytes(el.text.encode('ascii')) - else: - return base64.decodestring(el.text.encode('ascii')) + return base64.decodebytes(el.text.encode('ascii')) if isusertype(datatype): datatype = datatype.basetype if datatype == datetime.date: @@ -112,7 +103,7 @@ def loadxml(el, datatype): if datatype == datetime.datetime: return parse_isodatetime(el.text) if datatype == wsme.types.text: - return datatype(el.text if el.text else u('')) + return datatype(el.text if el.text else '') if datatype == bool: return el.text.lower() != 'false' if datatype is None: @@ -168,28 +159,28 @@ class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): value = MyType() value.aint = 5 - value.atext = u('test') + value.atext = 'test' language, sample = wsme.rest.xml.encode_sample_value( MyType, value, True) print(language, sample) assert language == 'xml' - assert sample == b("""<value> + assert sample == b"""<value> <aint>5</aint> <atext>test</atext> -</value>""") +</value>""" def test_encode_sample_params(self): lang, content = wsme.rest.xml.encode_sample_params( [('a', int, 2)], True) assert lang == 'xml', lang - assert content == b('<parameters>\n <a>2</a>\n</parameters>'), content + assert content == b'<parameters>\n <a>2</a>\n</parameters>', content def test_encode_sample_result(self): lang, content = wsme.rest.xml.encode_sample_result(int, 2, True) assert lang == 'xml', lang - assert content == b('<result>2</result>'), content + assert content == b'<result>2</result>', content def test_nil_fromxml(self): for dt in ( @@ -204,7 +195,7 @@ class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): [int], {int: str}, bool, datetime.date, datetime.time, datetime.datetime): x = et.tostring(toxml(dt, 'value', None)) - assert x == b('<value nil="true" />'), x + assert x == b'<value nil="true" />', x def test_unset_attrs(self): class AType(object): @@ -213,4 +204,4 @@ class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): wsme.types.register_type(AType) x = et.tostring(toxml(AType, 'value', AType())) - assert x == b('<value />'), x + assert x == b'<value />', x diff --git a/wsme/tests/test_root.py b/wsme/tests/test_root.py index 8ccb0c1..e7530cb 100644 --- a/wsme/tests/test_root.py +++ b/wsme/tests/test_root.py @@ -7,7 +7,6 @@ import wsme.protocol import wsme.rest.protocol from wsme.root import default_prepare_response_body -from six import b, u from webob import Request @@ -21,10 +20,10 @@ class TestRoot(unittest.TestCase): txn.abort() def test_default_prepare_response_body(self): - default_prepare_response_body(None, [b('a')]) == b('a') - default_prepare_response_body(None, [b('a'), b('b')]) == b('a\nb') - default_prepare_response_body(None, [u('a')]) == u('a') - default_prepare_response_body(None, [u('a'), u('b')]) == u('a\nb') + default_prepare_response_body(None, [b'a']) == b'a' + default_prepare_response_body(None, [b'a', b'b']) == b'a\nb' + default_prepare_response_body(None, ['a']) == 'a' + default_prepare_response_body(None, ['a', 'b']) == 'a\nb' def test_protocol_selection_error(self): class P(wsme.protocol.Protocol): diff --git a/wsme/tests/test_types.py b/wsme/tests/test_types.py index 81e6891..f5f5abe 100644 --- a/wsme/tests/test_types.py +++ b/wsme/tests/test_types.py @@ -1,9 +1,5 @@ import re -try: - import unittest2 as unittest -except ImportError: - import unittest -import six +import unittest from wsme import exc from wsme import types @@ -37,8 +33,8 @@ class TestTypes(unittest.TestCase): def test_flat_type(self): class Flat(object): aint = int - abytes = six.binary_type - atext = six.text_type + abytes = bytes + atext = str afloat = float types.register_type(Flat) @@ -228,12 +224,12 @@ Value: 'v3'. Value should be one of: v., v.", obj = SType() - obj.atext = six.b('somebytes') - assert obj.atext == six.u('somebytes') + obj.atext = b'somebytes' + assert obj.atext == 'somebytes' assert isinstance(obj.atext, types.text) - obj.abytes = six.u('sometext') - assert obj.abytes == six.b('sometext') + obj.abytes = 'sometext' + assert obj.abytes == b'sometext' assert isinstance(obj.abytes, types.bytes) def test_named_attribute(self): @@ -303,8 +299,8 @@ Value: 'v3'. Value should be one of: v., v.", def test_validate_int(self): self.assertEqual(types.validate_value(int, 1), 1) + self.assertEqual(types.validate_value(int, b'1'), 1) self.assertEqual(types.validate_value(int, '1'), 1) - self.assertEqual(types.validate_value(int, six.u('1')), 1) self.assertRaises(ValueError, types.validate_value, int, 1.1) def test_validate_integer_type(self): @@ -440,10 +436,10 @@ Value: 'v3'. Value should be one of: v., v.", def test_base_init(self): class C1(types.Base): - s = six.text_type + s = str - c = C1(s=six.u('test')) - assert c.s == six.u('test') + c = C1(s='test') + assert c.s == 'test' def test_array_eq(self): ell = [types.ArrayType(str)] @@ -464,20 +460,14 @@ Value: 'v3'. Value should be one of: v., v.", def test_binary_to_base(self): import base64 assert types.binary.tobasetype(None) is None - if six.PY3: - expected = base64.encodebytes(six.b('abcdef')) - else: - expected = base64.encodestring(six.b('abcdef')) - assert types.binary.tobasetype(six.b('abcdef')) == expected + expected = base64.encodebytes(b'abcdef') + assert types.binary.tobasetype(b'abcdef') == expected def test_binary_from_base(self): import base64 assert types.binary.frombasetype(None) is None - if six.PY3: - encoded = base64.encodebytes(six.b('abcdef')) - else: - encoded = base64.encodestring(six.b('abcdef')) - assert types.binary.frombasetype(encoded) == six.b('abcdef') + encoded = base64.encodebytes(b'abcdef') + assert types.binary.frombasetype(encoded) == b'abcdef' def test_wsattr_weakref_datatype(self): # If the datatype inside the wsattr ends up a weakref, it @@ -557,8 +547,8 @@ Value: 'v3'. Value should be one of: v., v.", class buffer: def read(self): return 'from-file' - f = types.File(content=six.b('from-content')) - assert f.file.read() == six.b('from-content') + f = types.File(content=b'from-content') + assert f.file.read() == b'from-content' def test_unregister(self): class TempType(object): diff --git a/wsme/types.py b/wsme/types.py index e67f623..a2dcdf0 100644 --- a/wsme/types.py +++ b/wsme/types.py @@ -2,10 +2,10 @@ import base64 import datetime import decimal import inspect +import io import logging import netaddr import re -import six import sys import uuid import weakref @@ -14,15 +14,15 @@ from wsme import exc log = logging.getLogger(__name__) -#: The 'str' (python 2) or 'bytes' (python 3) type. +#: Byte string. #: Its use should be restricted to #: pure ascii strings as the protocols will generally not be #: be able to send non-unicode strings. #: To transmit binary strings, use the :class:`binary` type -bytes = six.binary_type +bytes = bytes #: Unicode string. -text = six.text_type +text = str class ArrayType(object): @@ -128,18 +128,12 @@ class BinaryType(UserType): def tobasetype(self, value): if value is None: return None - if six.PY3: - return base64.encodebytes(value) - else: - return base64.encodestring(value) + return base64.encodebytes(value) def frombasetype(self, value): if value is None: return None - if six.PY3: - return base64.decodebytes(value) - else: - return base64.decodestring(value) + return base64.decodebytes(value) #: The binary almost-native type @@ -194,13 +188,13 @@ class StringType(UserType): Name = StringType(min_length=1, pattern='^[a-zA-Z ]*$') """ - basetype = six.string_types + basetype = str name = "string" def __init__(self, min_length=None, max_length=None, pattern=None): self.min_length = min_length self.max_length = max_length - if isinstance(pattern, six.string_types): + if isinstance(pattern, str): self.pattern = re.compile(pattern) else: self.pattern = pattern @@ -231,7 +225,7 @@ class IPv4AddressType(UserType): """ A simple IPv4 type. """ - basetype = six.string_types + basetype = str name = "ipv4address" @staticmethod @@ -251,7 +245,7 @@ class IPv6AddressType(UserType): This type represents IPv6 addresses in the short format. """ - basetype = six.string_types + basetype = str name = "ipv6address" @staticmethod @@ -273,13 +267,13 @@ class UuidType(UserType): having dashes. For example, '6a0a707c-45ef-4758-b533-e55adddba8ce' and '6a0a707c45ef4758b533e55adddba8ce' are distinguished as valid. """ - basetype = six.string_types + basetype = str name = "uuid" @staticmethod def validate(value): try: - return six.text_type((uuid.UUID(value))) + return str(uuid.UUID(value)) except (TypeError, ValueError, AttributeError): error = 'Value should be UUID format' raise ValueError(error) @@ -305,13 +299,13 @@ class Enum(UserType): self.values = set(values) name = kw.pop('name', None) if name is None: - name = "Enum(%s)" % ', '.join((six.text_type(v) for v in values)) + name = "Enum(%s)" % ', '.join((str(v) for v in values)) self.name = name def validate(self, value): if value not in self.values: raise ValueError("Value should be one of: %s" % - ', '.join(map(six.text_type, self.values))) + ', '.join(map(str, self.values))) return value def tobasetype(self, value): @@ -341,13 +335,12 @@ Unset = UnsetType() HostRequest = object() -pod_types = six.integer_types + ( - bytes, text, float, bool) +pod_types = (int, bytes, str, float, bool) dt_types = (datetime.date, datetime.time, datetime.datetime) extra_types = (binary, decimal.Decimal) native_types = pod_types + dt_types + extra_types # The types for which we allow promotion to certain numbers. -_promotable_types = six.integer_types + (text, bytes) +_promotable_types = (int, str, bytes) def iscomplex(datatype): @@ -380,7 +373,7 @@ def validate_value(datatype, value): # Do type promotion/conversion and data validation for builtin # types. v_type = type(value) - if datatype in six.integer_types: + if datatype in (int,): if v_type in _promotable_types: try: # Try to turn the value into an int @@ -396,9 +389,9 @@ def validate_value(datatype, value): # An error is raised at the end of the function # when the types don't match. pass - elif datatype is text and isinstance(value, bytes): + elif datatype is str and isinstance(value, bytes): value = value.decode() - elif datatype is bytes and isinstance(value, text): + elif datatype is bytes and isinstance(value, str): value = value.encode() if not isinstance(value, datatype): @@ -496,7 +489,7 @@ class wsattr(object): try: value = validate_value(self.datatype, value) except (ValueError, TypeError) as e: - raise exc.InvalidInput(self.name, value, six.text_type(e)) + raise exc.InvalidInput(self.name, value, str(e)) dataholder = self._get_dataholder(instance) if value is Unset: if hasattr(dataholder, self.key): @@ -730,7 +723,7 @@ class Registry(object): return ct def resolve_type(self, type_): - if isinstance(type_, six.string_types): + if isinstance(type_, str): return self.lookup(type_) if isinstance(type_, list): type_ = ArrayType(type_[0]) @@ -769,7 +762,7 @@ class BaseMeta(type): cls.__registry__.register(cls) -class Base(six.with_metaclass(BaseMeta)): +class Base(metaclass=BaseMeta): """Base type for complex types""" def __init__(self, **kw): for key, value in kw.items(): @@ -784,10 +777,10 @@ class File(Base): input, File can be loaded from a form file field. """ #: The file name - filename = wsattr(text) + filename = wsattr(str) #: Mime type of the content - contenttype = wsattr(text) + contenttype = wsattr(str) def _get_content(self): if self._content is None and self._file: @@ -812,14 +805,14 @@ class File(Base): if fieldstorage.file: self._file = fieldstorage.file self.filename = fieldstorage.filename - self.contenttype = text(fieldstorage.type) + self.contenttype = str(fieldstorage.type) else: self._content = fieldstorage.value @property def file(self): if self._file is None and self._content: - self._file = six.BytesIO(self._content) + self._file = io.BytesIO(self._content) return self._file diff --git a/wsme/utils.py b/wsme/utils.py index e52b0ef..d63d8b1 100644 --- a/wsme/utils.py +++ b/wsme/utils.py @@ -1,8 +1,9 @@ -import decimal +import builtins import datetime +import decimal +from http import client as http_client import pytz import re -from six.moves import builtins, http_client try: import dateutil.parser diff --git a/wsmeext/pecan.py b/wsmeext/pecan.py index 0d1c3b6..560329d 100644 --- a/wsmeext/pecan.py +++ b/wsmeext/pecan.py @@ -2,7 +2,6 @@ from __future__ import absolute_import import functools import inspect -import six import sys import pecan @@ -135,10 +134,7 @@ def wsexpose(*args, **kwargs): pecan_text_xml_decorate(callfunction) if 'json' in funcdef.rest_content_types: pecan_json_decorate(callfunction) - if six.PY2: - argspec = inspect.getargspec(f) - else: - argspec = inspect.getfullargspec(f) + argspec = inspect.getfullargspec(f) pecan.util._cfg(callfunction)['argspec'] = argspec callfunction._wsme_definition = funcdef return callfunction diff --git a/wsmeext/sphinxext.py b/wsmeext/sphinxext.py index 3881a90..f2dde7b 100644 --- a/wsmeext/sphinxext.py +++ b/wsmeext/sphinxext.py @@ -4,7 +4,6 @@ import sys from docutils.parsers.rst import Directive from docutils.parsers.rst import directives -import six from sphinx import addnodes from sphinx.ext import autodoc from sphinx.domains.python import PyClasslike, PyClassmember @@ -36,9 +35,9 @@ def datatypename(datatype): def make_sample_object(datatype): if datatype is wsme.types.bytes: - return six.b('samplestring') + return b'samplestring' if datatype is wsme.types.text: - return u'sample unicode' + return 'sample unicode' if datatype is int: return 5 sample_obj = getattr(datatype, 'sample', datatype)() @@ -252,7 +251,7 @@ class TypeDocumenter(autodoc.ClassDocumenter): ]) content.extend( u' ' * 8 + line - for line in six.text_type(sample).split('\n')) + for line in str(sample).split('\n')) for line in content: self.add_line(line, u'<wsmeext.sphinxext') @@ -455,7 +454,7 @@ def document_function(funcdef, docstrings=None, protocols=['restjson']): ]) codesamples.extend(( u' ' * 12 + line - for line in six.text_type(sample).split('\n') + for line in str(sample).split('\n') )) if funcdef.return_type: @@ -475,7 +474,7 @@ def document_function(funcdef, docstrings=None, protocols=['restjson']): ]) codesamples.extend(( u' ' * 12 + line - for line in six.text_type(sample).split('\n') + for line in str(sample).split('\n') )) docstrings[0:0] = [codesamples]