Skip to content

Commit

Permalink
Merge pull request #2 from zopefoundation/python3
Browse files Browse the repository at this point in the history
Python 3.4/5/6 and PyPy
  • Loading branch information
jamadden committed May 11, 2017
2 parents de4d471 + 1fab410 commit 5025325
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 83 deletions.
8 changes: 8 additions & 0 deletions .coveragerc
@@ -0,0 +1,8 @@
[run]
source = src

[report]
exclude_lines =
pragma: no cover
raise NotImplementedError
if __name__ == '__main__':
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -9,3 +9,5 @@ bin
develop-eggs
docs
parts
.coverage
htmlcov/
29 changes: 22 additions & 7 deletions .travis.yml
@@ -1,11 +1,26 @@
language: python
sudo: false
python:
- 2.6
- 2.7
- 3.3
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
7 changes: 6 additions & 1 deletion CHANGES.txt → CHANGES.rst
Expand Up @@ -5,7 +5,12 @@ CHANGES
2.0.0a2 (unreleased)
====================

- Nothing changed yet.
- Dropped support for Python 2.6 and 3.3.

- Added support for Python 3.4, 3.5, 3.6 and PyPy.

- Fix using complex slices (e.g., negative strides) in
``CompositeQueue``. The cost is higher memory usage.


2.0.0a1 (2013-03-01)
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Expand Up @@ -3,6 +3,8 @@ include *.txt
include *.py
include buildout.cfg
include tox.ini
include .travis.yml
include .coveragerc

recursive-include src *

Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions setup.cfg
@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1
26 changes: 16 additions & 10 deletions setup.py
Expand Up @@ -17,19 +17,23 @@
from setuptools import setup

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.testing"]
tests_require = [
"zope.testing",
"zope.testrunner",
]

setup(
name="zc.queue",
version='2.0.0a2.dev0',
author="Zope Project",
author_email="zope-dev@zope.org",
description=read('README.txt'),
description=read('README.rst'),
long_description='\n\n'.join([
read('src', 'zc', 'queue', 'queue.txt'),
read('CHANGES.txt'),
read('src', 'zc', 'queue', 'queue.rst'),
read('CHANGES.rst'),
]),
keywords='zope zope3',
classifiers=[
Expand All @@ -38,16 +42,18 @@ def read(*rnames):
'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.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',
'Framework :: Zope3'
],
url='http://pypi.python.org/pypi/zc.queue',
url='http://github.com/zopefoundation/zc.queue',
license="ZPL 2.1",
namespace_packages=['zc'],
packages=['zc', 'zc.queue'],
Expand All @@ -63,6 +69,6 @@ def read(*rnames):
test_suite='zc.queue.tests.test_suite',
extras_require=dict(
test=tests_require,
),
),
zip_safe=False
)
)
8 changes: 1 addition & 7 deletions src/zc/__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
39 changes: 15 additions & 24 deletions src/zc/queue/_queue.py
Expand Up @@ -235,32 +235,23 @@ def __iter__(self):
yield i

def __getitem__(self, index):
# not efficient, but quick and easy
if isinstance(index, slice):
start, stop, stride = index.indices(len(self))
res = []
stride_ct = 1
for ix, v in enumerate(self):
if ix >= stop:
break
if ix < start:
continue
stride_ct -= 1
if stride_ct == 0:
res.append(v)
stride_ct = stride
return res
# We do this the easy way instead of attempting to handle
# negative strides ourself
return list(self)[index]

if index < 0:
len_self = len(self)
rindex = index + len_self
if rindex < 0:
raise IndexError(index)
else:
if index < 0: # not efficient, but quick and easy
len_self = len(self)
rindex = index + len_self
if rindex < 0:
raise IndexError(index)
else:
rindex = index
for ix, v in enumerate(self):
if ix == rindex:
return v
raise IndexError(index)
rindex = index
for ix, v in enumerate(self):
if ix == rindex:
return v
raise IndexError(index)

def _p_resolveConflict(self, oldstate, committedstate, newstate):
return resolveQueueConflict(oldstate, committedstate, newstate)
Expand Down
11 changes: 8 additions & 3 deletions src/zc/queue/queue.txt → src/zc/queue/queue.rst
Expand Up @@ -450,14 +450,19 @@ objects that have same oid to simulate different transaction states.
`set` doesn't handle persistent reference objects properly. All
following set operations produce wrong results.

Deduplication:
Deduplication (notice that for items longer than length two we're only
checking the length and contents, not the ordering of the
representation, because that varies among different versions of Python):

>>> set((pr1, pr_c1))
set([SPR (1), SPR (1)])
>>> set((pr2, pr_c2))
set([SPR (2), SPR (2)])
>>> set((pr1, pr_c1, pr2))
set([SPR (1), SPR (1), SPR (2)])
>>> set4 = set((pr1, pr_c1, pr2))
>>> len(set4)
3
>>> pr1 in set4 and pr_c1 in set4 and pr2 in set4
True
>>> set4 = set((pr1, pr2, pr3, pr_c1, pr_c2, pr_c3))
>>> len(set4)
6
Expand Down
92 changes: 68 additions & 24 deletions src/zc/queue/tests.py
Expand Up @@ -23,9 +23,9 @@

