From af8c846cfee7e1a831aa7275adf4d8ab1f85dc8f Mon Sep 17 00:00:00 2001 From: Jason Madden Date: Mon, 1 May 2017 10:01:43 -0500 Subject: [PATCH] Python 3 and PyPy support - 100% test coverage - Rename README/CHANGES.txt -> .rst for rendering on github - Add tox.ini - Update travis.yml with sudo: false and pip caching and coveralls --- .coveragerc | 8 + .gitignore | 2 + .travis.yml | 27 +++- CHANGES.txt => CHANGES.rst | 4 +- MANIFEST.in | 5 + README.txt => README.rst | 0 setup.cfg | 2 + setup.py | 61 +++++--- src/zope/__init__.py | 8 +- src/zope/app/__init__.py | 8 +- src/zope/app/principalannotation/__init__.py | 3 +- src/zope/app/principalannotation/bootstrap.py | 4 +- .../app/principalannotation/interfaces.py | 1 - src/zope/app/principalannotation/tests.py | 141 ++++++++++++++---- tox.ini | 9 ++ 15 files changed, 210 insertions(+), 73 deletions(-) create mode 100644 .coveragerc rename CHANGES.txt => CHANGES.rst (95%) rename README.txt => README.rst (100%) create mode 100644 setup.cfg create mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..f31f86e --- /dev/null +++ b/.coveragerc @@ -0,0 +1,8 @@ +[run] +source = src + +[report] +exclude_lines = + pragma: no cover + if __name__ == '__main__': + raise NotImplementedError diff --git a/.gitignore b/.gitignore index 5149542..f25457c 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..38a5a1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,26 @@ language: python +sudo: false python: - - 2.7 -install: - - pip install . + - 2.7 + - 3.4 + - 3.5 + - 3.6 + - pypy-5.4.1 script: - - python setup.py test -q + - coverage run -m zope.testrunner --test-path=src --auto-color --auto-progress + +after_success: + - coveralls notifications: - email: false + email: false + +install: + - pip install -U pip setuptools + - pip install -U coveralls coverage + - pip install -U -e ".[test]" + + +cache: pip + +before_cache: + - rm -f $HOME/.cache/pip/log/debug.log diff --git a/CHANGES.txt b/CHANGES.rst similarity index 95% rename from CHANGES.txt rename to CHANGES.rst index 950d79d..7eecde6 100644 --- a/CHANGES.txt +++ b/CHANGES.rst @@ -2,10 +2,10 @@ CHANGES ======= -3.7.1 (unreleased) +4.0.0 (unreleased) ------------------ -- Nothing changed yet. +- Add support for Python 3.4, 3.5 and 3.6 and PyPy. 3.7.0 (2009-12-26) diff --git a/MANIFEST.in b/MANIFEST.in index 95b9ff2..e93fab1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,9 @@ include *.py include *.txt +include *.rst include buildout.cfg +include .travis.yml +include tox.ini +include .coveragerc + recursive-include src *.zcml 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 232c42a..afac2c8 100644 --- a/setup.py +++ b/setup.py @@ -18,47 +18,68 @@ ############################################################################## """Setup for zope.app.principalannotation 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() + +tests_require = [ + 'zope.container', + 'zope.testing', + 'zope.testrunner', + 'zope.traversing', +] setup(name='zope.app.principalannotation', - version = '3.7.1dev', + version='4.0.0.dev0', author='Zope Corporation and Contributors', author_email='zope-dev@zope.org', description='Bootstrap subscriber and browser menu item for zope.principalannotation', long_description=( - read('README.txt') + read('README.rst') + '\n\n' + - read('CHANGES.txt') + read('CHANGES.rst') ), - keywords = "zope security principal annotation", - classifiers = [ + keywords="zope security principal annotation", + 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.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + '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.principalannotation', + 'Framework :: Zope3', + ], + url='http://github.com/zopefoundation/zope.app.principalannotation', license='ZPL 2.1', packages=find_packages('src'), - package_dir = {'': 'src'}, + package_dir={'': 'src'}, namespace_packages=['zope', 'zope.app'], - extras_require = dict(test=['zope.testing']), - install_requires=['setuptools', - 'transaction', - 'zope.app.appsetup >= 3.11.0', - 'zope.processlifetime', - 'zope.principalannotation', - ], - include_package_data = True, - zip_safe = False, - ) + extras_require={ + 'test': tests_require, + }, + tests_require=tests_require, + install_requires=[ + 'setuptools', + 'transaction', + 'zope.app.appsetup >= 4.0.0', + 'zope.processlifetime >= 2.1.0', + 'zope.principalannotation >= 4.0.0', + ], + include_package_data=True, + zip_safe=False, +) diff --git a/src/zope/__init__.py b/src/zope/__init__.py index 2e2033b..2cdb0e4 100644 --- a/src/zope/__init__.py +++ b/src/zope/__init__.py @@ -1,7 +1 @@ -# 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 2e2033b..2cdb0e4 100644 --- a/src/zope/app/__init__.py +++ b/src/zope/app/__init__.py @@ -1,7 +1 @@ -# 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/principalannotation/__init__.py b/src/zope/app/principalannotation/__init__.py index 321e3ac..532b05c 100644 --- a/src/zope/app/principalannotation/__init__.py +++ b/src/zope/app/principalannotation/__init__.py @@ -13,11 +13,10 @@ ############################################################################## """Implementation of `IPrincipalAnnotationUtility`. -$Id$ """ # BBB: the functionality was moved to zope.principalannotation from zope.principalannotation.utility import ( PrincipalAnnotationUtility, Annotations, - annotations) + annotations) diff --git a/src/zope/app/principalannotation/bootstrap.py b/src/zope/app/principalannotation/bootstrap.py index 9969ede..e8f041e 100644 --- a/src/zope/app/principalannotation/bootstrap.py +++ b/src/zope/app/principalannotation/bootstrap.py @@ -12,8 +12,6 @@ # ############################################################################## """Bootstrap code for principal annotation utility. - -$Id$ """ import transaction @@ -29,7 +27,7 @@ def bootStrapSubscriber(event): Create utility at that time if not yet present """ - db, connection, root, root_folder = getInformationFromEvent(event) + _db, connection, _root, root_folder = getInformationFromEvent(event) ensureUtility(root_folder, IPrincipalAnnotationUtility, 'PrincipalAnnotation', PrincipalAnnotationUtility) diff --git a/src/zope/app/principalannotation/interfaces.py b/src/zope/app/principalannotation/interfaces.py index 5f6966d..555c336 100644 --- a/src/zope/app/principalannotation/interfaces.py +++ b/src/zope/app/principalannotation/interfaces.py @@ -13,6 +13,5 @@ ############################################################################## """Utility for storing `IAnnotations` for principals. -$Id$ """ from zope.principalannotation.interfaces import IPrincipalAnnotationUtility # BBB diff --git a/src/zope/app/principalannotation/tests.py b/src/zope/app/principalannotation/tests.py index 9cfa803..1125909 100644 --- a/src/zope/app/principalannotation/tests.py +++ b/src/zope/app/principalannotation/tests.py @@ -13,36 +13,125 @@ ############################################################################## """Principal Annotation Tests -$Id$ """ import doctest import unittest -def test_bbb_imports(): - """ - The most of functionality was moved to zope.principalannotation. - Let's test if old imports still work:: - - >>> from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility - >>> IPrincipalAnnotationUtility - - - >>> from zope.app.principalannotation import PrincipalAnnotationUtility - >>> from zope.app.principalannotation import Annotations - >>> from zope.app.principalannotation import annotations - - >>> PrincipalAnnotationUtility - - - >>> Annotations - - - >>> print annotations.__module__ + '.' + annotations.__name__ - zope.principalannotation.utility.annotations - - """ +from zope import component +from zope import interface + +from zope.component.testing import PlacelessSetup + +from zope.traversing.interfaces import ITraverser +from zope.container.interfaces import INameChooser + +class TestImports(unittest.TestCase): + + + def test_bbb_imports(self): + # The most of functionality was moved to zope.principalannotation. + # Let's test if old imports still work: + + from zope.app.principalannotation import interfaces as OldI + from zope.principalannotation import interfaces as NewI + self.assertIs(NewI.IPrincipalAnnotationUtility, OldI.IPrincipalAnnotationUtility) + + from zope.app import principalannotation as Old + from zope.principalannotation import utility as New + + self.assertIs(Old.PrincipalAnnotationUtility, New.PrincipalAnnotationUtility) + self.assertIs(Old.Annotations, New.Annotations) + + self.assertEqual(Old.annotations.__module__, + 'zope.principalannotation.utility') + + +class TestBootstrap(PlacelessSetup, unittest.TestCase): + + def test_subscriber_utility(self): + + from zope.app.principalannotation.bootstrap import bootStrapSubscriber + + test = self + + @interface.implementer(ITraverser, + INameChooser) + class SiteManager(object): + + def __init__(self): + self._data = {} + + def traverse(self, name, request=None): + test.assertEqual(name, 'default') + return self + + def chooseName(self, name, utility): + test.assertEqual(name, 'PrincipalAnnotation') + return name + + def __getattr__(self, name): + return getattr(component.getGlobalSiteManager(), name) + + def __setitem__(self, name, value): + self._data[name] = value + + def __getitem__(self, name): + return self._data[name] + + def __contains__(self, name): + return name in self._data + + class RootFolder(dict): + + def __init__(self): + self.sm = SiteManager() + + def getSiteManager(self): + return self.sm + + class Connection(object): + closed = False + + def __init__(self): + self._root = {'Application': RootFolder()} + + def close(self): + self.closed = True + + def root(self): + return self._root + + class Database(object): + + def __init__(self): + self.conn = Connection() + + def open(self): + return self.conn + + class Event(object): + + def __init__(self): + self.database = Database() + + event = Event() + bootStrapSubscriber(event) + + # We closed the connection when we were done + self.assertTrue(event.database.conn.closed) + + # We only register once + self.assertIn('PrincipalAnnotation', + event.database.conn.root()['Application'].getSiteManager()) + + event2 = Event() + bootStrapSubscriber(event2) + + self.assertNotIn('PrincipalAnnotation', + event2.database.conn.root()['Application'].getSiteManager()) + def test_suite(): return unittest.TestSuite(( - doctest.DocTestSuite() - )) + unittest.defaultTestLoader.loadTestsFromName(__name__), + )) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..128e680 --- /dev/null +++ b/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = + py27, pypy, py34, py35, py36 + +[testenv] +commands = + zope-testrunner --test-path=src [] +deps = + .[test]