Skip to content

Commit

Permalink
Python 3 and PyPy support
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
jamadden committed May 1, 2017
1 parent f3b8d0c commit af8c846
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 73 deletions.
8 changes: 8 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[run]
source = src

[report]
exclude_lines =
pragma: no cover
if __name__ == '__main__':
raise NotImplementedError
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ build/
dist/
*.egg-info/
.tox/
.coverage
htmlcov
27 changes: 22 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions CHANGES.txt → CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -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
File renamed without changes.
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1
61 changes: 41 additions & 20 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
8 changes: 1 addition & 7 deletions src/zope/__init__.py
Original file line number Diff line number Diff line change
@@ -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
8 changes: 1 addition & 7 deletions src/zope/app/__init__.py
Original file line number Diff line number Diff line change
@@ -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
3 changes: 1 addition & 2 deletions src/zope/app/principalannotation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
4 changes: 1 addition & 3 deletions src/zope/app/principalannotation/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#
##############################################################################
"""Bootstrap code for principal annotation utility.
$Id$
"""

import transaction
Expand All @@ -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)
Expand Down
1 change: 0 additions & 1 deletion src/zope/app/principalannotation/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@
##############################################################################
"""Utility for storing `IAnnotations` for principals.
$Id$
"""
from zope.principalannotation.interfaces import IPrincipalAnnotationUtility # BBB
141 changes: 115 additions & 26 deletions src/zope/app/principalannotation/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
<InterfaceClass zope.principalannotation.interfaces.IPrincipalAnnotationUtility>
>>> from zope.app.principalannotation import PrincipalAnnotationUtility
>>> from zope.app.principalannotation import Annotations
>>> from zope.app.principalannotation import annotations
>>> PrincipalAnnotationUtility
<class 'zope.principalannotation.utility.PrincipalAnnotationUtility'>
>>> Annotations
<class 'zope.principalannotation.utility.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__),
))
9 changes: 9 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[tox]
envlist =
py27, pypy, py34, py35, py36

[testenv]
commands =
zope-testrunner --test-path=src []
deps =
.[test]

0 comments on commit af8c846

Please sign in to comment.