checker = renormalizing.RENormalizing([
# Python 3 set representation changed.
(re.compile("set\(\[(.*?)\]\)"),
(re.compile(r"set\(\[(.*?)\]\)"),
r"{\1}"),
(re.compile("set\(\)"),
(re.compile(r"set\(\)"),
r"{}"),
])

Expand All @@ -49,8 +49,9 @@ class ConflictResolvingMappingStorage(

def store(self, oid, serial, data, version, transaction):
assert not version, "Versions are not supported"
if transaction is not self._transaction:
raise POSException.StorageTransactionError(self, transaction)
# Real storages would raise a StorageTransactionError for this
assert transaction is self._transaction


old_tid = None
tid_data = self._data.get(oid)
Expand All @@ -59,11 +60,9 @@ def store(self, oid, serial, data, version, transaction):
if serial != old_tid:
rdata = self.tryToResolveConflict(
oid, old_tid, serial, data)
if rdata is None:
raise POSException.ConflictError(
oid=oid, serials=(old_tid, serial), data=data)
else:
data = rdata
# Real storages would raise a ConflictError for this
assert rdata is not None
data = rdata
self._tdata[oid] = data
return self._tid

Expand Down Expand Up @@ -147,20 +146,14 @@ def __hash__(self):
# as the OID actually equals correct behavior!
return id(self)#self.oid

def __cmp__(self, other):
if self.oid == other.oid:
return 0
else:
raise ValueError("Can't compare")

def __eq__(self, other):
if self.oid == other.oid:
return True
else:
raise ValueError("Can't compare")
# Raising ValueError is actually expected
raise ValueError("Can't compare")

def __ne__(self, other):
raise ValueError("Can't compare")
raise NotImplementedError("Not called")

__lt__ = __gt__ = __le__ = __ge__ = __ne__

Expand All @@ -179,35 +172,86 @@ def __repr__(self):
return "%s" % self.value


class TestQueue(unittest.TestCase):

def _make_one(self):
return zc.queue.Queue()

def test_negative_pull_empty(self):
self.assertRaises(IndexError,
self._make_one().pull, -1)

def test_negative_getitem_empty(self):
self.assertRaises(IndexError,
self._make_one().__getitem__, -1)


def test_get_slice(self):
q = self._make_one()
q.put(1)
q.put(2)
q.put(3)
q.put(4)

self.assertEqual(list(q[:]), [1, 2, 3, 4])
self.assertEqual(list(q[:1]), [1])
self.assertEqual(list(q[::-1]), [4, 3, 2, 1])

def test_resolve_conflict_different_key(self):
q = self._make_one()
committedstate = {'k': 1}
newstate = {'j': 1}
oldstate = {}
self.assertRaises(POSException.ConflictError,
q._p_resolveConflict,
oldstate, committedstate, newstate)

def test_resolve_conflict_different_data(self):
q = self._make_one()
newstate = {'j': 1}
committedstate = {'j': 2}
oldstate = {}
self.assertRaises(POSException.ConflictError,
q._p_resolveConflict,
oldstate, committedstate, newstate)


class TestCompositeQueue(TestQueue):

def _make_one(self):
return zc.queue.CompositeQueue()


def test_suite():
flags = doctest.IGNORE_EXCEPTION_DETAIL
return unittest.TestSuite((
doctest.DocFileSuite(
'queue.txt',
'queue.rst',
optionflags=flags, checker=checker,
globs={
'Queue': zc.queue.Queue,
'Item': PersistentObject}),
doctest.DocFileSuite(
'queue.txt',
'queue.rst',
optionflags=flags, checker=checker,
globs={
'Queue': lambda: zc.queue.CompositeQueue(2),
'Item': PersistentObject}),
doctest.DocFileSuite(
'queue.txt',
'queue.rst',
optionflags=flags, checker=checker,
globs={
'Queue': zc.queue.Queue,
'Item': lambda x: x}),
doctest.DocFileSuite(
'queue.txt',
'queue.rst',
optionflags=flags, checker=checker,
globs={
'Queue': lambda: zc.queue.CompositeQueue(2),
'Item': lambda x: x}),
doctest.DocTestSuite()
))
doctest.DocTestSuite(),
unittest.defaultTestLoader.loadTestsFromName(__name__),
))

if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
10 changes: 3 additions & 7 deletions tox.ini
@@ -1,12 +1,8 @@
[tox]
envlist =
py26,py27,py33
envlist = py27,py34,py35,py36,pypy

[testenv]
commands =
python setup.py test -q
zope-testrunner --test-path=src []
deps =
ZODB
persistent
zope.interface
zope.testing
.[test]

0 comments on commit 5025325

Please sign in to comment.