Skip to content

Commit

Permalink
Merge pull request #1 from davisagli/compat-coverage
Browse files Browse the repository at this point in the history
test setup, pure python implementation, coverage
  • Loading branch information
tseaver committed Apr 6, 2015
2 parents d333f13 + 756ee6f commit 3e7473e
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 55 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -8,7 +8,11 @@ parts
*.pyc
*.pyo
*.so
.coverage
.installed.cfg
.tox
develop-eggs/
eggs/
*.egg-info/
coverage.xml
nosetests.xml
11 changes: 8 additions & 3 deletions .travis.yml
@@ -1,11 +1,16 @@
language: python
sudo: false
python:
- 2.6
- 2.7
- 3.2
- 3.3
- 3.4
- pypy
- pypy3
install:
- python bootstrap.py
- bin/buildout
- pip install nose
script:
- bin/test -v1
- nosetests
notifications:
email: false
7 changes: 5 additions & 2 deletions CHANGES.txt
@@ -1,9 +1,12 @@
Changelog
=========

2.13.1 (unreleased)
-------------------
3.0 (unreleased)
----------------

- Add a pure-Python implementation used for Python 3 and Pypy.

- Rewrote tests as unit tests.

2.13.0 (2010-03-30)
-------------------
Expand Down
9 changes: 9 additions & 0 deletions MANIFEST.in
@@ -0,0 +1,9 @@
include *.txt

recursive-include include *
recursive-include src *

global-exclude *.dll
global-exclude *.pyc
global-exclude *.pyo
global-exclude *.so
69 changes: 50 additions & 19 deletions setup.py
Expand Up @@ -14,26 +14,57 @@

from os.path import join
from setuptools import setup, find_packages, Extension
import os
import platform
import sys

setup(name='MultiMapping',
version = '2.13.1dev',
url='http://pypi.python.org/pypi/MultiMapping',
license='ZPL 2.1',
description="Special MultiMapping objects used in Zope2.",
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
long_description=open('README.txt').read() + '\n' +
open('CHANGES.txt').read(),

packages=find_packages('src'),
package_dir={'': 'src'},
ext_modules=[Extension(
# PyPy won't build the extension.
py_impl = getattr(platform, 'python_implementation', lambda: None)
is_pypy = py_impl() == 'PyPy'
is_pure = 'PURE_PYTHON' in os.environ
py3k = sys.version_info >= (3, )
if is_pypy or is_pure or py3k:
ext_modules = []
else:
ext_modules = [
Extension(
name='MultiMapping._MultiMapping',
include_dirs=['include', 'src'],
sources=[join('src', 'MultiMapping', '_MultiMapping.c')],
depends=[join('include', 'ExtensionClass', 'ExtensionClass.h')]),
],
install_requires=['ExtensionClass'],
include_package_data=True,
zip_safe=False,
)
),
]


setup(
name='MultiMapping',
version='3.0.dev0',
url='http://pypi.python.org/pypi/MultiMapping',
license='ZPL 2.1',
description="Special MultiMapping objects used in Zope2.",
classifiers=[
"Development Status :: 6 - Mature",
"Environment :: Web Environment",
"Framework :: Zope2",
"License :: OSI Approved :: Zope Public License",
"Operating System :: OS Independent",
"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.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
],
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
long_description=open('README.txt').read() + '\n' + open('CHANGES.txt').read(),
packages=find_packages('src'),
package_dir={'': 'src'},
ext_modules=ext_modules,
install_requires=['ExtensionClass'],
include_package_data=True,
zip_safe=False,
)
47 changes: 46 additions & 1 deletion src/MultiMapping/__init__.py
@@ -1 +1,46 @@
from _MultiMapping import *
import os


class MultiMapping:
__slots__ = ('__dicts__',)

def __init__(self, *args):
self.__dicts__ = list(args)

def __getitem__(self, key):
for d in self.__dicts__[::-1]:
try:
return d[key]
except (KeyError, AttributeError):
# XXX How do we get an AttributeError?
pass
raise KeyError(key)

def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default

def has_key(self, key):
try:
self[key]
except KeyError:
return False
return True

def push(self, d):
self.__dicts__.append(d)

def pop(self, n=-1):
return self.__dicts__.pop(n)

def __len__(self):
return sum(len(d) for d in self.__dicts__)


if 'PURE_PYTHON' not in os.environ: # pragma no cover
try:
from _MultiMapping import * # noqa
except ImportError:
pass
75 changes: 45 additions & 30 deletions src/MultiMapping/tests.py
Expand Up @@ -11,48 +11,63 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Multi-mapping tests

>>> from MultiMapping import *
import unittest

>>> def sortprint(L):
... L.sort()
... print L

>>> m=MultiMapping()
class TestMultiMapping(unittest.TestCase):

>>> m.push({'spam':1, 'eggs':2})
def _makeOne(self):
from MultiMapping import MultiMapping
return MultiMapping()

>>> print m['spam']
1
>>> print m['eggs']
2
def test_push(self):
m = self._makeOne()
m.push({'spam': 1, 'eggs': 2})
self.assertEqual(m['spam'], 1)
self.assertEqual(m['eggs'], 2)

>>> m.push({'spam':3})
def test_push_multiple(self):
m = self._makeOne()
m.push({'spam': 1, 'eggs': 2})
m.push({'spam': 3})
self.assertEqual(m['spam'], 3)
self.assertEqual(m['eggs'], 2)

>>> print m['spam']
3
>>> print m['eggs']
2
def test_pop(self):
m = self._makeOne()
m.push({'spam': 1, 'eggs': 2})
m.push({'spam': 3})
self.assertEqual(m.pop(), {'spam': 3})
self.assertEqual(m.pop(), {'spam': 1, 'eggs': 2})
self.assertRaises(IndexError, m.pop)

>>> sortprint(m.pop().items())
[('spam', 3)]
def test_getitem_not_found(self):
m = self._makeOne()
self.assertRaises(KeyError, m.__getitem__, 'ham')

>>> sortprint(m.pop().items())
[('eggs', 2), ('spam', 1)]
def test_get(self):
m = self._makeOne()
m.push({'spam': 1})
self.assertEqual(m.get('spam'), 1)
self.assertEqual(m.get('eggs'), None)

def test_has_key(self):
m = self._makeOne()
m.push({'spam': 1})
self.assertTrue(m.has_key('spam'))
self.assertFalse(m.has_key('eggs'))

def test_len(self):
m = self._makeOne()
m.push({'spam': 1})
self.assertEqual(len(m), 1)

>>> try:
... print m.pop()
... raise "That\'s odd", "This last pop should have failed!"
... except: # I should probably raise a specific error in this case.
... pass
"""
import unittest
from doctest import DocTestSuite

def test_suite():
return unittest.TestSuite((
DocTestSuite(),
unittest.makeSuite(TestMultiMapping),
))

if __name__ == '__main__': unittest.main()
if __name__ == '__main__':
unittest.main()
27 changes: 27 additions & 0 deletions tox.ini
@@ -0,0 +1,27 @@
[tox]
envlist =
py26,py27,py27-pure,py32,py33,py34,pypy,pypy3,coverage

[testenv]
commands =
nosetests
deps =
nose

[testenv:py27-pure]
basepython =
python2.7
setenv =
PURE_PYTHON = 1

[testenv:coverage]
basepython =
python2.7
commands =
nosetests --with-xunit --with-xcoverage
deps =
nose
coverage
nosexcover
setenv =
PURE_PYTHON = 1

0 comments on commit 3e7473e

Please sign in to comment.