diff options
author | Michael Howitz <mh@gocept.com> | 2023-01-09 16:38:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-09 16:38:40 +0100 |
commit | ae3a111230d0fd6e7c95fdf9f1cb33d7c3584ea7 (patch) | |
tree | 45fb0fa9ebbeacf6cbb772abf78a4a3376a9d8a9 | |
parent | 65064f94db2680cb694dd94688221c529061e48e (diff) | |
download | zope-traversing-ae3a111230d0fd6e7c95fdf9f1cb33d7c3584ea7.tar.gz |
Config with pure python template (#19)
* Drop support for Python 2.7, 3.5, 3.6.
* Add support for Python 3.11.
23 files changed, 143 insertions, 256 deletions
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f9f622d..2ca497a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,33 +17,30 @@ jobs: fail-fast: false matrix: os: - - ubuntu + - ["ubuntu", "ubuntu-20.04"] config: # [Python version, tox env] - ["3.9", "lint"] - - ["2.7", "py27"] - - ["3.5", "py35"] - - ["3.6", "py36"] - ["3.7", "py37"] - ["3.8", "py38"] - ["3.9", "py39"] - ["3.10", "py310"] - - ["pypy-2.7", "pypy"] + - ["3.11", "py311"] - ["pypy-3.7", "pypy3"] - ["3.9", "docs"] - ["3.9", "coverage"] - runs-on: ${{ matrix.os }}-latest + runs-on: ${{ matrix.os[1] }} if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: ${{ matrix.config[1] }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.config[0] }} - name: Pip cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }} @@ -59,7 +56,7 @@ jobs: - name: Coverage if: matrix.config[1] == 'coverage' run: | - pip install coveralls coverage-python-version + pip install coveralls coveralls --service=github env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -2,15 +2,15 @@ # https://github.com/zopefoundation/meta/tree/master/config/pure-python [meta] template = "pure-python" -commit-id = "d5b6c610d0ec7f0b8f6bbba49353eb89288f62b1" +commit-id = "d03ad585" [python] with-windows = false with-pypy = true with-future-python = false -with-legacy-python = true with-docs = true with-sphinx-doctests = false +with-macos = false [tox] use-flake8 = true diff --git a/CHANGES.rst b/CHANGES.rst index 2b009e8..203b28b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,9 +2,13 @@ Changes ========= -4.5 (unreleased) +5.0 (unreleased) ================ +- Add support for Python 3.11. + +- Drop support for Python 2.7, 3.5, 3.6. + - Add support for Python 3.9, 3.10. @@ -1,7 +1,7 @@ # Generated from: # https://github.com/zopefoundation/meta/tree/master/config/pure-python [bdist_wheel] -universal = 1 +universal = 0 [flake8] doctests = 1 @@ -46,7 +46,7 @@ TESTS_REQUIRE = [ setup( name='zope.traversing', - version='4.5.dev0', + version='5.0.dev0', url='https://github.com/zopefoundation/zope.traversing', license='ZPL 2.1', author='Zope Foundation and Contributors', @@ -59,15 +59,12 @@ setup( 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Natural Language :: English', @@ -87,7 +84,6 @@ setup( }, install_requires=[ 'setuptools', - 'six', 'transaction', 'zope.component', 'zope.i18n', @@ -101,12 +97,5 @@ setup( tests_require=TESTS_REQUIRE, include_package_data=True, zip_safe=False, - python_requires=', '.join([ - '>=2.7', - '!=3.0.*', - '!=3.1.*', - '!=3.2.*', - '!=3.3.*', - '!=3.4.*', - ]), + python_requires='>=3.7', ) diff --git a/src/zope/traversing/adapters.py b/src/zope/traversing/adapters.py index 3ce5aee..2deae8f 100644 --- a/src/zope/traversing/adapters.py +++ b/src/zope/traversing/adapters.py @@ -15,8 +15,6 @@ Adapters for the traversing mechanism. """ -import six - import zope.interface from zope.location.interfaces import ILocationInfo from zope.location.interfaces import LocationError @@ -32,7 +30,7 @@ _marker = object() # opaque marker that doesn't get security proxied @zope.interface.implementer(ITraversable) -class DefaultTraversable(object): +class DefaultTraversable: """ Traverses objects via attribute and item lookup. @@ -45,14 +43,7 @@ class DefaultTraversable(object): def traverse(self, name, furtherPath): subject = self._subject __traceback_info__ = (subject, name, furtherPath) - try: - attr = getattr(subject, name, _marker) - except UnicodeEncodeError: - # If we're on Python 2, and name was a unicode string the - # name would have been encoded using the system encoding - # (usually ascii). Failure to encode means invalid - # attribute name. - attr = _marker + attr = getattr(subject, name, _marker) if attr is not _marker: return attr if hasattr(subject, '__getitem__'): @@ -64,7 +55,7 @@ class DefaultTraversable(object): @zope.interface.implementer(ITraverser) -class Traverser(object): +class Traverser: """ Provide traverse features. @@ -80,7 +71,7 @@ class Traverser(object): if not path: return self.context - if isinstance(path, six.string_types): + if isinstance(path, str): path = path.split('/') if len(path) > 1 and not path[-1]: # Remove trailing slash @@ -156,14 +147,6 @@ def traversePathElement(obj, name, further_path, default=_marker, try: return traversable.traverse(nm, further_path) - except UnicodeEncodeError: - # If we're on Python 2, and nm was a unicode string, and the - # traversable tried to do an attribute lookup, the nm would have been - # encoded using the system encoding (usually ascii). Failure to encode - # means invalid attribute name. - if default is not _marker: - return default - raise LocationError(obj, name) except LocationError: if default is not _marker: return default diff --git a/src/zope/traversing/api.py b/src/zope/traversing/api.py index 0f7ec65..89ad786 100644 --- a/src/zope/traversing/api.py +++ b/src/zope/traversing/api.py @@ -16,12 +16,11 @@ Convenience functions for traversing the object tree. This module provides :class:`zope.traversing.interfaces.ITraversalAPI` """ -import six - from zope.interface import moduleProvides from zope.location.interfaces import ILocationInfo from zope.location.interfaces import IRoot +from zope.traversing.adapters import traversePathElement from zope.traversing.interfaces import ITraversalAPI from zope.traversing.interfaces import ITraverser @@ -43,16 +42,15 @@ def joinPath(path, *args): """ if not args: - # Concatenating u'' is much quicker than unicode(path) - return u'' + path + return path if path != '/' and path.endswith('/'): raise ValueError('path must not end with a "/": %s' % path) if path != '/': - path += u'/' + path += '/' for arg in args: if arg.startswith('/') or arg.endswith('/'): raise ValueError("Leading or trailing slashes in path elements") - return _normalizePath(path + u'/'.join(args)) + return _normalizePath(path + '/'.join(args)) def getPath(obj): @@ -155,19 +153,19 @@ def _normalizePath(path): """Normalize a path by resolving '.' and '..' path elements.""" # Special case for the root path. - if path == u'/': + if path == '/': return path new_segments = [] - prefix = u'' + prefix = '' if path.startswith('/'): - prefix = u'/' + prefix = '/' path = path[1:] - for segment in path.split(u'/'): - if segment == u'.': + for segment in path.split('/'): + if segment == '.': continue - if segment == u'..': + if segment == '..': new_segments.pop() # raises IndexError if there is nothing to pop continue if not segment: @@ -175,7 +173,7 @@ def _normalizePath(path): % path) new_segments.append(segment) - return prefix + u'/'.join(new_segments) + return prefix + '/'.join(new_segments) def canonicalPath(path_or_object): @@ -185,32 +183,28 @@ def canonicalPath(path_or_object): See `ITraversalAPI` for details. """ - if isinstance(path_or_object, six.string_types): + if isinstance(path_or_object, str): path = path_or_object if not path: raise ValueError("path must be non-empty: %s" % path) else: path = getPath(path_or_object) - path = u'' + path + path = '' + path # Special case for the root path. - if path == u'/': + if path == '/': return path - if path[0] != u'/': + if path[0] != '/': raise ValueError('canonical path must start with a "/": %s' % path) - if path[-1] == u'/': + if path[-1] == '/': raise ValueError('path must not end with a "/": %s' % path) # Break path into segments. Process '.' and '..' segments. return _normalizePath(path) -# import this down here to avoid circular imports -from zope.traversing.adapters import traversePathElement - - # Synchronize the documentation. for name in ITraversalAPI.names(): if name in globals(): diff --git a/src/zope/traversing/browser/absoluteurl.py b/src/zope/traversing/browser/absoluteurl.py index 0cdddae..7be68f5 100644 --- a/src/zope/traversing/browser/absoluteurl.py +++ b/src/zope/traversing/browser/absoluteurl.py @@ -18,15 +18,8 @@ These are registered as views and named views (``absolute_url``) if you load this package's ``configure.zcml`` with :mod:`zope.configuration.xmlconfig`. """ -try: - from urllib.parse import quote_from_bytes as quote -except ImportError: - from urllib import quote - -try: - from urllib.parse import unquote_to_bytes as unquote -except ImportError: - from urllib import unquote +from urllib.parse import quote_from_bytes as quote +from urllib.parse import unquote_to_bytes as unquote import zope.component from zope.i18nmessageid import MessageFactory @@ -133,8 +126,8 @@ class AbsoluteURL(_EncodedUnicode, base += ( { 'name': name, - 'url': ("%s/%s" % (base[-1]['url'], - quote(name.encode('utf-8'), _safe))) + 'url': ("{}/{}".format(base[-1]['url'], + quote(name.encode('utf-8'), _safe))) }, ) @@ -181,8 +174,8 @@ class SiteAbsoluteURL(_EncodedUnicode, base += ( { 'name': name, - 'url': ("%s/%s" % (base[-1]['url'], - quote(name.encode('utf-8'), _safe))) + 'url': ("{}/{}".format(base[-1]['url'], + quote(name.encode('utf-8'), _safe))) }, ) diff --git a/src/zope/traversing/browser/interfaces.py b/src/zope/traversing/browser/interfaces.py index 21a6a24..2d4f0d8 100644 --- a/src/zope/traversing/browser/interfaces.py +++ b/src/zope/traversing/browser/interfaces.py @@ -25,16 +25,16 @@ class IAbsoluteURL(Interface): """ def __unicode__(): - """Returns the URL as a unicode string.""" + """Return the URL as unquoted str.""" def __str__(): - """Returns an ASCII string with all unicode characters url quoted.""" + """Return a ASCII string with all non-ASCII characters url quoted.""" def __repr__(): - """Get a string representation """ + """Get a string representation.""" def __call__(): - """Returns an ASCII string with all unicode characters url quoted.""" + """Return an ASCII string with all non-ASCII characters url quoted.""" def breadcrumbs(): """Returns a tuple like ({'name':name, 'url':url}, ...) diff --git a/src/zope/traversing/browser/tests.py b/src/zope/traversing/browser/tests.py index dde3eeb..0430880 100644 --- a/src/zope/traversing/browser/tests.py +++ b/src/zope/traversing/browser/tests.py @@ -46,21 +46,21 @@ class Root(Contained): pass -class TrivialContent(object): +class TrivialContent: """Trivial content object, used because instances of object are rocks.""" -class AdaptedContent(object): +class AdaptedContent: """A simple content object that has an ILocation adapter for it.""" -class FooContent(object): +class FooContent: """Class whose location will be provided by an adapter.""" @implementer(ILocation) @adapter(FooContent) -class FooLocation(object): +class FooLocation: """Adapts FooAdapter to the ILocation protocol.""" def __init__(self, context): @@ -77,11 +77,6 @@ class FooLocation(object): class TestAbsoluteURL(PlacelessSetup, unittest.TestCase): - assertRaisesRegex = getattr( - unittest.TestCase, - 'assertRaisesRegex', - getattr(unittest.TestCase, 'assertRaisesRegexp')) # PY2 - def setUp(self): PlacelessSetup.setUp(self) from zope.traversing.browser import AbsoluteURL @@ -195,11 +190,11 @@ class TestAbsoluteURL(PlacelessSetup, unittest.TestCase): # Tests so that AbsoluteURL handle unicode names as well request = TestRequest() root = Root() - root.__name__ = u'\u0439' + root.__name__ = '\u0439' - content = contained(TrivialContent(), root, name=u'\u0442') - content = contained(TrivialContent(), content, name=u'\u0435') - content = contained(TrivialContent(), content, name=u'\u0441') + content = contained(TrivialContent(), root, name='\u0442') + content = contained(TrivialContent(), content, name='\u0435') + content = contained(TrivialContent(), content, name='\u0441') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81') @@ -215,13 +210,13 @@ class TestAbsoluteURL(PlacelessSetup, unittest.TestCase): breadcrumbs, ( {'name': '', 'url': 'http://127.0.0.1'}, - {'name': u'\u0439', + {'name': '\u0439', 'url': 'http://127.0.0.1/%D0%B9'}, - {'name': u'\u0442', + {'name': '\u0442', 'url': 'http://127.0.0.1/%D0%B9/%D1%82'}, - {'name': u'\u0435', + {'name': '\u0435', 'url': 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5'}, - {'name': u'\u0441', + {'name': '\u0441', 'url': 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81'})) def testRetainSkin(self): @@ -323,11 +318,11 @@ class TestAbsoluteURL(PlacelessSetup, unittest.TestCase): def test_nameless_context(self): @implementer(ILocation) - class Context(object): + class Context: __parent__ = self __name__ = None - class DummyAbsoluteURL(object): + class DummyAbsoluteURL: # Our implementation of IAbsoluteURL # for our parent diff --git a/src/zope/traversing/namespace.py b/src/zope/traversing/namespace.py index 31f4ef4..08609e2 100644 --- a/src/zope/traversing/namespace.py +++ b/src/zope/traversing/namespace.py @@ -63,8 +63,6 @@ __docformat__ = 'restructuredtext' import re -import six - import zope.component import zope.interface from zope.i18n.interfaces import IModifiableUserPreferredLanguages @@ -125,7 +123,7 @@ def namespaceLookup(ns, name, object, request=None): >>> namespaceLookup('fiz', 'bar', C()) # doctest: +ELLIPSIS Traceback (most recent call last): ... - LocationError: (<zope.traversing.namespace.C object at 0x...>, '++fiz++bar') + zope.location.interfaces.LocationError: (<zope.traversing.namespace.C object at 0x...>, '++fiz++bar') We'll get the same thing if we provide a request:: @@ -134,7 +132,7 @@ def namespaceLookup(ns, name, object, request=None): >>> namespaceLookup('foo', 'bar', C(), request) # doctest: +ELLIPSIS Traceback (most recent call last): ... - LocationError: (<zope.traversing.namespace.C object at 0x...>, '++foo++bar') + zope.location.interfaces.LocationError: (<zope.traversing.namespace.C object at 0x...>, '++foo++bar') We need to provide a view:: @@ -161,7 +159,7 @@ def namespaceLookup(ns, name, object, request=None): traverser = zope.component.queryAdapter(object, ITraversable, ns) if traverser is None: - raise LocationError(object, "++%s++%s" % (ns, name)) + raise LocationError(object, "++{}++{}".format(ns, name)) return traverser.traverse(name, ()) @@ -236,7 +234,7 @@ def queryResource(context, name, request, default=None): # ---- namespace processors below ---- @zope.interface.implementer(ITraversable) -class SimpleHandler(object): +class SimpleHandler: def __init__(self, context, request=None): """ @@ -295,7 +293,7 @@ class acquire(SimpleHandler): >>> adapter.traverse('d', ()) Traceback (most recent call last): ... - LocationError: (splat, 'd') + zope.location.interfaces.LocationError: (splat, 'd') """ i = 0 ob = self.context @@ -400,7 +398,7 @@ class etc(SimpleHandler): @zope.interface.implementer(ITraversable) -class view(object): +class view: """ Traversal adapter for the ``view`` (``@@``) namespace. @@ -500,11 +498,6 @@ class vh(view): request = self.request - if not six.PY3: - # `name` comes in as unicode, we need to make it a string - # so absolute URLs don't all become unicode. - name = name.encode('utf-8') - if name: try: proto, host, port = name.split(":") diff --git a/src/zope/traversing/publicationtraverse.py b/src/zope/traversing/publicationtraverse.py index 301d939..437e2de 100644 --- a/src/zope/traversing/publicationtraverse.py +++ b/src/zope/traversing/publicationtraverse.py @@ -15,8 +15,6 @@ """ __docformat__ = 'restructuredtext' -import six - from zope.component import queryMultiAdapter from zope.publisher.interfaces import IPublishTraverse from zope.publisher.interfaces import NotFound @@ -28,7 +26,7 @@ from zope.traversing.namespace import namespaceLookup from zope.traversing.namespace import nsParse -class PublicationTraverser(object): +class PublicationTraverser: """Traversal used for publication. The significant differences from @@ -83,7 +81,7 @@ class PublicationTraverser(object): def traversePath(self, request, ob, path): - if isinstance(path, six.string_types): + if isinstance(path, str): path = path.split('/') if len(path) > 1 and not path[-1]: # Remove trailing slash diff --git a/src/zope/traversing/testing.py b/src/zope/traversing/testing.py index 5a54f33..adbc0a7 100644 --- a/src/zope/traversing/testing.py +++ b/src/zope/traversing/testing.py @@ -35,13 +35,13 @@ from zope.traversing.namespace import etc @zope.interface.implementer(IContained) -class Contained(object): +class Contained: __parent__ = None __name__ = None @zope.interface.implementer(IContained) -class ContainedProxy(object): +class ContainedProxy: __parent__ = None __name__ = None __obj__ = None diff --git a/src/zope/traversing/tests/test_conveniencefunctions.py b/src/zope/traversing/tests/test_conveniencefunctions.py index 1f8baf7..9354cf4 100644 --- a/src/zope/traversing/tests/test_conveniencefunctions.py +++ b/src/zope/traversing/tests/test_conveniencefunctions.py @@ -31,7 +31,7 @@ from zope.traversing.interfaces import ITraverser from zope.traversing.testing import contained -class C(object): +class C: __parent__ = None __name__ = None @@ -136,23 +136,6 @@ class TestFunctional(PlacelessSetup, unittest.TestCase): self.folder, './item' ) - def testTraverseNameUnicode(self): - from zope.interface import implementer - - from zope.traversing.api import traverseName - - @implementer(ITraversable) - class BrokenTraversable(object): - def traverse(self, name, furtherPath): - getattr(self, u'\u2019', None) - # The above actually works on Python 3 - raise unittest.SkipTest("Unicode attrs legal on Py3") - - self.assertRaises( - LocationError, - traverseName, - BrokenTraversable(), '') - def testGetName(self): from zope.traversing.api import getName self.assertEqual( @@ -209,21 +192,21 @@ class TestFunctional(PlacelessSetup, unittest.TestCase): from zope.traversing.api import getPath self.assertEqual( getPath(self.item), - u'/folder/item' + '/folder/item' ) def testGetPathOfRoot(self): from zope.traversing.api import getPath self.assertEqual( getPath(self.root), - u'/', + '/', ) def testGetNameOfRoot(self): from zope.traversing.api import getName self.assertEqual( getName(self.root), - u'', + '', ) def testGetRoot(self): @@ -259,18 +242,18 @@ class TestFunctional(PlacelessSetup, unittest.TestCase): _good_locations = ( # location returned as string - (u'/xx/yy/zz', + ('/xx/yy/zz', # arguments to try in addition to the above '/xx/yy/zz', '/xx/./yy/ww/../zz', ), - (u'/xx/yy/zz', + ('/xx/yy/zz', '/xx/yy/zz', ), - (u'/xx', + ('/xx', '/xx', ), - (u'/', + ('/', '/', self.root, ), @@ -339,7 +322,7 @@ class TestFunctional(PlacelessSetup, unittest.TestCase): def test_joinPath_slashes(self): from zope.traversing.api import joinPath - path = u'/' + path = '/' args = ('/test', 'bla', '/foo', 'bar') self.assertRaises(ValueError, joinPath, path, *args) @@ -348,56 +331,51 @@ class TestFunctional(PlacelessSetup, unittest.TestCase): def test_joinPath(self): from zope.traversing.api import joinPath - path = u'/bla' + path = '/bla' args = ('foo', 'bar', 'baz', 'bone') - self.assertEqual(joinPath(path, *args), u'/bla/foo/bar/baz/bone') + self.assertEqual(joinPath(path, *args), '/bla/foo/bar/baz/bone') - path = u'bla' + path = 'bla' args = ('foo', 'bar', 'baz', 'bone') - self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') + self.assertEqual(joinPath(path, *args), 'bla/foo/bar/baz/bone') - path = u'bla' + path = 'bla' args = ('foo', 'bar/baz', 'bone') - self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') + self.assertEqual(joinPath(path, *args), 'bla/foo/bar/baz/bone') - path = u'bla/' + path = 'bla/' args = ('foo', 'bar', 'baz', 'bone') self.assertRaises(ValueError, joinPath, path, *args) def test_joinPath_normalize(self): from zope.traversing.api import joinPath - path = u'/bla' + path = '/bla' args = ('foo', 'bar', '..', 'baz', 'bone') - self.assertEqual(joinPath(path, *args), u'/bla/foo/baz/bone') + self.assertEqual(joinPath(path, *args), '/bla/foo/baz/bone') - path = u'bla' + path = 'bla' args = ('foo', 'bar', '.', 'baz', 'bone') - self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') + self.assertEqual(joinPath(path, *args), 'bla/foo/bar/baz/bone') - path = u'/' + path = '/' args = ('foo', 'bar', '.', 'baz', 'bone') - self.assertEqual(joinPath(path, *args), u'/foo/bar/baz/bone') + self.assertEqual(joinPath(path, *args), '/foo/bar/baz/bone') def test_joinPath_empty_args(self): from zope.traversing.api import joinPath path = 'abc' - self.assertEqual(joinPath(path), u'abc') + self.assertEqual(joinPath(path), 'abc') class TestStandalone(unittest.TestCase): # Unlike TestFunctional, we don't register gobs of # adapters, making these tests more self-contained - assertRaisesRegex = getattr( - unittest.TestCase, - 'assertRaisesRegex', - getattr(unittest.TestCase, 'assertRaisesRegexp')) # PY2 - def test_getParent_no_location_info(self): from zope.traversing.api import getParent test = self - class Context(object): + class Context: called = False def __conform__(self, iface): diff --git a/src/zope/traversing/tests/test_lang.py b/src/zope/traversing/tests/test_lang.py index 8590161..e667e14 100644 --- a/src/zope/traversing/tests/test_lang.py +++ b/src/zope/traversing/tests/test_lang.py @@ -38,7 +38,7 @@ class TestRequest(test_browserlanguages.TestRequest): class Test(CleanUp, unittest.TestCase): def setUp(self): - super(Test, self).setUp() + super().setUp() self.request = TestRequest("en") directlyProvides(self.request, IHTTPRequest, IAttributeAnnotatable) diff --git a/src/zope/traversing/tests/test_namespacetrversal.py b/src/zope/traversing/tests/test_namespacetrversal.py index cadbd78..1303954 100644 --- a/src/zope/traversing/tests/test_namespacetrversal.py +++ b/src/zope/traversing/tests/test_namespacetrversal.py @@ -13,7 +13,6 @@ ############################################################################## """Traversal Namespace Tests """ -import re import unittest from doctest import DocTestSuite @@ -21,7 +20,6 @@ from zope.component.testing import PlacelessSetup from zope.component.testing import setUp from zope.component.testing import tearDown from zope.location.interfaces import LocationError -from zope.testing.renormalizing import RENormalizing from zope import component from zope import interface @@ -52,7 +50,7 @@ class TestAcquire(unittest.TestCase): from zope.traversing.namespace import ExcessiveDepth @interface.implementer(ITraversable) - class Context(object): + class Context: max_call_count = 200 @@ -78,7 +76,7 @@ class TestEtc(PlacelessSetup, unittest.TestCase): def test_traverse_site_no_manager(self): test = self - class Context(object): + class Context: def __getattribute__(self, name): test.assertEqual(name, 'getSiteManager') return None @@ -91,7 +89,7 @@ class TestEtc(PlacelessSetup, unittest.TestCase): self.assertEqual((context, 'site'), ex.args) def test_traverse_site_lookup_error(self): - class Context(object): + class Context: called = False def getSiteManager(self): @@ -128,27 +126,15 @@ class TestView(unittest.TestCase): class TestVh(unittest.TestCase): - assertRaisesRegex = getattr( - unittest.TestCase, - 'assertRaisesRegex', - getattr(unittest.TestCase, 'assertRaisesRegexp')) # PY2 - def test_invalid_vh(self): with self.assertRaisesRegex(ValueError, 'Vhost directive should have the form'): - namespace.vh(None, None).traverse(u'invalid name', ()) + namespace.vh(None, None).traverse('invalid name', ()) def test_suite(): - checker = RENormalizing([ - # Python 3 includes module name in exceptions - (re.compile(r"zope.location.interfaces.LocationError"), - "LocationError"), - ]) - suite = unittest.defaultTestLoader.loadTestsFromName(__name__) suite.addTest(DocTestSuite( 'zope.traversing.namespace', - setUp=setUp, tearDown=tearDown, - checker=checker)) + setUp=setUp, tearDown=tearDown)) return suite diff --git a/src/zope/traversing/tests/test_presentation.py b/src/zope/traversing/tests/test_presentation.py index 17b9df6..b8fa189 100644 --- a/src/zope/traversing/tests/test_presentation.py +++ b/src/zope/traversing/tests/test_presentation.py @@ -31,17 +31,17 @@ class IContent(Interface): @implementer(IContent) -class Content(object): +class Content: pass -class Resource(object): +class Resource: def __init__(self, request): pass -class View(object): +class View: def __init__(self, content, request): self.content = content diff --git a/src/zope/traversing/tests/test_publicationtraverse.py b/src/zope/traversing/tests/test_publicationtraverse.py index 8218314..731d4a7 100644 --- a/src/zope/traversing/tests/test_publicationtraverse.py +++ b/src/zope/traversing/tests/test_publicationtraverse.py @@ -175,7 +175,7 @@ class TestPublicationTraverser(CleanUp, unittest.TestCase): def traversePath(self, request, ob, path): return ob - class Context(object): + class Context: called = False def __conform__(self, iface): @@ -212,17 +212,17 @@ class IContent(Interface): @implementer(IContent) -class Content(object): +class Content: pass -class View(object): +class View: def __init__(self, name): self.name = name @implementer(ITraversable) -class DummyViewTraverser(object): +class DummyViewTraverser: def __init__(self, content, request): self.content = content @@ -232,7 +232,7 @@ class DummyViewTraverser(object): @implementer(IPublishTraverse) -class DummyPublishTraverse(object): +class DummyPublishTraverse: def __init__(self, context, request): pass @@ -242,7 +242,7 @@ class DummyPublishTraverse(object): @implementer(IBrowserPublisher) -class DummyBrowserPublisher(object): +class DummyBrowserPublisher: def __init__(self, context): self.context = removeSecurityProxy(context) diff --git a/src/zope/traversing/tests/test_skin.py b/src/zope/traversing/tests/test_skin.py index 8460428..91b8d7b 100644 --- a/src/zope/traversing/tests/test_skin.py +++ b/src/zope/traversing/tests/test_skin.py @@ -22,7 +22,7 @@ from zope.publisher.interfaces.browser import IBrowserSkinType from zope.testing.cleanup import CleanUp -class FauxRequest(object): +class FauxRequest: def shiftNameToApplication(self): self.shifted = 1 @@ -37,7 +37,7 @@ directlyProvides(IFoo, IBrowserSkinType) class Test(CleanUp, unittest.TestCase): def setUp(self): - super(Test, self).setUp() + super().setUp() zope.component.provideUtility(IFoo, IBrowserSkinType, name='foo') def test(self): diff --git a/src/zope/traversing/tests/test_traverser.py b/src/zope/traversing/tests/test_traverser.py index 69ff88b..3d4a4ef 100644 --- a/src/zope/traversing/tests/test_traverser.py +++ b/src/zope/traversing/tests/test_traverser.py @@ -42,7 +42,7 @@ from zope.traversing.testing import Contained from zope.traversing.testing import contained -class ParticipationStub(object): +class ParticipationStub: def __init__(self, principal): self.principal = principal @@ -126,9 +126,9 @@ class UnrestrictedTraverseTests(PlacelessSetup, unittest.TestCase): tr = self.tr item = self.item - self.assertEqual(tr.traverse(u'/folder/item'), item) - self.assertEqual(tr.traverse(u'folder/item'), item) - self.assertEqual(tr.traverse(u'/folder/item/'), item) + self.assertEqual(tr.traverse('/folder/item'), item) + self.assertEqual(tr.traverse('folder/item'), item) + self.assertEqual(tr.traverse('/folder/item/'), item) def testSimplePathTuple(self): tr = self.tr @@ -294,32 +294,13 @@ class DefaultTraversableTests(unittest.TestCase): def testUnicodeTraversal(self): df = DefaultTraversable(object()) - self.assertRaises(LocationError, df.traverse, u'\u2019', ()) + self.assertRaises(LocationError, df.traverse, '\u2019', ()) class TestFunctions(unittest.TestCase): - def test_traversePathElement_UnicodeEncodeError_with_default(self): - test = self - - class Traversable(object): - called = False - fail = test.fail - - def traverse(self, nm, further_path): - self.called = True - u'\xff'.encode("ascii") - self.fail("Should not be reached") - - t = Traversable() - self.assertIs(self, - adapters.traversePathElement(None, None, (), - default=self, - traversable=t)) - self.assertTrue(t.called) - def test_traversePathElement_LocationError_with_default(self): - class Traversable(object): + class Traversable: called = False def traverse(self, nm, further_path): diff --git a/src/zope/traversing/tests/test_vh.py b/src/zope/traversing/tests/test_vh.py index d70c408..99e284c 100644 --- a/src/zope/traversing/tests/test_vh.py +++ b/src/zope/traversing/tests/test_vh.py @@ -16,7 +16,7 @@ import unittest -class TestRequest(object): +class TestRequest: def __init__(self, names=None, stack=None): self._traversal_stack = stack @@ -31,9 +31,9 @@ class TestRequest(object): self._traversal_stack[:] = list(stack) def setApplicationServer(self, host, proto='http', port=None): - host = "%s://%s" % (proto, host) + host = f"{proto}://{host}" if port: - host = "%s:%s" % (host, port) + host = f"{host}:{port}" self._app_server = host def setVirtualHostRoot(self, names=None): @@ -82,7 +82,7 @@ class TestVHNamespace(unittest.TestCase): request = TestRequest(['folder1'], ['folder1_1', '++']) ob = object() - vh(ob, request).traverse(u'http:www.fubarco.com:80', ()) + vh(ob, request).traverse('http:www.fubarco.com:80', ()) self.assertTrue( isinstance(request._app_server, str), repr(request._app_server)) diff --git a/src/zope/traversing/tests/test_vhosting.py b/src/zope/traversing/tests/test_vhosting.py index df35500..c049291 100644 --- a/src/zope/traversing/tests/test_vhosting.py +++ b/src/zope/traversing/tests/test_vhosting.py @@ -76,7 +76,7 @@ class RootFolder(Folder): # Copy some code from zope.pagetemplate to avoid the depedency (break circle) -class ZopeTraverser(object): +class ZopeTraverser: def __call__(self, object, path_items, econtext): request = econtext._vars_stack[0].get('request', None) @@ -97,7 +97,7 @@ zopeTraverser = ZopeTraverser() class PathExpr(expressions.PathExpr): def __init__(self, name, expr, engine): - super(PathExpr, self).__init__(name, expr, engine, zopeTraverser) + super().__init__(name, expr, engine, zopeTraverser) def Engine(): @@ -110,7 +110,7 @@ def Engine(): Engine = Engine() -class MyTalesPage(object): +class MyTalesPage: def __init__(self, source): self.source = source @@ -173,7 +173,7 @@ class TestVirtualHosting(unittest.TestCase): if len(p) == 1: env['PATH_INFO'] = p[0] - request = BrowserRequest(StringIO(u''), env) + request = BrowserRequest(StringIO(''), env) request.setPublication(DummyPublication(self.app)) setDefaultSkin(request) return request @@ -182,7 +182,7 @@ class TestVirtualHosting(unittest.TestCase): return publish(self.makeRequest(path)).response def test_request_url(self): - self.addPage('/pt', u'request/URL') + self.addPage('/pt', 'request/URL') self.verify('/pt', 'http://localhost/pt/index.html') self.verify('/++vh++/++/pt', 'http://localhost/pt/index.html') @@ -191,7 +191,7 @@ class TestVirtualHosting(unittest.TestCase): self.verify('/++vh++https:localhost:443/fake/folders/++/pt', 'https://localhost/fake/folders/pt/index.html') - self.addPage('/foo/bar/pt', u'request/URL') + self.addPage('/foo/bar/pt', 'request/URL') self.verify('/foo/bar/pt', 'http://localhost/foo/bar/pt/index.html') self.verify('/foo/bar/++vh++/++/pt', 'http://localhost/pt/index.html') @@ -201,7 +201,7 @@ class TestVirtualHosting(unittest.TestCase): 'https://localhost/fake/folders/bar/pt/index.html') def test_request_redirect(self): - self.addPage('/foo/index.html', u'Spam') + self.addPage('/foo/index.html', 'Spam') self.verifyRedirect('/foo', 'http://localhost/foo/index.html') self.verifyRedirect('/++vh++https:localhost:443/++/foo', 'https://localhost/foo/index.html') @@ -209,7 +209,7 @@ class TestVirtualHosting(unittest.TestCase): 'https://localhost/bar/index.html') def test_absolute_url(self): - self.addPage('/pt', u'context/@@absolute_url') + self.addPage('/pt', 'context/@@absolute_url') self.verify('/pt', 'http://localhost') self.verify('/++vh++/++/pt', 'http://localhost') @@ -219,7 +219,7 @@ class TestVirtualHosting(unittest.TestCase): 'https://localhost/fake/folders') self.addPage('/foo/bar/pt', - u'context/@@absolute_url') + 'context/@@absolute_url') self.verify('/foo/bar/pt', 'http://localhost/foo/bar') self.verify('/foo/bar/++vh++/++/pt', 'http://localhost') @@ -231,7 +231,7 @@ class TestVirtualHosting(unittest.TestCase): def test_absolute_url_absolute_traverse(self): self.createObject('/foo/bar/obj', MyObj()) self.addPage('/foo/bar/pt', - u'container/obj/pt/@@absolute_url') + 'container/obj/pt/@@absolute_url') self.verify('/foo/bar/pt', 'http://localhost/foo/bar/pt') self.verify('/foo/++vh++https:localhost:443/++/bar/pt', 'https://localhost/bar/pt') @@ -241,11 +241,11 @@ class TestVirtualHosting(unittest.TestCase): # Only register the checker once, so that multiple test runs pass. if Resource not in _checkers: defineChecker(Resource, NamesChecker(['__call__'])) - self.addPage(u'/foo/bar/pt', - u'context/++resource++quux') - self.verify(u'/foo/bar/pt', u'http://localhost/@@/quux') - self.verify(u'/foo/++vh++https:localhost:443/fake/folders/++/bar/pt', - u'https://localhost/fake/folders/@@/quux') + self.addPage('/foo/bar/pt', + 'context/++resource++quux') + self.verify('/foo/bar/pt', 'http://localhost/@@/quux') + self.verify('/foo/++vh++https:localhost:443/fake/folders/++/bar/pt', + 'https://localhost/fake/folders/@@/quux') def createFolders(self, path): """addFolders('/a/b/c/d') would traverse and/or create three nested @@ -283,7 +283,7 @@ class TestVirtualHosting(unittest.TestCase): self.assertEqual(result.getHeader('Location'), location) -class DummyPublication(object): +class DummyPublication: def __init__(self, app): self.app = app @@ -4,14 +4,11 @@ minversion = 3.18 envlist = lint - py27 - py35 - py36 py37 py38 py39 py310 - pypy + py311 pypy3 docs coverage @@ -41,6 +38,7 @@ deps = [testenv:isort-apply] basepython = python3 +skip_install = true commands_pre = deps = isort @@ -62,16 +60,14 @@ allowlist_externals = mkdir deps = coverage - coverage-python-version commands = mkdir -p {toxinidir}/parts/htmlcov coverage run -m zope.testrunner --test-path=src {posargs:-vc} - coverage html - coverage report -m --fail-under=99 + coverage html --ignore-errors + coverage report --ignore-errors --show-missing --fail-under=99 [coverage:run] branch = True -plugins = coverage_python_version source = zope.traversing [coverage:report] |