summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Howitz <mh@gocept.com>2022-11-29 08:34:22 +0100
committerGitHub <noreply@github.com>2022-11-29 08:34:22 +0100
commit149e734d2db75f37c72d49a5509c07de91f97074 (patch)
tree1a5da7211f6a48ecfad2fc2041fe393d8aada2f3
parent4cf2ac83e12e7722851495acb2d4c500bc9ccdcf (diff)
parent46fd0d4ef67fc95df706880542d162a42e8ac922 (diff)
downloadzope-location-149e734d2db75f37c72d49a5509c07de91f97074.tar.gz
Merge pull request #8 from zopefoundation/config-with-pure-python
* Config with pure python * Add support for Python 3.8, 3.9, 3.10, 3.11. * Drop support for Python 3.4.
-rw-r--r--.coveragerc11
-rw-r--r--.editorconfig39
-rw-r--r--.github/workflows/tests.yml66
-rw-r--r--.gitignore40
-rw-r--r--.meta.toml33
-rw-r--r--.travis.yml26
-rw-r--r--CHANGES.rst4
-rw-r--r--CONTRIBUTING.md23
-rw-r--r--MANIFEST.in23
-rw-r--r--README.rst6
-rw-r--r--bootstrap.py210
-rw-r--r--setup.cfg36
-rw-r--r--setup.py17
-rw-r--r--src/zope/__init__.py2
-rw-r--r--src/zope/location/__init__.py7
-rw-r--r--src/zope/location/interfaces.py7
-rw-r--r--src/zope/location/location.py10
-rw-r--r--src/zope/location/pickling.py8
-rw-r--r--src/zope/location/tests/__init__.py2
-rw-r--r--src/zope/location/tests/test_configure.py6
-rw-r--r--src/zope/location/tests/test_location.py38
-rw-r--r--src/zope/location/tests/test_pickling.py8
-rw-r--r--src/zope/location/tests/test_traversing.py32
-rw-r--r--src/zope/location/traversing.py7
-rw-r--r--tox.ini99
25 files changed, 412 insertions, 348 deletions
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 51ab167..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,11 +0,0 @@
-[run]
-source = zope.location
-
-[report]
-precision = 2
-exclude_lines =
- pragma: no cover
- if __name__ == '__main__':
- raise NotImplementedError
- self.fail
- raise AssertionError
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c5508b9
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,39 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+#
+# EditorConfig Configuration file, for more details see:
+# http://EditorConfig.org
+# EditorConfig is a convention description, that could be interpreted
+# by multiple editors to enforce common coding conventions for specific
+# file types
+
+# top-most EditorConfig file:
+# Will ignore other EditorConfig files in Home directory or upper tree level.
+root = true
+
+
+[*] # For All Files
+# Unix-style newlines with a newline ending every file
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+# Set default charset
+charset = utf-8
+# Indent style default
+indent_style = space
+# Max Line Length - a hard line wrap, should be disabled
+max_line_length = off
+
+[*.{py,cfg,ini}]
+# 4 space indentation
+indent_size = 4
+
+[*.{yml,zpt,pt,dtml,zcml}]
+# 2 space indentation
+indent_size = 2
+
+[{Makefile,.gitmodules}]
+# Tab indentation (no size specified, but view as 4 spaces)
+indent_style = tab
+indent_size = unset
+tab_width = unset
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..3c40fa5
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,66 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+name: tests
+
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: '0 12 * * 0' # run once a week on Sunday
+ # Allow to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ build:
+ strategy:
+ # We want to see all failures:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu
+ 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"]
+ - ["3.11", "py311"]
+ - ["pypy-2.7", "pypy"]
+ - ["pypy-3.7", "pypy3"]
+ - ["3.9", "docs"]
+ - ["3.9", "coverage"]
+
+ runs-on: ${{ matrix.os }}-latest
+ 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@v3
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.config[0] }}
+ - name: Pip cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-${{ matrix.config[0] }}-
+ ${{ runner.os }}-pip-
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install tox
+ - name: Test
+ run: tox -e ${{ matrix.config[1] }}
+ - name: Coverage
+ if: matrix.config[1] == 'coverage'
+ run: |
+ pip install coveralls coverage-python-version
+ coveralls --service=github
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index af1fd06..1f321f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,32 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+*.dll
+*.egg-info/
+*.profraw
*.pyc
-__pycache__
-*.egg-info
-.installed.cfg
-bin
-develop-eggs
-eggs
-parts
-docs/_build
-.tox
+*.pyo
+*.so
.coverage
-nosetests.xml
+.coverage.*
+.eggs/
+.installed.cfg
+.mr.developer.cfg
+.tox/
+.vscode/
+__pycache__/
+bin/
+build/
coverage.xml
-htmlcov/
+develop-eggs/
+develop/
+dist/
+docs/_build
+eggs/
+etc/
+lib/
+lib64
+log/
+parts/
+pyvenv.cfg
+testing.log
+var/
diff --git a/.meta.toml b/.meta.toml
new file mode 100644
index 0000000..ef6abe6
--- /dev/null
+++ b/.meta.toml
@@ -0,0 +1,33 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+[meta]
+template = "pure-python"
+commit-id = "90a5c439bc150722699aff9fa7cd96f6e59db536"
+
+[python]
+with-macos = false
+with-windows = false
+with-pypy = true
+with-future-python = false
+with-legacy-python = true
+with-docs = true
+with-sphinx-doctests = true
+
+[tox]
+use-flake8 = true
+
+[coverage]
+fail-under = 100
+
+[flake8]
+additional-config = [
+ "# F401 imported but unused",
+ "per-file-ignores =",
+ " src/zope/location/__init__.py: F401",
+ ]
+
+[manifest]
+additional-rules = [
+ "recursive-include docs *.bat",
+ "recursive-include src *.zcml",
+ ]
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b2ff47d..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-language: python
-sudo: false
-python:
- - 2.7
- - 3.4
- - 3.5
- - 3.6
- - pypy
- - pypy3
-matrix:
- include:
- - python: "3.7"
- dist: xenial
- sudo: true
-install:
- - pip install -U pip setuptools
- - pip install -U coverage coveralls
- - pip install -U -e .[test,docs]
-script:
- - coverage run -m zope.testrunner --test-path=src
- - coverage run -a -m sphinx -b doctest -d docs/_build/doctrees docs docs/_build/doctest
-after_success:
- - coveralls
-notifications:
- email: false
-cache: pip
diff --git a/CHANGES.rst b/CHANGES.rst
index 4850898..f98e012 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -5,7 +5,9 @@
4.3 (unreleased)
================
-- Nothing changed yet.
+- Add support for Python 3.8, 3.9, 3.10, 3.11.
+
+- Drop support for Python 3.4.
4.2 (2018-10-09)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..31d95f0
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+<!--
+Generated from:
+https://github.com/zopefoundation/meta/tree/master/config/pure-python
+-->
+# Contributing to zopefoundation projects
+
+The projects under the zopefoundation GitHub organization are open source and
+welcome contributions in different forms:
+
+* bug reports
+* code improvements and bug fixes
+* documentation improvements
+* pull request reviews
+
+For any changes in the repository besides trivial typo fixes you are required
+to sign the contributor agreement. See
+https://www.zope.dev/developer/becoming-a-committer.html for details.
+
+Please visit our [Developer
+Guidelines](https://www.zope.dev/developer/guidelines.html) if you'd like to
+contribute code changes and our [guidelines for reporting
+bugs](https://www.zope.dev/developer/reporting-bugs.html) if you want to file a
+bug report.
diff --git a/MANIFEST.in b/MANIFEST.in
index 312397b..1762883 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,19 +1,16 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+include *.md
include *.rst
include *.txt
-include *.py
-include .coveragerc
include buildout.cfg
include tox.ini
-include .travis.yml
-recursive-include docs *
-recursive-include src *
+recursive-include docs *.py
+recursive-include docs *.rst
+recursive-include docs *.txt
+recursive-include docs Makefile
-exclude .coverage
-exclude nosetests.xml
-exclude src/coverage.xml
-
-global-exclude *.dll
-global-exclude *.pyc
-global-exclude *.pyo
-global-exclude *.so
+recursive-include src *.py
+recursive-include docs *.bat
+recursive-include src *.zcml
diff --git a/README.rst b/README.rst
index 11bb4f9..ae6526f 100644
--- a/README.rst
+++ b/README.rst
@@ -10,8 +10,8 @@
:target: https://pypi.org/project/zope.location/
:alt: Supported Python versions
-.. image:: https://travis-ci.com/zopefoundation/zope.location.svg?branch=master
- :target: https://travis-ci.com/zopefoundation/zope.location
+.. image:: https://github.com/zopefoundation/zope.location/actions/workflows/tests.yml/badge.svg
+ :target: https://github.com/zopefoundation/zope.location/actions/workflows/tests.yml
.. image:: https://coveralls.io/repos/github/zopefoundation/zope.location/badge.svg?branch=master
:target: https://coveralls.io/github/zopefoundation/zope.location?branch=master
@@ -20,7 +20,7 @@
:target: http://zopelocation.readthedocs.org/en/latest/
:alt: Documentation Status
-In Zope3, "locations" are special objects that have a structural
+In Zope 3, "locations" are special objects that have a structural
location, indicated with ``__name__`` and ``__parent__`` attributes.
See `zope.container <https://zopecontainer.readthedocs.io/en/latest>`_
diff --git a/bootstrap.py b/bootstrap.py
deleted file mode 100644
index a459921..0000000
--- a/bootstrap.py
+++ /dev/null
@@ -1,210 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Bootstrap a buildout-based project
-
-Simply run this script in a directory containing a buildout.cfg.
-The script accepts buildout command-line options, so you can
-use the -c option to specify an alternate configuration file.
-"""
-
-import os
-import shutil
-import sys
-import tempfile
-
-from optparse import OptionParser
-
-__version__ = '2015-07-01'
-# See zc.buildout's changelog if this version is up to date.
-
-tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
-
-usage = '''\
-[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
-
-Bootstraps a buildout-based project.
-
-Simply run this script in a directory containing a buildout.cfg, using the
-Python that you want bin/buildout to use.
-
-Note that by using --find-links to point to local resources, you can keep
-this script from going over the network.
-'''
-
-parser = OptionParser(usage=usage)
-parser.add_option("--version",
- action="store_true", default=False,
- help=("Return bootstrap.py version."))
-parser.add_option("-t", "--accept-buildout-test-releases",
- dest='accept_buildout_test_releases',
- action="store_true", default=False,
- help=("Normally, if you do not specify a --version, the "
- "bootstrap script and buildout gets the newest "
- "*final* versions of zc.buildout and its recipes and "
- "extensions for you. If you use this flag, "
- "bootstrap and buildout will get the newest releases "
- "even if they are alphas or betas."))
-parser.add_option("-c", "--config-file",
- help=("Specify the path to the buildout configuration "
- "file to be used."))
-parser.add_option("-f", "--find-links",
- help=("Specify a URL to search for buildout releases"))
-parser.add_option("--allow-site-packages",
- action="store_true", default=False,
- help=("Let bootstrap.py use existing site packages"))
-parser.add_option("--buildout-version",
- help="Use a specific zc.buildout version")
-parser.add_option("--setuptools-version",
- help="Use a specific setuptools version")
-parser.add_option("--setuptools-to-dir",
- help=("Allow for re-use of existing directory of "
- "setuptools versions"))
-
-options, args = parser.parse_args()
-if options.version:
- print("bootstrap.py version %s" % __version__)
- sys.exit(0)
-
-
-######################################################################
-# load/install setuptools
-
-try:
- from urllib.request import urlopen
-except ImportError:
- from urllib2 import urlopen
-
-ez = {}
-if os.path.exists('ez_setup.py'):
- exec(open('ez_setup.py').read(), ez)
-else:
- exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
-
-if not options.allow_site_packages:
- # ez_setup imports site, which adds site packages
- # this will remove them from the path to ensure that incompatible versions
- # of setuptools are not in the path
- import site
- # inside a virtualenv, there is no 'getsitepackages'.
- # We can't remove these reliably
- if hasattr(site, 'getsitepackages'):
- for sitepackage_path in site.getsitepackages():
- # Strip all site-packages directories from sys.path that
- # are not sys.prefix; this is because on Windows
- # sys.prefix is a site-package directory.
- if sitepackage_path != sys.prefix:
- sys.path[:] = [x for x in sys.path
- if sitepackage_path not in x]
-
-setup_args = dict(to_dir=tmpeggs, download_delay=0)
-
-if options.setuptools_version is not None:
- setup_args['version'] = options.setuptools_version
-if options.setuptools_to_dir is not None:
- setup_args['to_dir'] = options.setuptools_to_dir
-
-ez['use_setuptools'](**setup_args)
-import setuptools
-import pkg_resources
-
-# This does not (always?) update the default working set. We will
-# do it.
-for path in sys.path:
- if path not in pkg_resources.working_set.entries:
- pkg_resources.working_set.add_entry(path)
-
-######################################################################
-# Install buildout
-
-ws = pkg_resources.working_set
-
-setuptools_path = ws.find(
- pkg_resources.Requirement.parse('setuptools')).location
-
-# Fix sys.path here as easy_install.pth added before PYTHONPATH
-cmd = [sys.executable, '-c',
- 'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
- 'from setuptools.command.easy_install import main; main()',
- '-mZqNxd', tmpeggs]
-
-find_links = os.environ.get(
- 'bootstrap-testing-find-links',
- options.find_links or
- ('http://downloads.buildout.org/'
- if options.accept_buildout_test_releases else None)
- )
-if find_links:
- cmd.extend(['-f', find_links])
-
-requirement = 'zc.buildout'
-version = options.buildout_version
-if version is None and not options.accept_buildout_test_releases:
- # Figure out the most recent final version of zc.buildout.
- import setuptools.package_index
- _final_parts = '*final-', '*final'
-
- def _final_version(parsed_version):
- try:
- return not parsed_version.is_prerelease
- except AttributeError:
- # Older setuptools
- for part in parsed_version:
- if (part[:1] == '*') and (part not in _final_parts):
- return False
- return True
-
- index = setuptools.package_index.PackageIndex(
- search_path=[setuptools_path])
- if find_links:
- index.add_find_links((find_links,))
- req = pkg_resources.Requirement.parse(requirement)
- if index.obtain(req) is not None:
- best = []
- bestv = None
- for dist in index[req.project_name]:
- distv = dist.parsed_version
- if _final_version(distv):
- if bestv is None or distv > bestv:
- best = [dist]
- bestv = distv
- elif distv == bestv:
- best.append(dist)
- if best:
- best.sort()
- version = best[-1].version
-if version:
- requirement = '=='.join((requirement, version))
-cmd.append(requirement)
-
-import subprocess
-if subprocess.call(cmd) != 0:
- raise Exception(
- "Failed to execute command:\n%s" % repr(cmd)[1:-1])
-
-######################################################################
-# Import and run buildout
-
-ws.add_entry(tmpeggs)
-ws.require(requirement)
-import zc.buildout.buildout
-
-if not [a for a in args if '=' not in a]:
- args.append('bootstrap')
-
-# if -c was provided, we push it back into args for buildout' main function
-if options.config_file is not None:
- args[0:0] = ['-c', options.config_file]
-
-zc.buildout.buildout.main(args)
-shutil.rmtree(tmpeggs)
diff --git a/setup.cfg b/setup.cfg
index e9ca612..b86541d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,14 +1,28 @@
-[nosetests]
-nocapture=1
-cover-package=zope.location
-cover-erase=1
-with-doctest=0
-where=src
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
+[bdist_wheel]
+universal = 1
-[aliases]
-dev = develop easy_install zope.location[testing]
-docs = easy_install zope.location[docs]
+[flake8]
+doctests = 1
+# F401 imported but unused
+per-file-ignores =
+ src/zope/location/__init__.py: F401
+[check-manifest]
+ignore =
+ .editorconfig
+ .meta.toml
+ docs/_build/html/_sources/*
+ docs/_build/doctest/*
-[bdist_wheel]
-universal = 1
+[isort]
+force_single_line = True
+combine_as_imports = True
+sections = FUTURE,STDLIB,THIRDPARTY,ZOPE,FIRSTPARTY,LOCALFOLDER
+known_third_party = six, docutils, pkg_resources
+known_zope =
+known_first_party =
+default_section = ZOPE
+line_length = 79
+lines_after_imports = 2
diff --git a/setup.py b/setup.py
index 4c069f6..1f4fda8 100644
--- a/setup.py
+++ b/setup.py
@@ -19,12 +19,16 @@
"""Setup for zope.location package
"""
import os
-from setuptools import setup, find_packages
+
+from setuptools import find_packages
+from setuptools import setup
+
def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()
+
ZCML_REQUIRES = [
'zope.configuration',
]
@@ -41,7 +45,7 @@ TESTS_REQUIRE = ZCML_REQUIRES + COMPONENT_REQUIRES + [
DOCS_REQUIRE = [
'Sphinx',
'repoze.sphinx.autointerface',
-] + ZCML_REQUIRES + COMPONENT_REQUIRES # doctest snippets need these
+] + ZCML_REQUIRES + COMPONENT_REQUIRES # doctest snippets need these
setup(name='zope.location',
version='4.3.dev0',
@@ -64,10 +68,13 @@ setup(name='zope.location',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.4',
'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',
@@ -78,7 +85,7 @@ setup(name='zope.location',
url='http://github.com/zopefoundation/zope.location/',
packages=find_packages('src'),
package_dir={'': 'src'},
- namespace_packages=['zope',],
+ namespace_packages=['zope', ],
install_requires=[
'setuptools',
'zope.interface>=4.0.2',
@@ -94,4 +101,4 @@ setup(name='zope.location',
test_suite='zope.location.tests',
include_package_data=True,
zip_safe=False,
-)
+ )
diff --git a/src/zope/__init__.py b/src/zope/__init__.py
index 2cdb0e4..656dc0f 100644
--- a/src/zope/__init__.py
+++ b/src/zope/__init__.py
@@ -1 +1 @@
-__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
+__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
diff --git a/src/zope/location/__init__.py b/src/zope/location/__init__.py
index 104c1ac..ca0e267 100644
--- a/src/zope/location/__init__.py
+++ b/src/zope/location/__init__.py
@@ -16,5 +16,8 @@
__docformat__ = 'restructuredtext'
from zope.location.interfaces import ILocation
-from zope.location.location import Location, locate, LocationIterator
-from zope.location.location import inside, LocationProxy
+from zope.location.location import Location
+from zope.location.location import LocationIterator
+from zope.location.location import LocationProxy
+from zope.location.location import inside
+from zope.location.location import locate
diff --git a/src/zope/location/interfaces.py b/src/zope/location/interfaces.py
index b490a09..c706934 100644
--- a/src/zope/location/interfaces.py
+++ b/src/zope/location/interfaces.py
@@ -15,8 +15,8 @@
"""
__docformat__ = 'restructuredtext'
-from zope.interface import Interface
from zope.interface import Attribute
+from zope.interface import Interface
from zope.schema import TextLine
@@ -52,9 +52,11 @@ class ILocation(Interface):
# used within this package, but is depended upon by external
# consumers.
+
class IContained(ILocation):
"""Objects contained in containers."""
+
class ILocationInfo(Interface):
"""Provides supplemental information for located objects.
@@ -121,12 +123,13 @@ class IRoot(Interface):
class LocationError(KeyError, LookupError):
"""There is no object for a given location."""
+
# Soft dependency on zope.component.
#
# Also, these interfaces used to be defined here directly, so this provides
# backward-compatibility
try:
from zope.component.interfaces import ISite
-except ImportError: # pragma: no cover
+except ImportError: # pragma: no cover
class ISite(Interface):
pass
diff --git a/src/zope/location/location.py b/src/zope/location/location.py
index 3554c51..857ad6f 100644
--- a/src/zope/location/location.py
+++ b/src/zope/location/location.py
@@ -23,6 +23,7 @@ from zope.proxy.decorator import DecoratorSpecificationDescriptor
from zope.location.interfaces import ILocation
+
@implementer(ILocation)
class Location(object):
"""Mix-in that implements ILocation.
@@ -70,6 +71,7 @@ def inside(l1, l2):
l1 = getattr(l1, '__parent__', None)
return False
+
class ClassAndInstanceDescr(object):
def __init__(self, *args):
@@ -93,8 +95,8 @@ class LocationProxy(ProxyBase):
__doc__ = ClassAndInstanceDescr(
lambda inst: getProxiedObject(inst).__doc__,
- lambda cls, __doc__ = __doc__: __doc__,
- )
+ lambda cls, __doc__=__doc__: __doc__,
+ )
def __new__(self, ob, container=None, name=None):
return ProxyBase.__new__(self, ob)
@@ -111,10 +113,10 @@ class LocationProxy(ProxyBase):
def __setattr__(self, name, value):
if name in self.__slots__ + getattr(ProxyBase, '__slots__', ()):
- #('_wrapped', '__parent__', '__name__'):
+ # ('_wrapped', '__parent__', '__name__'):
try:
return object.__setattr__(self, name, value)
- except TypeError: #pragma NO COVER C Optimization
+ except TypeError: # pragma NO COVER C Optimization
return ProxyBase.__setattr__(self, name, value)
return ProxyBase.__setattr__(self, name, value)
diff --git a/src/zope/location/pickling.py b/src/zope/location/pickling.py
index 46e6217..47181eb 100644
--- a/src/zope/location/pickling.py
+++ b/src/zope/location/pickling.py
@@ -16,11 +16,14 @@
__docformat__ = 'restructuredtext'
from zope.interface import implementer
+
from zope.location.location import inside
+
try:
- from zope.copy.interfaces import ICopyHook, ResumeCopy
-except ImportError: # pragma: no cover
+ from zope.copy.interfaces import ICopyHook
+ from zope.copy.interfaces import ResumeCopy
+except ImportError: # pragma: no cover
raise NotImplementedError("zope.location.pickling is not supported "
"because zope.copy is not available")
@@ -30,6 +33,7 @@ class LocationCopyHook(object):
"""Copy hook to preserve copying referenced objects that are not
located inside object that's being copied.
"""
+
def __init__(self, context):
self.context = context
diff --git a/src/zope/location/tests/__init__.py b/src/zope/location/tests/__init__.py
index d3173e6..5bb534f 100644
--- a/src/zope/location/tests/__init__.py
+++ b/src/zope/location/tests/__init__.py
@@ -1 +1 @@
-#package
+# package
diff --git a/src/zope/location/tests/test_configure.py b/src/zope/location/tests/test_configure.py
index ec31efb..332faa5 100644
--- a/src/zope/location/tests/test_configure.py
+++ b/src/zope/location/tests/test_configure.py
@@ -15,14 +15,16 @@
"""
import unittest
+
class Test_ZCML_loads(unittest.TestCase):
def test_it(self):
- import zope.component # no registrations made if not present
+ import zope.component # no registrations made if not present
ADAPTERS_REGISTERED = 4
+ from zope.configuration.xmlconfig import XMLConfig
from zope.configuration.xmlconfig import _clearContext
from zope.configuration.xmlconfig import _getContext
- from zope.configuration.xmlconfig import XMLConfig
+
import zope.location
_clearContext()
diff --git a/src/zope/location/tests/test_location.py b/src/zope/location/tests/test_location.py
index ea60099..635a2d9 100644
--- a/src/zope/location/tests/test_location.py
+++ b/src/zope/location/tests/test_location.py
@@ -18,11 +18,13 @@ class ConformsToILocation(object):
def test_class_conforms_to_ILocation(self):
from zope.interface.verify import verifyClass
+
from zope.location.interfaces import ILocation
verifyClass(ILocation, self._getTargetClass())
def test_instance_conforms_to_ILocation(self):
from zope.interface.verify import verifyObject
+
from zope.location.interfaces import ILocation
verifyObject(ILocation, self._makeOne())
@@ -75,7 +77,9 @@ class Test_located(unittest.TestCase):
def test_wo_name_obj_implements_ILocation(self):
from zope.interface import implementer
+
from zope.location.interfaces import ILocation
+
@implementer(ILocation)
class Dummy(object):
__parent__ = None
@@ -88,11 +92,14 @@ class Test_located(unittest.TestCase):
def test_w_name_adaptable_to_ILocation(self):
from zope.interface.interface import adapter_hooks
+
from zope.location.interfaces import ILocation
_hooked = []
+
def _hook(iface, obj):
_hooked.append((iface, obj))
return obj
+
class Dummy(object):
pass
parent = Dummy()
@@ -206,13 +213,16 @@ class ClassAndInstanceDescrTests(unittest.TestCase):
def _makeScaffold(self):
_inst_called = []
+
def _inst(*args, **kw):
_inst_called.append((args, kw))
return 'INST'
_class_called = []
+
def _class(*args, **kw):
_class_called.append((args, kw))
return 'CLASS'
+
class Foo(object):
descr = self._makeOne(_inst, _class)
return Foo, _class_called, _inst_called
@@ -220,7 +230,7 @@ class ClassAndInstanceDescrTests(unittest.TestCase):
def test_fetched_from_class(self):
Foo, _class_called, _inst_called = self._makeScaffold()
self.assertEqual(Foo.descr, 'CLASS')
- self.assertEqual(_class_called, [((Foo,),{})])
+ self.assertEqual(_class_called, [((Foo,), {})])
self.assertEqual(_inst_called, [])
def test_fetched_from_instance(self):
@@ -228,7 +238,7 @@ class ClassAndInstanceDescrTests(unittest.TestCase):
foo = Foo()
self.assertEqual(foo.descr, 'INST')
self.assertEqual(_class_called, [])
- self.assertEqual(_inst_called, [((foo,),{})])
+ self.assertEqual(_inst_called, [((foo,), {})])
_MARKER = object()
@@ -250,13 +260,13 @@ class LocationProxyTests(unittest.TestCase, ConformsToILocation):
return self._getTargetClass()(obj, container, name)
def test_ctor_defaults(self):
- dummy = object() # can't setattr
+ dummy = object() # can't setattr
proxy = self._makeOne(dummy)
self.assertEqual(proxy.__parent__, None)
self.assertEqual(proxy.__name__, None)
def test_ctor_explicit(self):
- dummy = object() # can't setattr
+ dummy = object() # can't setattr
parent = object()
proxy = self._makeOne(dummy, parent, 'name')
self.assertTrue(proxy.__parent__ is parent)
@@ -279,19 +289,18 @@ class LocationProxyTests(unittest.TestCase, ConformsToILocation):
def test___doc___from_derived_class(self):
klass = self._getTargetClass()
+
class Derived(klass):
"""DERIVED"""
self.assertEqual(Derived.__doc__, 'DERIVED')
def test___doc___from_target_class(self):
- klass = self._getTargetClass()
class Context(object):
"""CONTEXT"""
proxy = self._makeOne(Context())
self.assertEqual(proxy.__doc__, 'CONTEXT')
def test___doc___from_target_instance(self):
- klass = self._getTargetClass()
class Context(object):
"""CONTEXT"""
context = Context()
@@ -309,6 +318,7 @@ class LocationProxyTests(unittest.TestCase, ConformsToILocation):
def test___reduce___via_pickling(self):
import pickle
+
class Context(object):
def __reduce__(self):
raise AssertionError("This is not called")
@@ -323,10 +333,13 @@ class LocationProxyTests(unittest.TestCase, ConformsToILocation):
from zope.interface import implementer
from zope.interface import providedBy
from zope.interface import provider
+
class IProxyFactory(Interface):
pass
+
class IProxy(Interface):
pass
+
@provider(IProxyFactory)
@implementer(IProxy)
class Foo(self._getTargetClass()):
@@ -338,26 +351,34 @@ class LocationProxyTests(unittest.TestCase, ConformsToILocation):
from zope.interface import implementer
from zope.interface import providedBy
from zope.interface import provider
+
from zope.location.interfaces import ILocation
+
class IProxyFactory(Interface):
pass
+
class IProxy(Interface):
pass
+
class IContextFactory(Interface):
pass
+
class IContext(Interface):
pass
+
@provider(IProxyFactory)
@implementer(IProxy)
class Proxy(self._getTargetClass()):
pass
+
@provider(IContextFactory)
@implementer(IContext)
class Context(object):
pass
context = Context()
proxy = Proxy(context)
- self.assertEqual(list(providedBy(proxy)), [IContext, IProxy, ILocation])
+ self.assertEqual(list(providedBy(proxy)), [
+ IContext, IProxy, ILocation])
class LocationPyProxyTests(LocationProxyTests):
@@ -368,7 +389,7 @@ class LocationPyProxyTests(LocationProxyTests):
'zope.proxy.decorator'):
try:
del sys.modules[mod]
- except KeyError: # pragma: no cover
+ except KeyError: # pragma: no cover
pass
import zope.proxy
self.orig = (zope.proxy.ProxyBase,
@@ -390,7 +411,6 @@ class LocationPyProxyTests(LocationProxyTests):
zope.proxy.removeAllProxies = zope.proxy.py_removeAllProxies
zope.proxy.non_overridable = zope.proxy.PyNonOverridable
-
def tearDown(self):
import zope.proxy
(zope.proxy.ProxyBase,
diff --git a/src/zope/location/tests/test_pickling.py b/src/zope/location/tests/test_pickling.py
index 063c9f6..bd1923a 100644
--- a/src/zope/location/tests/test_pickling.py
+++ b/src/zope/location/tests/test_pickling.py
@@ -14,8 +14,6 @@
import unittest
-import zope.copy
-
class LocationCopyHookTests(unittest.TestCase):
def _getTargetClass(self):
@@ -28,17 +26,18 @@ class LocationCopyHookTests(unittest.TestCase):
return self._getTargetClass()(obj)
def test_class_conforms_to_ICopyHook(self):
- from zope.interface.verify import verifyClass
from zope.copy.interfaces import ICopyHook
+ from zope.interface.verify import verifyClass
verifyClass(ICopyHook, self._getTargetClass())
def test_instance_conforms_to_ICopyHook(self):
- from zope.interface.verify import verifyObject
from zope.copy.interfaces import ICopyHook
+ from zope.interface.verify import verifyObject
verifyObject(ICopyHook, self._makeOne())
def test___call___w_context_inside_toplevel(self):
from zope.copy.interfaces import ResumeCopy
+
class Dummy(object):
__parent__ = __name__ = None
top_level = Dummy()
@@ -56,6 +55,5 @@ class LocationCopyHookTests(unittest.TestCase):
self.assertTrue(hook(top_level, object()) is context)
-
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
diff --git a/src/zope/location/tests/test_traversing.py b/src/zope/location/tests/test_traversing.py
index ed82e4b..f4505be 100644
--- a/src/zope/location/tests/test_traversing.py
+++ b/src/zope/location/tests/test_traversing.py
@@ -18,17 +18,19 @@ class ConformsToILocationInfo(object):
def test_class_conforms_to_ILocationInfo(self):
from zope.interface.verify import verifyClass
+
from zope.location.interfaces import ILocationInfo
verifyClass(ILocationInfo, self._getTargetClass())
def test_instance_conforms_to_ILocationInfo(self):
from zope.interface.verify import verifyObject
+
from zope.location.interfaces import ILocationInfo
verifyObject(ILocationInfo, self._makeOne())
class LocationPhysicallyLocatableTests(
- unittest.TestCase, ConformsToILocationInfo):
+ unittest.TestCase, ConformsToILocationInfo):
def _getTargetClass(self):
from zope.location.traversing import LocationPhysicallyLocatable
@@ -51,7 +53,9 @@ class LocationPhysicallyLocatableTests(
def test_getRoot_wo_cycle(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = None
one = Dummy()
@@ -87,7 +91,9 @@ class LocationPhysicallyLocatableTests(
def test_getPath_at_root(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -97,7 +103,9 @@ class LocationPhysicallyLocatableTests(
def test_getPath_wo_cycle(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -137,7 +145,9 @@ class LocationPhysicallyLocatableTests(
def test_getParent_at_root(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -147,7 +157,9 @@ class LocationPhysicallyLocatableTests(
def test_getParent_wo_cycle(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -173,7 +185,9 @@ class LocationPhysicallyLocatableTests(
def test_getParents_at_root(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -183,7 +197,9 @@ class LocationPhysicallyLocatableTests(
def test_getParents_wo_cycle(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -214,8 +230,11 @@ class LocationPhysicallyLocatableTests(
self.assertEqual(proxy.getName(), 'name')
def test_getNearestSite_context_is_site(self):
- from zope.location.interfaces import ISite # zope.component, if present
from zope.interface import directlyProvides
+
+ from zope.location.interfaces import \
+ ISite # zope.component, if present
+
class Dummy(object):
pass
context = Dummy()
@@ -224,9 +243,12 @@ class LocationPhysicallyLocatableTests(
self.assertTrue(proxy.getNearestSite() is context)
def test_getNearestSite_ancestor_is_site(self):
- from zope.location.interfaces import ISite # zope.component, if present
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+ from zope.location.interfaces import \
+ ISite # zope.component, if present
+
class Dummy(object):
pass
one = Dummy()
@@ -242,7 +264,9 @@ class LocationPhysicallyLocatableTests(
def test_getNearestSite_no_site(self):
from zope.interface import directlyProvides
+
from zope.location.interfaces import IRoot
+
class Dummy(object):
__parent__ = __name__ = None
one = Dummy()
@@ -258,7 +282,7 @@ class LocationPhysicallyLocatableTests(
class RootPhysicallyLocatableTests(
- unittest.TestCase, ConformsToILocationInfo):
+ unittest.TestCase, ConformsToILocationInfo):
def _getTargetClass(self):
from zope.location.traversing import RootPhysicallyLocatable
diff --git a/src/zope/location/traversing.py b/src/zope/location/traversing.py
index 2e6836c..0b49c9d 100644
--- a/src/zope/location/traversing.py
+++ b/src/zope/location/traversing.py
@@ -19,13 +19,14 @@ from zope.interface import implementer
from zope.location.interfaces import ILocationInfo
from zope.location.interfaces import IRoot
-from zope.location.interfaces import ISite # zope.component, if present
+from zope.location.interfaces import ISite # zope.component, if present
@implementer(ILocationInfo)
class LocationPhysicallyLocatable(object):
"""Provide location information for location objects
"""
+
def __init__(self, context):
self.context = context
@@ -84,7 +85,7 @@ class LocationPhysicallyLocatable(object):
# from zope.traversing.
parents = []
w = self.context
- while 1:
+ while True:
w = getattr(w, '__parent__', None)
if w is None:
break
@@ -110,6 +111,7 @@ class LocationPhysicallyLocatable(object):
return parent
return self.getRoot()
+
@implementer(ILocationInfo)
class RootPhysicallyLocatable(object):
"""Provide location information for the root object
@@ -118,6 +120,7 @@ class RootPhysicallyLocatable(object):
for parents and nearest sites, so we are only working with context
object, knowing that its the root object already.
"""
+
def __init__(self, context):
self.context = context
diff --git a/tox.ini b/tox.ini
index 56dbd2b..8ebc319 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,39 +1,92 @@
+# Generated from:
+# https://github.com/zopefoundation/meta/tree/master/config/pure-python
[tox]
+minversion = 3.18
envlist =
-# Jython support pending 2.7 support, due 2012-07-15 or so. See:
-# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
-# py27,jython,pypy,coverage
- py27,py34,py35,py36,py37,pypy,pypy3,coverage
+ lint
+ py27
+ py35
+ py36
+ py37
+ py38
+ py39
+ py310
+ py311
+ pypy
+ pypy3
+ docs
+ coverage
[testenv]
-commands =
- zope-testrunner --test-path=src []
- sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+usedevelop = true
deps =
- .[test,docs]
-
-[testenv:jython]
commands =
- jython setup.py test -q
+ zope-testrunner --test-path=src {posargs:-vc}
+ !py27-!pypy: sphinx-build -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+extras =
+ test
+ docs
-[testenv:coverage]
-usedevelop = true
-basepython =
- python3.7
+[testenv:lint]
+basepython = python3
+skip_install = true
commands =
- coverage run -m zope.testrunner --test-path=src
- coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
- coverage report
+ isort --check-only --diff {toxinidir}/src {toxinidir}/setup.py
+ flake8 src setup.py
+ check-manifest
+ check-python-versions
deps =
- {[testenv]deps}
- coverage
+ check-manifest
+ check-python-versions >= 0.19.1
+ wheel
+ flake8
+ isort
+[testenv:isort-apply]
+basepython = python3
+commands_pre =
+deps =
+ isort
+commands =
+ isort {toxinidir}/src {toxinidir}/setup.py []
[testenv:docs]
-basepython =
- python3.7
+basepython = python3
+skip_install = false
+commands_pre =
commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
+
+[testenv:coverage]
+basepython = python3
+allowlist_externals =
+ mkdir
deps =
- .[docs]
+ coverage
+ coverage-python-version
+commands =
+ mkdir -p {toxinidir}/parts/htmlcov
+ coverage run -m zope.testrunner --test-path=src {posargs:-vc}
+ coverage run -a -m sphinx -b doctest -d {envdir}/.cache/doctrees docs {envdir}/.cache/doctest
+ coverage html
+ coverage report -m --fail-under=100
+
+[coverage:run]
+branch = True
+plugins = coverage_python_version
+source = zope.location
+
+[coverage:report]
+precision = 2
+exclude_lines =
+ pragma: no cover
+ pragma: nocover
+ except ImportError:
+ raise NotImplementedError
+ if __name__ == '__main__':
+ self.fail
+ raise AssertionError
+
+[coverage:html]
+directory = parts/htmlcov