Commit e64a066d authored by Stephan Richter's avatar Stephan Richter

Added support for Python 3.3 and tests pass. TOX does not run yet,

because porting zope.publisher is not done, but with buildout I am able
to run against the branch. Same for ZODB.
parent 3d95da90
......@@ -2,9 +2,11 @@
CHANGES
=======
4.0.0 (unreleased)
4.0.0a1 (unreleased)
-------------------
- Added support for Python 3.3.
- Made ``Folder`` class inherit from ``BTreeContainer`` class, so that the
IContainer interface does not need to be re-implemented. Added a ``data``
attribute for BBB.
......
......@@ -18,75 +18,10 @@ The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os, shutil, sys, tempfile, urllib, urllib2, subprocess
import os, shutil, sys, tempfile
from optparse import OptionParser
if sys.platform == 'win32':
def quote(c):
if ' ' in c:
return '"%s"' % c # work around spawn lamosity on windows
else:
return c
else:
quote = str
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
stdout, stderr = subprocess.Popen(
[sys.executable, '-Sc',
'try:\n'
' import ConfigParser\n'
'except ImportError:\n'
' print 1\n'
'else:\n'
' print 0\n'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
has_broken_dash_S = bool(int(stdout.strip()))
# In order to be more robust in the face of system Pythons, we want to
# run without site-packages loaded. This is somewhat tricky, in
# particular because Python 2.6's distutils imports site, so starting
# with the -S flag is not sufficient. However, we'll start with that:
if not has_broken_dash_S and 'site' in sys.modules:
# We will restart with python -S.
args = sys.argv[:]
args[0:0] = [sys.executable, '-S']
args = map(quote, args)
os.execv(sys.executable, args)
# Now we are running with -S. We'll get the clean sys.path, import site
# because distutils will do it later, and then reset the path and clean
# out any namespace packages from site-packages that might have been
# loaded by .pth files.
clean_path = sys.path[:]
import site # imported because of its side effects
sys.path[:] = clean_path
for k, v in sys.modules.items():
if k in ('setuptools', 'pkg_resources') or (
hasattr(v, '__path__') and
len(v.__path__) == 1 and
not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))):
# This is a namespace package. Remove it.
sys.modules.pop(k)
is_jython = sys.platform.startswith('java')
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
distribute_source = 'http://python-distribute.org/distribute_setup.py'
# parsing arguments
def normalize_to_url(option, opt_str, value, parser):
if value:
if '://' not in value: # It doesn't smell like a URL.
value = 'file://%s' % (
urllib.pathname2url(
os.path.abspath(os.path.expanduser(value))),)
if opt_str == '--download-base' and not value.endswith('/'):
# Download base needs a trailing slash to make the world happy.
value += '/'
else:
value = None
name = opt_str[2:].replace('-', '_')
setattr(parser.values, name, value)
tmpeggs = tempfile.mkdtemp()
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
......@@ -101,26 +36,8 @@ local resources, you can keep this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="use_distribute", default=False,
help="Use Distribute rather than Setuptools.")
parser.add_option("--setup-source", action="callback", dest="setup_source",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or file location for the setup file. "
"If you use Setuptools, this will default to " +
setuptools_source + "; if you use Distribute, this "
"will default to " + distribute_source + "."))
parser.add_option("--download-base", action="callback", dest="download_base",
callback=normalize_to_url, nargs=1, type="string",
help=("Specify a URL or directory for downloading "
"zc.buildout and either Setuptools or Distribute. "
"Defaults to PyPI."))
parser.add_option("--eggs",
help=("Specify a directory for storing eggs. Defaults to "
"a temporary directory that is deleted when the "
"bootstrap script completes."))
parser.add_option("-v", "--version", help="use a specific zc.buildout version")
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
......@@ -130,46 +47,38 @@ parser.add_option("-t", "--accept-buildout-test-releases",
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", None, action="store", dest="config_file",
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
options, args = parser.parse_args()
if options.eggs:
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
else:
eggs_dir = tempfile.mkdtemp()
if options.setup_source is None:
if options.use_distribute:
options.setup_source = distribute_source
else:
options.setup_source = setuptools_source
options, args = parser.parse_args()
if options.accept_buildout_test_releases:
args.insert(0, 'buildout:accept-buildout-test-releases=true')
######################################################################
# load/install distribute
to_reload = False
try:
import pkg_resources
import setuptools # A flag. Sometimes pkg_resources is installed alone.
import pkg_resources, setuptools
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError:
ez_code = urllib2.urlopen(
options.setup_source).read().replace('\r\n', '\n')
ez = {}
exec ez_code in ez
setup_args = dict(to_dir=eggs_dir, download_delay=0)
if options.download_base:
setup_args['download_base'] = options.download_base
if options.use_distribute:
setup_args['no_fake'] = True
if sys.version_info[:2] == (2, 4):
setup_args['version'] = '0.6.32'
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez)
setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True)
ez['use_setuptools'](**setup_args)
if 'pkg_resources' in sys.modules:
reload(sys.modules['pkg_resources'])
if to_reload:
reload(pkg_resources)
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
......@@ -177,33 +86,26 @@ except ImportError:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
cmd = [quote(sys.executable),
'-c',
quote('from setuptools.command.easy_install import main; main()'),
'-mqNxd',
quote(eggs_dir)]
######################################################################
# Install buildout
ws = pkg_resources.working_set
if not has_broken_dash_S:
cmd.insert(1, '-S')
cmd = [sys.executable, '-c',
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = options.download_base
if not find_links:
find_links = os.environ.get('bootstrap-testing-find-links')
if not find_links and options.accept_buildout_test_releases:
find_links = 'http://downloads.buildout.org/'
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', quote(find_links)])
cmd.extend(['-f', find_links])
if options.use_distribute:
setup_requirement = 'distribute'
else:
setup_requirement = 'setuptools'
ws = pkg_resources.working_set
setup_requirement_path = ws.find(
pkg_resources.Requirement.parse(setup_requirement)).location
env = dict(
os.environ,
PYTHONPATH=setup_requirement_path)
distribute_path = ws.find(
pkg_resources.Requirement.parse('distribute')).location
requirement = 'zc.buildout'
version = options.version
......@@ -211,14 +113,13 @@ if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setup_requirement_path])
search_path=[distribute_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
......@@ -227,8 +128,6 @@ if version is None and not options.accept_buildout_test_releases:
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if distv >= pkg_resources.parse_version('2dev'):
continue
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
......@@ -238,40 +137,29 @@ if version is None and not options.accept_buildout_test_releases:
if best:
best.sort()
version = best[-1].version
if version:
requirement += '=='+version
else:
requirement += '<2dev'
requirement = '=='.join((requirement, version))
cmd.append(requirement)
if is_jython:
import subprocess
exitcode = subprocess.Popen(cmd, env=env).wait()
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
if exitcode != 0:
sys.stdout.flush()
sys.stderr.flush()
print ("An error occurred when trying to install zc.buildout. "
"Look above this message for any errors that "
"were output by easy_install.")
sys.exit(exitcode)
import subprocess
if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=distribute_path)) != 0:
raise Exception(
"Failed to execute command:\n%s",
repr(cmd)[1:-1])
ws.add_entry(eggs_dir)
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
# If there isn't already a command in the args, add bootstrap
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout's main function
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
if not options.eggs: # clean up temporary egg directory
shutil.rmtree(eggs_dir)
shutil.rmtree(tmpeggs)
[buildout]
develop = .
parts = test graph coverage-test coverage-report
../zope.publisher
../ZODB
parts = test
# graph coverage-test coverage-report
[test]
recipe = zc.recipe.testrunner
......
......@@ -24,8 +24,23 @@ from setuptools import setup, find_packages, Extension
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
def alltests():
import os
import sys
import unittest
# use the zope.testrunner machinery to find all the
# test suites we've put under ourselves
import zope.testrunner.find
import zope.testrunner.options
here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
args = sys.argv[:]
defaults = ["--test-path", here]
options = zope.testrunner.options.get_options(args, defaults)
suites = list(zope.testrunner.find.find_suites(options))
return unittest.TestSuite(suites)
setup(name='zope.container',
version = '4.0.0dev',
version = '4.0.0a1.dev0',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Container',
......@@ -64,16 +79,17 @@ setup(name='zope.container',
], include_dirs=['include']),
],
extras_require=dict(
test=['zope.testing',
test=['zope.testing', 'zope.testrunner'
],
zcml=[
'zope.component[zcml]',
'zope.configuration',
'zope.security[zcml]>=3.8',
'zope.security[zcml]>=4.0.0a3',
],
zodb=['ZODB>=3.10',
]),
install_requires=['setuptools',
'six',
'zope.interface',
'zope.dottedname',
'zope.schema',
......@@ -85,11 +101,15 @@ setup(name='zope.container',
'zope.i18nmessageid',
'zope.filerepresentation',
'zope.size',
'zope.traversing',
'zope.traversing>=4.0.0a1',
'zope.publisher',
'persistent',
'BTrees'
],
tests_require = [
'zope.testing',
'zope.testrunner'],
test_suite = '__main__.alltests',
include_package_data = True,
zip_safe = False,
)
......@@ -309,18 +309,18 @@ class ItemTypePrecondition(_TypesBased):
>>> try:
... precondition(None, 'foo', ob)
... except InvalidItemType, v:
... print v[0], (v[1] is ob), (v[2] == (I1, I2))
... except InvalidItemType as v:
... print(v.args[0], (v.args[1] is ob), (v.args[2] == (I1, I2)))
... else:
... print 'Should have failed'
... print('Should have failed')
None True True
>>> try:
... precondition.factory(None, 'foo', factory)
... except InvalidItemType, v:
... print v[0], (v[1] is factory), (v[2] == (I1, I2))
... except InvalidItemType as v:
... print(v.args[0], (v.args[1] is factory), (v.args[2] == (I1, I2)))
... else:
... print 'Should have failed'
... print('Should have failed')
None True True
>>> zope.interface.classImplements(Ob, I2)
......@@ -415,10 +415,10 @@ class ContainerTypesConstraint(_TypesBased):
>>> constraint = ContainerTypesConstraint(I1, I2)
>>> try:
... constraint(ob)
... except InvalidContainerType, v:
... print (v[0] is ob), (v[1] == (I1, I2))
... except InvalidContainerType as v:
... print((v.args[0] is ob), (v.args[1] == (I1, I2)))
... else:
... print 'Should have failed'
... print('Should have failed')
True True
>>> zope.interface.classImplements(Ob, I2)
......
......@@ -13,8 +13,6 @@
##############################################################################
"""Classes to support implementing `IContained`
"""
__docformat__ = 'restructuredtext'
import zope.component
import zope.interface.declarations
from zope.interface import providedBy, Interface
......@@ -43,6 +41,11 @@ except ImportError:
class IBroken(Interface):
pass
try:
unicode
except NameError:
# Py3: Define unicode type.
unicode = str
@zope.interface.implementer(IContained)
class Contained(object):
......@@ -130,8 +133,7 @@ def dispatchToSublocations(object, event):
Now, we should have seen all of the subobjects:
>>> seenreprs = map(repr, seen)
>>> seenreprs.sort()
>>> seenreprs = sorted(map(repr, seen))
>>> seenreprs
['(C(11), C(1))', '(C(12), C(1))', '(L(111), C(1))',""" \
""" '(L(112), C(1))', '(L(121), C(1))', '(L(122), C(1))',""" \
......@@ -519,7 +521,7 @@ def setitem(container, setitemf, name, object):
...
TypeError: name not unicode or ascii string
>>> setitem(container, container.__setitem__, 'hello ' + chr(200), item)
>>> setitem(container, container.__setitem__, b'hello ' + bytes([200]), item)
Traceback (most recent call last):
...
TypeError: name not unicode or ascii string
......@@ -538,9 +540,9 @@ def setitem(container, setitemf, name, object):
"""
# Do basic name check:
if isinstance(name, str):
if isinstance(name, bytes):
try:
name = unicode(name)
name = name.decode('ascii')
except UnicodeError:
raise TypeError("name not unicode or ascii string")
elif not isinstance(name, unicode):
......@@ -746,8 +748,8 @@ class NameChooser(object):
NameReserved: reserved
"""
if isinstance(name, str):
name = unicode(name)
if isinstance(name, bytes):
name = name.decode()
elif not isinstance(name, unicode):
raise TypeError("Invalid name type", type(name))
......@@ -789,7 +791,10 @@ class NameChooser(object):
the suggested name is converted to unicode:
>>> NameChooser(container).chooseName('foobar', object())
>>> NameChooser(container).chooseName(u'foobar', object())
u'foobar'
>>> NameChooser(container).chooseName(b'foobar', object())
u'foobar'
If it already exists, a number is appended but keeps the same extension:
......@@ -812,14 +817,19 @@ class NameChooser(object):
container = self.context
# convert to unicode and remove characters that checkName does not allow
try:
name = unicode(name)
except:
name = u''
if isinstance(name, bytes):
name = name.decode()
if not isinstance(name, unicode):
try:
name = unicode(name)
except:
name = u''
name = name.replace('/', '-').lstrip('+@')
if not name:
name = unicode(object.__class__.__name__)
name = object.__class__.__name__
if isinstance(name, bytes):
name = name.decode()
# for an existing name, append a number.
# We should keep client's os.path.extsep (not ours), we assume it's '.'
......@@ -834,7 +844,7 @@ class NameChooser(object):
i = 1
while n in container:
i += 1
n = name + u'-' + unicode(i) + suffix
n = name + u'-' + str(i) + suffix
# Make sure the name is valid. We may have started with something bad.
self.checkName(n, object)
......
......@@ -28,6 +28,8 @@ from zope.interface import implementer
from zope.component.interfaces import ISite
from zope.security.proxy import removeSecurityProxy
import zope.filerepresentation.interfaces
from six.moves import map
from six.moves import zip
MARKER = object()
......
......@@ -16,8 +16,8 @@
__docformat__ = 'restructuredtext'
from zope.interface import implementer
from interfaces import IFind, IIdFindFilter, IObjectFindFilter
from interfaces import IReadContainer
from .interfaces import IFind, IIdFindFilter, IObjectFindFilter
from .interfaces import IReadContainer
@implementer(IFind)
class FindAdapter(object):
......
......@@ -23,10 +23,10 @@ class Folder(btree.BTreeContainer):
# BBB: The data attribute used to be exposed. This should make it also
# compatible with old pickles.
@apply
def data():
def getter(self):
return self._SampleContainer__data
def setter(self, value):
self._SampleContainer__data = value
return property(getter, setter)
@property
def data(self):
return self._SampleContainer__data
@data.setter
def data(self, value):
self._SampleContainer__data = value
......@@ -14,13 +14,12 @@
"""Ordered container implementation.
"""
__docformat__ = 'restructuredtext'
from zope.container.interfaces import IOrderedContainer
from zope.interface import implementer
import six
from persistent import Persistent
from persistent.dict import PersistentDict
from persistent.list import PersistentList
from types import StringTypes, TupleType, ListType
from zope.container.interfaces import IOrderedContainer
from zope.interface import implementer
from zope.container.contained import Contained, setitem, uncontained
from zope.container.contained import notifyContainerModified
......@@ -157,7 +156,7 @@ class OrderedContainer(Persistent, Contained):
0
"""
return self._data.has_key(key)
return key in self._data
has_key = __contains__
......@@ -184,12 +183,15 @@ class OrderedContainer(Persistent, Contained):
['foo', 'baz']
"""
existed = self._data.has_key(key)
existed = key in self._data
bad = False
if isinstance(key, StringTypes):
if isinstance(key, six.string_types):
try:
unicode(key)
key.decode()
except AttributeError:
# Py3 str cannot decode.
pass
except UnicodeError:
bad = True
else:
......@@ -288,8 +290,8 @@ class OrderedContainer(Persistent, Contained):
0
"""
if not isinstance(order, ListType) and \
not isinstance(order, TupleType):
if not isinstance(order, list) and \
not isinstance(order, tuple):
raise TypeError('order must be a tuple or a list.')
if len(order) != len(self._order):
......
......@@ -75,7 +75,7 @@ class SampleContainer(Contained):
def __contains__(self, key):
'''See interface `IReadContainer`'''
return self.__data.has_key(key)
return key in self.__data
has_key = __contains__
......
......@@ -13,13 +13,15 @@
##############################################################################
"""Unit test logic for setting up and tearing down basic infrastructure
"""
import re
import zope.interface
import zope.traversing.testing
from zope import component
from zope.component.testing import PlacelessSetup as CAPlacelessSetup
from zope.component.eventtesting import PlacelessSetup as EventPlacelessSetup
from zope.traversing.interfaces import ITraversable, IContainmentRoot
import zope.traversing.testing
import zope.interface
from zope.testing import renormalizing
from zope.container.interfaces import IWriteContainer, INameChooser
from zope.container.contained import NameChooser
......@@ -27,6 +29,29 @@ from zope.container.interfaces import ISimpleReadContainer
from zope.container.traversal import ContainerTraversable
from zope.container.sample import SampleContainer
checker = renormalizing.RENormalizing([
# Python 3 unicode removed the "u".
(re.compile("u('.*?')"),
r"\1"),
(re.compile('u(".*?")'),
r"\1"),
# Python 3 renamed type to class.
(re.compile('<type '),
r"<class "),
# Python 3 adds module name to exceptions.
(re.compile("zope.interface.exceptions.Invalid"),
r"Invalid"),
(re.compile("zope.container.interfaces.InvalidContainerType"),
r"InvalidContainerType"),
(re.compile("zope.container.interfaces.InvalidItemType"),
r"InvalidItemType"),
(re.compile("zope.container.interfaces.NameReserved"),
r"NameReserved"),
(re.compile("zope.schema._bootstrapinterfaces.ConstraintNotSatisfied"),
r"ConstraintNotSatisfied"),
])
# XXX we would like to swap the names of the *PlacelessSetup classes
# in here as that would seem to follow the convention better, but
# unfortunately that would break compatibility with zope.app.testing
......
......@@ -21,11 +21,11 @@ The new folder isn't a site manager and doesn't have any entries:
KeyError: 'test'
>>> list(fs_folder.__iter__())
[]
>>> fs_folder.values()
>>> list(fs_folder.values())
[]
>>> len(fs_folder)
0
>>> fs_folder.items()
>>> list(fs_folder.items())
[]
>>> 'test' in fs_folder
False
......@@ -37,7 +37,7 @@ access non-existing entries:
>>> from zope.security.checker import NamesChecker
>>> proxied_folder = ProxyFactory(fs_folder, NamesChecker(('get',)))
>>> proxied_fs_folder = ReadDirectory(proxied_folder)
>>> print proxied_fs_folder['i dont exist']
>>> print(proxied_fs_folder['i dont exist'])
Traceback (most recent call last):
KeyError: 'i dont exist'
......@@ -40,7 +40,7 @@ class TestBTreeSpecials(TestCase):
bc = BTreeContainer()
self.assertEqual(bc.__dict__['_BTreeContainer__len'](), 0)
del bc.__dict__['_BTreeContainer__len']
self.failIf(bc.__dict__.has_key('_BTreeContainer__len'))
self.failIf('_BTreeContainer__len' in bc.__dict__)
bc['1'] = 1
self.assertEqual(len(bc), 1)
self.assertEqual(bc.__dict__['_BTreeContainer__len'](), 1)
......@@ -154,12 +154,11 @@ class TestBTreeSpecials(TestCase):
def checkIterable(self, iterable):
it = iter(iterable)
self.assert_(callable(it.next))
self.assert_(callable(it.__iter__))
self.assert_(iter(it) is it)
# Exhaust the iterator:
first_time = list(it)
self.assertRaises(StopIteration, it.next)
self.assertRaises(StopIteration, next, it)
# Subsequent iterations will return the same values:
self.assertEqual(list(iterable), first_time)
self.assertEqual(list(iterable), first_time)
......
......@@ -13,10 +13,10 @@
##############################################################################
"""Container constraint tests
"""
import doctest
import unittest
from zope.testing import module
from zope.container import testing
def setUp(test):
module.setUp(test, 'zope.container.constraints_txt')
......@@ -26,9 +26,11 @@ def tearDown(test):
def test_suite():
return unittest.TestSuite((
doctest.DocTestSuite('zope.container.constraints'),
doctest.DocFileSuite('../constraints.txt',
setUp=setUp, tearDown=tearDown),
doctest.DocTestSuite(
'zope.container.constraints', checker=testing.checker),
doctest.DocFileSuite(
'../constraints.txt',
setUp=setUp, tearDown=tearDown, checker=testing.checker),
))
if __name__ == '__main__': unittest.main()
......@@ -130,10 +130,10 @@ def test_ContainedProxy_instances_have_no_instance_dictionaries():
>>> p.__dict__
{'x': 1}
>>> p.y = 3
>>> p.__dict__
{'y': 3, 'x': 1}
>>> c.__dict__
{'y': 3, 'x': 1}
>>> sorted(p.__dict__.items())
[('x', 1), ('y', 3)]
>>> sorted(c.__dict__.items())
[('x', 1), ('y', 3)]
>>> p.__dict__ is c.__dict__
True
......@@ -219,17 +219,21 @@ class TestNameChooser(unittest.TestCase):
class BadBoy:
def __unicode__(self):
raise Exception
# Py3: Support
__str__ = __unicode__
self.assertEqual(nc.chooseName(BadBoy(), set()), u'set')
def test_suite():
return unittest.TestSuite((
doctest.DocTestSuite('zope.container.contained',
setUp=testing.setUp,
tearDown=testing.tearDown),
doctest.DocTestSuite(optionflags=doctest.NORMALIZE_WHITESPACE),
unittest.makeSuite(TestNameChooser),
))
if __name__ == '__main__': unittest.main()
suite = unittest.TestSuite((
unittest.makeSuite(TestNameChooser),
))
suite.addTest(doctest.DocTestSuite(
'zope.container.contained',
setUp=testing.setUp, tearDown=testing.tearDown,
checker=testing.checker))
suite.addTest(doctest.DocTestSuite(
optionflags=doctest.NORMALIZE_WHITESPACE,
checker=testing.checker))
return suite
......@@ -224,9 +224,6 @@ def test_suite():
if not HAVE_ZODB:
return unittest.TestSuite([])
return unittest.TestSuite((
doctest.DocTestSuite('zope.container.contained',
setUp=testing.setUp,
tearDown=testing.tearDown),
doctest.DocTestSuite(optionflags=doctest.NORMALIZE_WHITESPACE),
))
......
......@@ -20,16 +20,17 @@ from zope.traversing.interfaces import TraversalError
from zope.container.traversal import ContainerTraversable
from zope.container.interfaces import IContainer
import six
@implementer(IContainer)
class Container(object):
def __init__(self, attrs={}, objs={}):
for attr,value in attrs.iteritems():
for attr,value in six.iteritems(attrs):
setattr(self, attr, value)
self.__objs = {}
for name,value in objs.iteritems():
for name,value in six.iteritems(objs):
self.__objs[name] = value
......@@ -40,7 +41,7 @@ class Container(object):
return self.__objs.get(name, default)
def __contains__(self, name):
return self.__objs.has_key(name)
return name in self.__objs
class Test(CleanUp, unittest.TestCase):
......
......@@ -89,7 +89,7 @@ class BaseTestIContainer(testing.ContainerPlacelessSetup):
values.remove(v)
except ValueError:
self.fail('Value not in list')
self.assertEqual(values, [])
def test_len(self):
......@@ -174,11 +174,11 @@ class BaseTestIContainer(testing.ContainerPlacelessSetup):
folder[name] = foo
self.assertEquals(len(folder.keys()), 1)
self.assertEquals(folder.keys()[0], name)
self.assertEquals(list(folder.keys())[0], name)
self.assertEquals(len(folder.values()), 1)
self.assertEquals(folder.values()[0], foo)
self.assertEquals(list(folder.values())[0], foo)
self.assertEquals(len(folder.items()), 1)
self.assertEquals(folder.items()[0], (name, foo))
self.assertEquals(list(folder.items())[0], (name, foo))
self.assertEquals(len(folder), 1)
self.failUnless(name in folder)
......@@ -192,7 +192,7 @@ class BaseTestIContainer(testing.ContainerPlacelessSetup):
self.assertRaises(KeyError, folder.__getitem__, data[6][0])
foo2 = data[1][1]
name2 = data[1][0]
folder[name2] = foo2
......@@ -308,7 +308,7 @@ class TestSampleContainer(BaseTestIContainer, TestCase):
return '10'
def getBadKeyTypes(self):
return [None, ['foo'], 1, '\xf3abc']
return [None, [b'foo'], 1, b'\xf3abc']
def test_suite():
return makeSuite(TestSampleContainer)
......
......@@ -61,10 +61,10 @@ def test_order_events():
def test_all_items_available_at_object_added_event():
"""
Prepare the setup::
>>> from zope.container.sample import SampleContainer
>>> root = SampleContainer()
Now register an event subscriber to object added events.
>>> import zope.component
......@@ -73,11 +73,11 @@ def test_all_items_available_at_object_added_event():
>>> @zope.component.adapter(IObjectAddedEvent)
... def printContainerKeys(event):
... print event.newParent.keys()
... print(event.newParent.keys())
>>> zope.component.provideHandler(printContainerKeys)
Now we are adding an object to the container.
Now we are adding an object to the container.
>>> from zope.container.ordered import OrderedContainer
>>> oc = OrderedContainer()
......@@ -138,7 +138,7 @@ def test_adding_none():
[None]
>>> oc.items()
[('foo', None)]
>>> print oc['foo']
>>> print(oc['foo'])
None
"""
......@@ -147,10 +147,12 @@ def test_suite():
suite = unittest.TestSuite()
suite.addTest(DocTestSuite("zope.container.ordered",
setUp=testing.setUp,
tearDown=testing.tearDown))
tearDown=testing.tearDown,
checker=testing.checker))
suite.addTest(DocTestSuite(
setUp=testing.ContainerPlacefulSetup().setUp,
tearDown=testing.ContainerPlacefulSetup().tearDown))
tearDown=testing.ContainerPlacefulSetup().tearDown,
checker=testing.checker))
return suite
if __name__ == '__main__':
......
......@@ -25,6 +25,8 @@ from zope.publisher.interfaces import IDefaultViewName, NotFound
from zope.container.interfaces import ISimpleReadContainer, IItemContainer
from zope.container.interfaces import IReadContainer
from six.moves import map
from six.moves import zip
# Note that the next two classes are included here because they
# can be used for multiple view types.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment