diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..af40312
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,6 @@
+[run]
+source = src
+
+[report]
+exclude_lines =
+ pragma: no cover
diff --git a/.gitignore b/.gitignore
index 5149542..6bacfe5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,5 @@ build/
dist/
*.egg-info/
.tox/
+.coverage
+htmlcov/
diff --git a/.travis.yml b/.travis.yml
index 02dca11..dc7e4b8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,20 @@
language: python
+sudo: false
python:
- 2.7
+ - pypy-5.4.1
+ - 3.5
+ - 3.6
install:
- - pip install .
+ - pip install -U pip setuptools
+ - pip install -U coverage coveralls
+ - pip install -U -e .[test]
script:
- - python setup.py test -q
+ - coverage run -m zope.testrunner --test-path=src --auto-color --auto-progress
notifications:
email: false
+after_success:
+ - coveralls
+cache: pip
+before_cache:
+ - rm -f $HOME/.cache/pip/log/debug.log
diff --git a/CHANGES.txt b/CHANGES.rst
similarity index 81%
rename from CHANGES.txt
rename to CHANGES.rst
index ad26321..3a52fd6 100644
--- a/CHANGES.txt
+++ b/CHANGES.rst
@@ -2,9 +2,13 @@
CHANGES
=======
-3.5.2 (unreleased)
+4.0.0 (unreleased)
------------------
+- Add support for Python 3.5 and 3.6 and PyPy.
+
+- Removed support for Python 2.6.
+
- Added `tox.ini` and manifest.
- Removed zope.app.testing dependency.
diff --git a/MANIFEST.in b/MANIFEST.in
index 61dad0f..de58807 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,7 +2,7 @@ include *.rst
include *.txt
include tox.ini
include bootstrap.py
-include buildout.cfg
+include *.cfg
recursive-include src *
diff --git a/README.txt b/README.rst
similarity index 100%
rename from README.txt
rename to README.rst
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..2a9acf1
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal = 1
diff --git a/setup.py b/setup.py
index ed8a981..3bff94b 100644
--- a/setup.py
+++ b/setup.py
@@ -17,55 +17,70 @@
# Zope Toolkit policies as described by this documentation.
##############################################################################
"""Setup for zope.app.dependable package
-
-$Id$
"""
import os
from setuptools import setup, find_packages
def read(*rnames):
- return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+ with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
+ return f.read()
+
+version = '4.0.0.dev0'
+tests_require = [
+ 'zope.container',
+ 'zope.testing',
+ 'zope.testrunner',
+]
setup(name='zope.app.dependable',
- version = '3.5.2dev',
+ version=version,
author='Zope Corporation and Contributors',
author_email='zope-dev@zope.org',
description='Simple Dependency API',
long_description=(
- read('README.txt')
+ read('README.rst')
+ '\n\n' +
- read('CHANGES.txt')
+ read('CHANGES.rst')
),
- keywords = "zope3 dependency",
- classifiers = [
+ keywords="zope3 dependency",
+ classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
- 'Framework :: Zope3'],
- url='http://pypi.python.org/pypi/zope.app.dependable',
+ 'Framework :: Zope3',
+ ],
+ url='http://github.com/zopefoundation/zope.app.dependable',
license='ZPL 2.1',
packages=find_packages('src'),
- package_dir = {'': 'src'},
+ package_dir={'': 'src'},
namespace_packages=['zope', 'zope.app'],
- extras_require=dict(test=[]),
- install_requires=['setuptools',
- 'zope.annotation',
- 'zope.exceptions',
- 'zope.i18nmessageid',
- 'zope.interface',
- 'zope.lifecycleevent',
- 'zope.location',
- 'zope.traversing',
- ],
- include_package_data = True,
- zip_safe = False,
+ extras_require={
+ 'test': tests_require,
+ },
+ tests_require=tests_require,
+ install_requires=[
+ 'setuptools',
+ 'zope.annotation',
+ 'zope.exceptions',
+ 'zope.i18nmessageid',
+ 'zope.interface',
+ 'zope.lifecycleevent',
+ 'zope.location',
+ 'zope.traversing',
+ ],
+ include_package_data=True,
+ zip_safe=False,
+ test_suite='zope.app.dependable.tests',
)
diff --git a/src/zope/__init__.py b/src/zope/__init__.py
index bf99a9d..155a31d 100644
--- a/src/zope/__init__.py
+++ b/src/zope/__init__.py
@@ -1,8 +1,2 @@
# this is a namespace package
-try:
- import pkg_resources
- pkg_resources.declare_namespace(__name__)
-except ImportError:
- import pkgutil
- __path__ = pkgutil.extend_path(__path__, __name__)
-
+__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
diff --git a/src/zope/app/__init__.py b/src/zope/app/__init__.py
index bf99a9d..155a31d 100644
--- a/src/zope/app/__init__.py
+++ b/src/zope/app/__init__.py
@@ -1,8 +1,2 @@
# this is a namespace package
-try:
- import pkg_resources
- pkg_resources.declare_namespace(__name__)
-except ImportError:
- import pkgutil
- __path__ = pkgutil.extend_path(__path__, __name__)
-
+__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
diff --git a/src/zope/app/dependable/__init__.py b/src/zope/app/dependable/__init__.py
index 7b69dba..b715241 100644
--- a/src/zope/app/dependable/__init__.py
+++ b/src/zope/app/dependable/__init__.py
@@ -13,11 +13,11 @@
##############################################################################
"""Dependable Framework.
-$Id$
"""
+
__docformat__ = 'restructuredtext'
-from zope.interface import implements
+from zope.interface import implementer
from zope.traversing.api import getParent, canonicalPath, getPath
from zope.annotation.interfaces import IAnnotations
@@ -37,6 +37,7 @@ def __init__(self, context):
parent = getParent(self.context)
except TypeError:
parent = None
+
if parent is not None:
try:
pp = getPath(parent)
@@ -53,7 +54,7 @@ def addPath(self, path):
path = self._make_relative(path)
annotations = IAnnotations(self.context)
old = annotations.get(self.key, ())
- fixed = map(self._make_relative, old)
+ fixed = [self._make_relative(o) for o in old]
if path not in fixed:
fixed.append(path)
new = tuple(fixed)
@@ -65,7 +66,7 @@ def removePath(self, path):
annotations = IAnnotations(self.context)
old = annotations.get(self.key, ())
if old:
- fixed = map(self._make_relative, old)
+ fixed = [self._make_relative(o) for o in old]
fixed = [loc for loc in fixed if loc != path]
new = tuple(fixed)
if new != old:
@@ -84,8 +85,15 @@ def _make_relative(self, path):
path = canonicalPath(path)
if path.startswith(self.pp):
path = path[self.pplen:]
- while path.startswith("/"):
- path = path[1:]
+ # Now, the path should not actually begin with a /.
+ # canonicalPath doesn't allow trailing / in a path
+ # segment, and we already cut off the whole length of
+ # the parent, which we guaranteed to begin and end
+ # with a /. But it's possible that older dependencies
+ # than we test with could produce this scenario, so we
+ # leave it for BWC.
+ path = path.lstrip("/")
+
return path
def _make_absolute(self, path):
@@ -93,12 +101,10 @@ def _make_absolute(self, path):
path = self.pp + path
return path
-
+@implementer(IDependable)
class Dependable(PathSetAnnotation):
"""See `IDependable`."""
- implements(IDependable)
-
key = "zope.app.dependable.Dependents"
addDependent = PathSetAnnotation.addPath
diff --git a/src/zope/app/dependable/configure.zcml b/src/zope/app/dependable/configure.zcml
index e236c6c..fc19784 100644
--- a/src/zope/app/dependable/configure.zcml
+++ b/src/zope/app/dependable/configure.zcml
@@ -3,6 +3,8 @@
xmlns:zcml="http://namespaces.zope.org/zcml"
>
+
+