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