[Zope-dev] Python 3.3 port of zope.configuration
Brian Sutherland
brian at vanguardistas.net
Wed Apr 11 07:57:19 UTC 2012
Hi,
I'd like to merge 2 branches which get zope.configuration's tests
running on Python 3.3. Here is an overview (with patches attached):
zope.schema:
* svn+ssh://svn.zope.org/repos/main/zope.schema/branches/jinty-native_string
* This branch corrects a mistake I think I made in the zope.schema
Python3 port. After my experience with the zope.configuration port
I now think that the URI field should be a "native" string rather
than bytes.
Unfortunately this change is backwards incompatible for Python 3
users of zope.schema. But I think the number users of zope.schema
under Python 3 are rather small at this point.
* I make public NativeString and NativeStringLine classes. These are
equivalent to the Bytes type under Python 2 and the Text type under
Python 3. Please devote some bikeshedding energy to better names
for these classes ;)
zope.configuration:
* svn+ssh://svn.zope.org/repos/main/zope.configuration/branches/jinty-python3
* Adds a dependency on six
* Drops Python 2.4 and 2.5 compatibility
To run the tests of the zope.configuration branch you currently need to
use the zope.interface trunk.
If there are no objections, I'll merge in a few weeks or so.
--
Brian Sutherland
-------------- next part --------------
Index: CHANGES.txt
===================================================================
--- CHANGES.txt (.../trunk) (revision 125127)
+++ CHANGES.txt (.../branches/jinty-native_string) (revision 125127)
@@ -2,12 +2,16 @@
CHANGES
=======
-4.1.2 (unreleased)
+4.2.0 (unreleased)
------------------
-- Nothing changed yet.
+- Introduce NativeString and NativeStringLine which are equal to Bytes and
+ BytesLine on Python 2 and Text and TextLine on Python 3.
+- Change IURI from a Bytes string to a "native" string. This is a backwards
+ incompatibility which only affects Python 3.
+
4.1.1 (2012-03-23)
------------------
Index: src/zope/schema/__init__.py
===================================================================
--- src/zope/schema/__init__.py (.../trunk) (revision 125127)
+++ src/zope/schema/__init__.py (.../branches/jinty-native_string) (revision 125127)
@@ -17,6 +17,7 @@
from zope.schema._field import MinMaxLen, Choice
from zope.schema._field import Bytes, ASCII, BytesLine, ASCIILine
from zope.schema._field import Text, TextLine, Bool, Int, Float, Decimal
+from zope.schema._field import NativeString, NativeStringLine
from zope.schema._field import Tuple, List, Set, FrozenSet
from zope.schema._field import Password, Dict, Datetime, Date, Timedelta
from zope.schema._field import Time, SourceText
Index: src/zope/schema/tests/test_uri.py
===================================================================
--- src/zope/schema/tests/test_uri.py (.../trunk) (revision 0)
+++ src/zope/schema/tests/test_uri.py (.../branches/jinty-native_string) (revision 125127)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""URI field tests
+"""
+from unittest import main, makeSuite
+
+from six import u
+from zope.schema import URI
+from zope.schema.tests.test_field import FieldTestBase
+from zope.schema.interfaces import RequiredMissing
+from zope.schema.interfaces import InvalidURI, WrongType
+
+class URITest(FieldTestBase):
+ """Test the URI Field."""
+
+ _Field_Factory = URI
+
+ def testValidate(self):
+ field = self._Field_Factory(
+ title=u('Not required field'), description=u(''),
+ readonly=False, required=False)
+ field.validate(None)
+ field.validate('http://www.example.com')
+ self.assertRaises(WrongType, field.validate, 2)
+
+ def testValidateRequired(self):
+ field = self._Field_Factory(
+ title=u('Required field'), description=u(''),
+ readonly=False, required=True)
+ field.validate('http://www.example.com')
+ self.assertRaises(RequiredMissing, field.validate, None)
+
+ def testFromUnicode(self):
+ field = self._Field_Factory()
+ # result is a native string
+ self.assertEqual(
+ field.fromUnicode(u("http://www.python.org/foo/bar")),
+ 'http://www.python.org/foo/bar')
+ # leading/trailing whitespace is stripped
+ self.assertEqual(
+ field.fromUnicode(u(" http://www.python.org/foo/bar")),
+ 'http://www.python.org/foo/bar')
+ self.assertEqual(
+ field.fromUnicode(u(" \n http://www.python.org/foo/bar\n")),
+ 'http://www.python.org/foo/bar')
+ # but not in the middle
+ self.assertRaises(InvalidURI,
+ field.fromUnicode,
+ u("http://www.python.org/ foo/bar"))
+
+def test_suite():
+ suite = makeSuite(URITest)
+ return suite
+
+if __name__ == '__main__':
+ main(defaultTest='test_suite')
Property changes on: src/zope/schema/tests/test_uri.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/zope/schema/tests/test_native_string.py
===================================================================
--- src/zope/schema/tests/test_native_string.py (.../trunk) (revision 0)
+++ src/zope/schema/tests/test_native_string.py (.../branches/jinty-native_string) (revision 125127)
@@ -0,0 +1,38 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import unittest
+
+import six
+
+from zope.schema import Text, Bytes, NativeString
+from zope.schema import TextLine, BytesLine, NativeStringLine
+
+class TestNativeString(unittest.TestCase):
+
+ def test_string_py2(self):
+ if six.PY3:
+ return
+ self.assertTrue(NativeString is Bytes)
+ self.assertTrue(NativeStringLine is BytesLine)
+
+ def test_string_py3(self):
+ if not six.PY3:
+ return
+ self.assertTrue(NativeString is Text)
+ self.assertTrue(NativeStringLine is TextLine)
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestNativeString))
+ return suite
Property changes on: src/zope/schema/tests/test_native_string.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/zope/schema/_field.py
===================================================================
--- src/zope/schema/_field.py (.../trunk) (revision 125127)
+++ src/zope/schema/_field.py (.../branches/jinty-native_string) (revision 125127)
@@ -107,12 +107,12 @@
# for things which are of the str type on both Python 2 and 3
if PY3:
- _Str = Text
+ NativeString = Text
else:
- _Str = Bytes
+ NativeString = Bytes
@implementer(IASCII)
-class ASCII(_Str):
+class ASCII(NativeString):
__doc__ = IASCII.__doc__
def _validate(self, value):
@@ -152,9 +152,9 @@
# for things which are of the str type on both Python 2 and 3
if PY3:
- _StrLine = TextLine
+ NativeStringLine = TextLine
else:
- _StrLine = BytesLine
+ NativeStringLine = BytesLine
@implementer(IASCIILine)
class ASCIILine(ASCII):
@@ -602,46 +602,32 @@
_isuri = r"[a-zA-z0-9+.-]+:" # scheme
_isuri += r"\S*$" # non space (should be pickier)
-_isuri_bytes = re.compile(_isuri.encode('ascii')).match
_isuri = re.compile(_isuri).match
@implementer(IURI, IFromUnicode)
-class URI(BytesLine):
+class URI(NativeStringLine):
"""URI schema field
"""
def _validate(self, value):
"""
>>> uri = URI(__name__='test')
- >>> uri.validate(b("http://www.python.org/foo/bar"))
- >>> uri.validate(b("DAV:"))
- >>> uri.validate(b("www.python.org/foo/bar"))
+ >>> uri.validate("http://www.python.org/foo/bar")
+ >>> uri.validate("DAV:")
+ >>> uri.validate("www.python.org/foo/bar")
Traceback (most recent call last):
...
InvalidURI: www.python.org/foo/bar
"""
super(URI, self)._validate(value)
- if _isuri_bytes(value):
+ if _isuri(value):
return
raise InvalidURI(value)
def fromUnicode(self, value):
- """
- >>> uri = URI(__name__='test')
- >>> uri.fromUnicode("http://www.python.org/foo/bar")
- 'http://www.python.org/foo/bar'
- >>> uri.fromUnicode(" http://www.python.org/foo/bar")
- 'http://www.python.org/foo/bar'
- >>> uri.fromUnicode(" \\n http://www.python.org/foo/bar\\n")
- 'http://www.python.org/foo/bar'
- >>> uri.fromUnicode("http://www.python.org/ foo/bar")
- Traceback (most recent call last):
- ...
- InvalidURI: http://www.python.org/ foo/bar
- """
- v = value.strip().encode('ascii')
+ v = str(value.strip())
self.validate(v)
return v
@@ -654,7 +640,7 @@
@implementer(IId, IFromUnicode)
-class Id(_StrLine):
+class Id(NativeStringLine):
"""Id field
Values of id fields must be either uris or dotted names.
@@ -705,7 +691,7 @@
@implementer(IDottedName)
-class DottedName(_StrLine):
+class DottedName(NativeStringLine):
"""Dotted name field.
Values of DottedName fields must be Python-style dotted names.
Index: src/zope/schema/interfaces.py
===================================================================
--- src/zope/schema/interfaces.py (.../trunk) (revision 125127)
+++ src/zope/schema/interfaces.py (.../branches/jinty-native_string) (revision 125127)
@@ -373,7 +373,7 @@
return True
-class IURI(IBytesLine):
+class IURI(_IStrLine):
"""A field containing an absolute URI
"""
Index: src/zope/schema/README.txt
===================================================================
--- src/zope/schema/README.txt (.../trunk) (revision 125127)
+++ src/zope/schema/README.txt (.../branches/jinty-native_string) (revision 125127)
@@ -65,7 +65,7 @@
is to define some data:
>>> title = u('Zope 3 Website')
- >>> url = b('http://dev.zope.org/Zope3')
+ >>> url = 'http://dev.zope.org/Zope3'
Now we, get the fields from the interface:
@@ -86,14 +86,9 @@
If the validation is successful, ``None`` is returned. If a validation error
occurs a ``ValidationError`` will be raised; for example:
- >>> url_bound.validate(u('http://zope.org/foo'))
+ >>> url_bound.validate('foo.bar')
Traceback (most recent call last):
...
- WrongType: (u'http://zope.org/foo', <type 'str'>, 'url')
-
- >>> url_bound.validate(b('foo.bar'))
- Traceback (most recent call last):
- ...
InvalidURI: foo.bar
Now that the data has been successfully validated, we can set it on the
-------------- next part --------------
Index: CHANGES.txt
===================================================================
--- CHANGES.txt (.../trunk) (revision 125127)
+++ CHANGES.txt (.../branches/jinty-python3) (revision 125127)
@@ -2,11 +2,11 @@
Changes
=======
-3.8.1 (unreleased)
+4.0.0 (unreleased)
------------------
-- Fixed Python 2.4 backwards incompat (itemgetter used with multiple args);
- Python 2.4 now works (at least if you use zope.schema == 3.8.1).
+- Support Python 3.3.
+- Drop support for Python 2.4 and Python 2.5.
3.8.0 (2011-12-06)
------------------
Index: setup.py
===================================================================
--- setup.py (.../trunk) (revision 125127)
+++ setup.py (.../branches/jinty-python3) (revision 125127)
@@ -78,6 +78,10 @@
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Programming Language :: Python',
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.3",
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
@@ -89,7 +93,8 @@
namespace_packages=['zope'],
extras_require=dict(
test=['zope.testing']),
- install_requires=['zope.i18nmessageid',
+ install_requires=['six',
+ 'zope.i18nmessageid',
'zope.interface',
'zope.schema',
'setuptools',
Index: src/zope/configuration/tests/test_simple.py
===================================================================
--- src/zope/configuration/tests/test_simple.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/test_simple.py (.../branches/jinty-python3) (revision 125127)
@@ -121,15 +121,16 @@
>>> from zope.configuration.tests.test_xmlconfig import clean_text_w_paths
>>> from zope.configuration.tests.test_xmlconfig import clean_path
+>>> from six import print_
>>> for i in file_registry:
-... print "path:", clean_path(i.path)
-... print "title:", i.title
-... print "description:", '\n'.join(
+... print_("path:", clean_path(i.path))
+... print_("title:", i.title)
+... print_("description:", '\n'.join(
... [l.rstrip()
... for l in i.description.strip().split('\n')
-... if l.rstrip()])
-... print "info:"
-... print clean_text_w_paths(i.info)
+... if l.rstrip()]))
+... print_("info:")
+... print_(clean_text_w_paths(i.info))
path: tests/test_simple.py
title: How to create a simple directive
description: Describes how to implement a simple directive
Index: src/zope/configuration/tests/victim.py
===================================================================
--- src/zope/configuration/tests/victim.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/victim.py (.../branches/jinty-python3) (revision 125127)
@@ -1 +1 @@
-import bad
+from . import bad
Index: src/zope/configuration/tests/directives.py
===================================================================
--- src/zope/configuration/tests/directives.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/directives.py (.../branches/jinty-python3) (revision 125127)
@@ -13,7 +13,7 @@
##############################################################################
"""Test directives
"""
-from zope.interface import Interface, implements
+from zope.interface import Interface, implementer
from zope.schema import Text, BytesLine
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.interfaces import IConfigurationContext
@@ -48,11 +48,11 @@
class IPackagedContext(IPackaged, IConfigurationContext):
pass
+ at implementer(IPackagedContext)
class Packaged(GroupingContextDecorator):
+ pass
- implements(IPackagedContext)
-
class IFactory(Interface):
factory = GlobalObject()
Index: src/zope/configuration/tests/test_config.py
===================================================================
--- src/zope/configuration/tests/test_config.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/test_config.py (.../branches/jinty-python3) (revision 125127)
@@ -17,250 +17,245 @@
import sys
import unittest
import re
+import six
from doctest import DocTestSuite
from zope.testing import renormalizing
from zope.configuration.config import metans, ConfigurationMachine
from zope.configuration import config
-def test_config_extended_example():
- """Configuration machine
+class TestConfig(unittest.TestCase):
- Examples:
+ def test_config_extended_example(self):
+ from zope.configuration.tests.directives import f
+ # Examples:
- >>> machine = ConfigurationMachine()
- >>> ns = "http://www.zope.org/testing"
+ machine = ConfigurationMachine()
+ ns = "http://www.zope.org/testing"
- Register some test directives:
+ # Register some test directives:
+ # Start with a grouping directive that sets a package:
- Start with a grouping directive that sets a package:
+ machine((metans, "groupingDirective"),
+ name="package", namespace=ns,
+ schema="zope.configuration.tests.directives.IPackaged",
+ handler="zope.configuration.tests.directives.Packaged",
+ )
- >>> machine((metans, "groupingDirective"),
- ... name="package", namespace=ns,
- ... schema="zope.configuration.tests.directives.IPackaged",
- ... handler="zope.configuration.tests.directives.Packaged",
- ... )
+ # we can set the package:
- Now we can set the package:
+ machine.begin((ns, "package"),
+ package="zope.configuration.tests.directives",
+ )
- >>> machine.begin((ns, "package"),
- ... package="zope.configuration.tests.directives",
- ... )
+ # Which makes it easier to define the other directives:
+ # First, define some simple directives:
- Which makes it easier to define the other directives:
+ machine((metans, "directive"),
+ namespace=ns, name="simple",
+ schema=".ISimple", handler=".simple")
- First, define some simple directives:
+ machine((metans, "directive"),
+ namespace=ns, name="newsimple",
+ schema=".ISimple", handler=".newsimple")
- >>> machine((metans, "directive"),
- ... namespace=ns, name="simple",
- ... schema=".ISimple", handler=".simple")
- >>> machine((metans, "directive"),
- ... namespace=ns, name="newsimple",
- ... schema=".ISimple", handler=".newsimple")
+ # try them out:
+ machine((ns, "simple"), "first", a=u"aa", c=u"cc")
+ machine((ns, "newsimple"), "second", a=u"naa", c=u"ncc", b=u"nbb")
- and try them out:
+ self.assertEqual(machine.actions,
+ [{'args': (u'aa', u'xxx', b'cc'),
+ 'callable': f,
+ 'discriminator': ('simple',
+ u'aa',
+ u'xxx',
+ b'cc'),
+ 'includepath': (),
+ 'info': 'first',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'naa', u'nbb', b'ncc'),
+ 'callable': f,
+ 'discriminator': ('newsimple',
+ u'naa',
+ u'nbb',
+ b'ncc'),
+ 'includepath': (),
+ 'info': 'second',
+ 'kw': {},
+ 'order': 0}])
- >>> machine((ns, "simple"), "first", a=u"aa", c=u"cc")
- >>> machine((ns, "newsimple"), "second", a=u"naa", c=u"ncc", b=u"nbb")
+ # Define and try a simple directive that uses a component:
- >>> from pprint import PrettyPrinter
- >>> pprint=PrettyPrinter(width=50).pprint
+ machine((metans, "directive"),
+ namespace=ns, name="factory",
+ schema=".IFactory", handler=".factory")
- >>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
- 'callable': f,
- 'discriminator': ('simple',
- u'aa',
- u'xxx',
- 'cc'),
- 'includepath': (),
- 'info': 'first',
- 'kw': {},
- 'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
- 'callable': f,
- 'discriminator': ('newsimple',
- u'naa',
- u'nbb',
- 'ncc'),
- 'includepath': (),
- 'info': 'second',
- 'kw': {},
- 'order': 0}]
- Define and try a simple directive that uses a component:
+ machine((ns, "factory"), factory=u".f")
- >>> machine((metans, "directive"),
- ... namespace=ns, name="factory",
- ... schema=".IFactory", handler=".factory")
+ self.assertEqual(machine.actions[-1:],
+ [{'args': (),
+ 'callable': f,
+ 'discriminator': ('factory', 1, 2),
+ 'includepath': (),
+ 'info': None,
+ 'kw': {},
+ 'order': 0}])
+ # Define and try a complex directive:
- >>> machine((ns, "factory"), factory=u".f")
- >>> pprint(machine.actions[-1:])
- [{'args': (),
- 'callable': f,
- 'discriminator': ('factory', 1, 2),
- 'includepath': (),
- 'info': None,
- 'kw': {},
- 'order': 0}]
+ machine.begin((metans, "complexDirective"),
+ namespace=ns, name="testc",
+ schema=".ISimple", handler=".Complex")
- Define and try a complex directive:
+ machine((metans, "subdirective"),
+ name="factory", schema=".IFactory")
- >>> machine.begin((metans, "complexDirective"),
- ... namespace=ns, name="testc",
- ... schema=".ISimple", handler=".Complex")
+ machine.end()
- >>> machine((metans, "subdirective"),
- ... name="factory", schema=".IFactory")
+ machine.begin((ns, "testc"), None, "third", a=u'ca', c='cc')
+ machine((ns, "factory"), "fourth", factory=".f")
- >>> machine.end()
+ # Note that we can't call a complex method unless there is a directive for
+ # it:
- >>> machine.begin((ns, "testc"), None, "third", a=u'ca', c='cc')
- >>> machine((ns, "factory"), "fourth", factory=".f")
+ self.assertRaises(config.ConfigurationError, machine, (ns, "factory2"), factory=".f")
+ #Traceback (most recent call last):
+ # ...
+ #ConfigurationError: ('Invalid directive', 'factory2')
- Note that we can't call a complex method unless there is a directive for
- it:
+ machine.end()
- >>> machine((ns, "factory2"), factory=".f")
- Traceback (most recent call last):
- ...
- ConfigurationError: ('Invalid directive', 'factory2')
+ self.assertEqual(machine.actions,
+ [{'args': (u'aa', u'xxx', b'cc'),
+ 'callable': f,
+ 'discriminator': ('simple',
+ u'aa',
+ u'xxx',
+ b'cc'),
+ 'includepath': (),
+ 'info': 'first',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'naa', u'nbb', b'ncc'),
+ 'callable': f,
+ 'discriminator': ('newsimple',
+ u'naa',
+ u'nbb',
+ b'ncc'),
+ 'includepath': (),
+ 'info': 'second',
+ 'kw': {},
+ 'order': 0},
+ {'args': (),
+ 'callable': f,
+ 'discriminator': ('factory', 1, 2),
+ 'includepath': (),
+ 'info': None,
+ 'kw': {},
+ 'order': 0},
+ {'args': (),
+ 'callable': None,
+ 'discriminator': 'Complex.__init__',
+ 'includepath': (),
+ 'info': 'third',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'ca',),
+ 'callable': f,
+ 'discriminator': ('Complex.factory', 1, 2),
+ 'includepath': (),
+ 'info': 'fourth',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'xxx', b'cc'),
+ 'callable': f,
+ 'discriminator': ('Complex', 1, 2),
+ 'includepath': (),
+ 'info': 'third',
+ 'kw': {},
+ 'order': 0}])
+ # Done with the package
- >>> machine.end()
- >>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
- 'callable': f,
- 'discriminator': ('simple',
- u'aa',
- u'xxx',
- 'cc'),
- 'includepath': (),
- 'info': 'first',
- 'kw': {},
- 'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
- 'callable': f,
- 'discriminator': ('newsimple',
- u'naa',
- u'nbb',
- 'ncc'),
- 'includepath': (),
- 'info': 'second',
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': f,
- 'discriminator': ('factory', 1, 2),
- 'includepath': (),
- 'info': None,
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': None,
- 'discriminator': 'Complex.__init__',
- 'includepath': (),
- 'info': 'third',
- 'kw': {},
- 'order': 0},
- {'args': (u'ca',),
- 'callable': f,
- 'discriminator': ('Complex.factory', 1, 2),
- 'includepath': (),
- 'info': 'fourth',
- 'kw': {},
- 'order': 0},
- {'args': (u'xxx', 'cc'),
- 'callable': f,
- 'discriminator': ('Complex', 1, 2),
- 'includepath': (),
- 'info': 'third',
- 'kw': {},
- 'order': 0}]
+ machine.end()
- Done with the package
+ # Verify that we can use a simple directive outside of the package:
- >>> machine.end()
+ machine((ns, "simple"), a=u"oaa", c=u"occ", b=u"obb")
+ # we can't use the factory directive, because it's only valid
+ # inside a package directive:
- Verify that we can use a simple directive outside of the package:
+ self.assertRaises(config.ConfigurationError, machine, (ns, "factory"), factory=u".F")
+ #Traceback (most recent call last):
+ #...
+ #ConfigurationError: ('Invalid value for', 'factory',""" \
+ # """ "Can't use leading dots in dotted names, no package has been set.")
- >>> machine((ns, "simple"), a=u"oaa", c=u"occ", b=u"obb")
+ self.assertEqual(machine.actions,
+ [{'args': (u'aa', u'xxx', b'cc'),
+ 'callable': f,
+ 'discriminator': ('simple',
+ u'aa',
+ u'xxx',
+ b'cc'),
+ 'includepath': (),
+ 'info': 'first',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'naa', u'nbb', b'ncc'),
+ 'callable': f,
+ 'discriminator': ('newsimple',
+ u'naa',
+ u'nbb',
+ b'ncc'),
+ 'includepath': (),
+ 'info': 'second',
+ 'kw': {},
+ 'order': 0},
+ {'args': (),
+ 'callable': f,
+ 'discriminator': ('factory', 1, 2),
+ 'includepath': (),
+ 'info': None,
+ 'kw': {},
+ 'order': 0},
+ {'args': (),
+ 'callable': None,
+ 'discriminator': 'Complex.__init__',
+ 'includepath': (),
+ 'info': 'third',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'ca',),
+ 'callable': f,
+ 'discriminator': ('Complex.factory', 1, 2),
+ 'includepath': (),
+ 'info': 'fourth',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'xxx', b'cc'),
+ 'callable': f,
+ 'discriminator': ('Complex', 1, 2),
+ 'includepath': (),
+ 'info': 'third',
+ 'kw': {},
+ 'order': 0},
+ {'args': (u'oaa', u'obb', b'occ'),
+ 'callable': f,
+ 'discriminator': ('simple',
+ u'oaa',
+ u'obb',
+ b'occ'),
+ 'includepath': (),
+ 'info': None,
+ 'kw': {},
+ 'order': 0}])
- But we can't use the factory directive, because it's only valid
- inside a package directive:
- >>> machine((ns, "factory"), factory=u".F")
- Traceback (most recent call last):
- ...
- ConfigurationError: ('Invalid value for', 'factory',""" \
- """ "Can't use leading dots in dotted names, no package has been set.")
-
- >>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
- 'callable': f,
- 'discriminator': ('simple',
- u'aa',
- u'xxx',
- 'cc'),
- 'includepath': (),
- 'info': 'first',
- 'kw': {},
- 'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
- 'callable': f,
- 'discriminator': ('newsimple',
- u'naa',
- u'nbb',
- 'ncc'),
- 'includepath': (),
- 'info': 'second',
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': f,
- 'discriminator': ('factory', 1, 2),
- 'includepath': (),
- 'info': None,
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': None,
- 'discriminator': 'Complex.__init__',
- 'includepath': (),
- 'info': 'third',
- 'kw': {},
- 'order': 0},
- {'args': (u'ca',),
- 'callable': f,
- 'discriminator': ('Complex.factory', 1, 2),
- 'includepath': (),
- 'info': 'fourth',
- 'kw': {},
- 'order': 0},
- {'args': (u'xxx', 'cc'),
- 'callable': f,
- 'discriminator': ('Complex', 1, 2),
- 'includepath': (),
- 'info': 'third',
- 'kw': {},
- 'order': 0},
- {'args': (u'oaa', u'obb', 'occ'),
- 'callable': f,
- 'discriminator': ('simple',
- u'oaa',
- u'obb',
- 'occ'),
- 'includepath': (),
- 'info': None,
- 'kw': {},
- 'order': 0}]
-
- """
- #'
-
def test_keyword_handling():
"""
>>> machine = ConfigurationMachine()
@@ -382,7 +377,7 @@
>>> c.resolve('zope.configuration.tests.victim')
Traceback (most recent call last):
...
- File "...bad.py", line 3 in ?
+ File "...bad.py", line 3 in ...
import bad_to_the_bone
ImportError: No module named bad_to_the_bone
@@ -417,14 +412,37 @@
"""
def test_suite():
- checker = renormalizing.RENormalizing([
+ checkers = [
(re.compile(r"<type 'exceptions.(\w+)Error'>:"),
r'exceptions.\1Error:'),
+ ]
+ if six.PY3:
+ checkers.extend([
+ (re.compile(r"^zope.schema._bootstrapinterfaces.([a-zA-Z]*):"),
+ r'\1:'),
+ (re.compile(r"^zope.configuration.interfaces.([a-zA-Z]*):"),
+ r'\1:'),
+ (re.compile(r"^zope.configuration.exceptions.([a-zA-Z]*):"),
+ r'\1:'),
+ (re.compile(r"b'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'b"([^"]*)"'),
+ r'"\1"'),
+ (re.compile(r"u'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'u"([^"]*)"'),
+ r'"\1"'),
+ (re.compile(r"\(<class 'int'>,\)"),
+ r"(<type 'int'>, <type 'long'>)"),
+ (re.compile(r"No module named '([^']*)'"),
+ r'No module named \1'),
])
+ checker = renormalizing.RENormalizing(checkers)
return unittest.TestSuite((
- DocTestSuite('zope.configuration.fields'),
- DocTestSuite('zope.configuration.config',checker=checker),
- DocTestSuite(),
+ unittest.findTestCases(sys.modules[__name__]),
+ DocTestSuite('zope.configuration.fields', checker=checker),
+ DocTestSuite('zope.configuration.config', checker=checker),
+ DocTestSuite(checker=checker),
))
if __name__ == '__main__': unittest.main()
Index: src/zope/configuration/tests/samplepackage/foo.py
===================================================================
--- src/zope/configuration/tests/samplepackage/foo.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/samplepackage/foo.py (.../branches/jinty-python3) (revision 125127)
@@ -28,8 +28,7 @@
) = args, info, basepath, package, includepath
def handler(_context, **kw):
- args = kw.items()
- args.sort()
+ args = sorted(kw.items())
args = tuple(args)
discriminator = args
args = (stuff(args, _context.info, _context.basepath, _context.package,
Index: src/zope/configuration/tests/test_nested.py
===================================================================
--- src/zope/configuration/tests/test_nested.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/test_nested.py (.../branches/jinty-python3) (revision 125127)
@@ -114,7 +114,7 @@
>>> from pprint import PrettyPrinter
>>> pprint=PrettyPrinter(width=70).pprint
->>> pprint(list(schema_registry))
+>>> pprint(sorted(schema_registry))
['zope.configuration.tests.test_nested.I1',
'zope.configuration.tests.test_nested.I2']
@@ -126,19 +126,19 @@
>>> i1 = schema_registry['zope.configuration.tests.test_nested.I1']
>>> sorted(i1)
['a', 'b']
->>> i1['a'].__class__.__name__
+>>> i1[b'a'].__class__.__name__
'Text'
->>> i1['a'].description.strip()
+>>> i1[b'a'].description.strip()
u'A\n\n Blah blah'
->>> i1['a'].min_length
+>>> i1[b'a'].min_length
1
->>> i1['b'].__class__.__name__
+>>> i1[b'b'].__class__.__name__
'Int'
->>> i1['b'].description.strip()
+>>> i1[b'b'].description.strip()
u'B\n\n Not feeling very creative'
->>> i1['b'].min
+>>> i1[b'b'].min
1
->>> i1['b'].max
+>>> i1[b'b'].max
10
>>> i2 = schema_registry['zope.configuration.tests.test_nested.I2']
@@ -151,13 +151,13 @@
(Note that we used the context we created above, so we don't have to
redefine our directives:
+>>> from six import print_
>>> try:
... v = xmlconfig.string(
... '<text xmlns="http://sample.namespaces.zope.org/schema" name="x" />',
... context)
-... except xmlconfig.ZopeXMLConfigurationError, v:
-... pass
->>> print v
+... except xmlconfig.ZopeXMLConfigurationError as v:
+... print_(v)
File "<string>", line 1.0
ConfigurationError: The directive """ \
"""(u'http://sample.namespaces.zope.org/schema', u'text') """ \
@@ -175,16 +175,20 @@
... </schema>
... ''',
... context)
-... except xmlconfig.ZopeXMLConfigurationError, v:
-... pass
->>> print v
+... except xmlconfig.ZopeXMLConfigurationError as v:
+... print_(v)
File "<string>", line 5.7-5.24
ValueError: ('Duplicate field', 'x')
"""
+import re
import unittest
from doctest import DocTestSuite
+
+import six
from zope import interface, schema
+from zope.testing import renormalizing
+
from zope.configuration import config, xmlconfig, fields
@@ -210,12 +214,11 @@
fields = interface.Attribute("Dictionary of field definitions"
)
+ at interface.implementer(config.IConfigurationContext, ISchema)
class Schema(config.GroupingContextDecorator):
"""Handle schema directives
"""
- interface.implements(config.IConfigurationContext, ISchema)
-
def __init__(self, context, name, id):
self.context, self.name, self.id = context, name, id
self.fields = {}
@@ -312,8 +315,21 @@
def test_suite():
+ checkers = []
+ if six.PY3:
+ checkers.extend([
+ (re.compile(r"b'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'b"([^"]*)"'),
+ r'"\1"'),
+ (re.compile(r"u'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'u"([^"]*)"'),
+ r'"\1"'),
+ ])
+ checker = renormalizing.RENormalizing(checkers)
return unittest.TestSuite((
- DocTestSuite(),
+ DocTestSuite(checker=checker),
))
if __name__ == '__main__': unittest.main()
Index: src/zope/configuration/tests/test_xmlconfig.py
===================================================================
--- src/zope/configuration/tests/test_xmlconfig.py (.../trunk) (revision 125127)
+++ src/zope/configuration/tests/test_xmlconfig.py (.../branches/jinty-python3) (revision 125127)
@@ -14,9 +14,12 @@
"""Test XML configuration (ZCML) machinery.
"""
import unittest
+import sys
import os
import re
from doctest import DocTestSuite, DocFileSuite
+import six
+from six import print_
from zope.testing import renormalizing
from zope.configuration import xmlconfig, config
from zope.configuration.tests.samplepackage import foo
@@ -48,37 +51,34 @@
def path(*p):
return os.path.join(os.path.dirname(__file__), *p)
-def test_ConfigurationHandler_normal():
- """
- >>> context = FauxContext()
- >>> locator = FauxLocator('tests//sample.zcml', 1, 1)
- >>> handler = xmlconfig.ConfigurationHandler(context)
- >>> handler.setDocumentLocator(locator)
- >>> handler.startElementNS((u"ns", u"foo"), u"foo",
- ... {(u"xxx", u"splat"): u"splatv",
- ... (None, u"a"): u"avalue",
- ... (None, u"b"): u"bvalue",
- ... })
- >>> context.info
- File "tests//sample.zcml", line 1.1
- >>> from pprint import PrettyPrinter
- >>> pprint=PrettyPrinter(width=50).pprint
- >>> pprint(context.begin_args)
- ((u'ns', u'foo'),
- {'a': u'avalue', 'b': u'bvalue'})
- >>> getattr(context, "end_called", 0)
- 0
+class TestConfigurationHandler(unittest.TestCase):
- >>> locator.line, locator.column = 7, 16
- >>> handler.endElementNS((u"ns", u"foo"), u"foo")
- >>> context.info
- File "tests//sample.zcml", line 1.1-7.16
- >>> context.end_called
- 1
+ def test_normal(self):
+ context = FauxContext()
+ locator = FauxLocator('tests//sample.zcml', 1, 1)
+ handler = xmlconfig.ConfigurationHandler(context)
+ handler.setDocumentLocator(locator)
- """
+ handler.startElementNS((u"ns", u"foo"),
+ u"foo",
+ {(u"xxx", u"splat"): u"splatv",
+ (None, u"a"): u"avalue",
+ (None, u"b"): u"bvalue",
+ })
+ self.assertEqual(repr(context.info), 'File "tests//sample.zcml", line 1.1')
+ self.assertEqual(context.begin_args, ((u'ns', u'foo'),
+ {'a': u'avalue', 'b': u'bvalue'}))
+ self.assertEqual(getattr(context, "end_called", 0), 0)
+
+ locator.line, locator.column = 7, 16
+ handler.endElementNS((u"ns", u"foo"), u"foo")
+
+ self.assertEqual(repr(context.info), 'File "tests//sample.zcml", line 1.1-7.16')
+ self.assertEqual(context.end_called, 1)
+
+
def test_ConfigurationHandler_err_start():
"""
@@ -97,9 +97,8 @@
... (None, u"a"): u"avalue",
... (None, u"b"): u"bvalue",
... })
- ... except xmlconfig.ZopeXMLConfigurationError, v:
- ... pass
- >>> print v
+ ... except xmlconfig.ZopeXMLConfigurationError as v:
+ ... print_(v)
File "tests//sample.zcml", line 1.1
AttributeError: xxx
@@ -126,9 +125,8 @@
>>> locator.line, locator.column = 7, 16
>>> try:
... v = handler.endElementNS((u"ns", u"foo"), u"foo")
- ... except xmlconfig.ZopeXMLConfigurationError, v:
- ... pass
- >>> print v
+ ... except xmlconfig.ZopeXMLConfigurationError as v:
+ ... print_(v)
File "tests//sample.zcml", line 1.1-7.16
AttributeError: xxx
@@ -165,10 +163,10 @@
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
<test:foo x="blah" y="0" />
@@ -187,15 +185,15 @@
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
<test:foo x="blah" y="0" />
>>> data.package
- >>> print clean_path(data.basepath)
+ >>> print_(clean_path(data.basepath))
tests/samplepackage
"""
@@ -212,10 +210,10 @@
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
<test:foo x="blah" y="0" />
@@ -255,10 +253,10 @@
>>> data.args
(('x', 'foo'), ('y', 2))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/foo.zcml.in", line 12.2-12.28
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/foo.zcml.in", line 12.2-12.28
<test:foo x="foo" y="2" />
@@ -284,10 +282,10 @@
>>> data.args
(('x', 'foo'), ('y', 3))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/baz3.zcml", line 5.2-5.28
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/baz3.zcml", line 5.2-5.28
<test:foo x="foo" y="3" />
@@ -303,10 +301,10 @@
>>> data.args
(('x', 'foo'), ('y', 2))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/baz2.zcml", line 5.2-5.28
- >>> print clean_info_path(str(data.info))
+ >>> print_(clean_info_path(str(data.info)))
File "tests/samplepackage/baz2.zcml", line 5.2-5.28
<test:foo x="foo" y="2" />
@@ -322,7 +320,7 @@
def clean_actions(actions):
return [
{'discriminator': action['discriminator'],
- 'info': clean_info_path(`action['info']`),
+ 'info': clean_info_path(repr(action['info'])),
'includepath': [clean_path(p) for p in action['includepath']],
}
for action in actions
@@ -330,7 +328,7 @@
def clean_text_w_paths(error):
r = []
- for line in unicode(error).split("\n"):
+ for line in six.text_type(error).split("\n"):
line = line.rstrip()
if not line:
continue
@@ -404,9 +402,8 @@
>>> try:
... v = context.execute_actions()
- ... except config.ConfigurationConflictError, v:
- ... pass
- >>> print clean_text_w_paths(str(v))
+ ... except config.ConfigurationConflictError as v:
+ ... print_(clean_text_w_paths(str(v)))
Conflicting configuration actions
For: (('x', 'blah'), ('y', 0))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
@@ -475,19 +472,19 @@
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 2))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 5.2-5.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 1))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
@@ -553,19 +550,19 @@
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 2))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 5.2-5.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 1))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
Finally, clean up.
@@ -597,19 +594,19 @@
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 2))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 5.2-5.24
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 1))
- >>> print clean_info_path(`data.info`)
+ >>> print_(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
Finally, clean up.
@@ -621,15 +618,29 @@
def test_suite():
+ checkers = []
+ if six.PY3:
+ checkers.extend([
+ (re.compile(r"b'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'b"([^"]*)"'),
+ r'"\1"'),
+ (re.compile(r"u'([^']*)'"),
+ r"'\1'"),
+ (re.compile(r'u"([^"]*)"'),
+ r'"\1"'),
+ ])
+ checker = renormalizing.RENormalizing(checkers)
return unittest.TestSuite((
- DocTestSuite('zope.configuration.xmlconfig'),
- DocTestSuite(),
+ unittest.findTestCases(sys.modules[__name__]),
+ DocTestSuite('zope.configuration.xmlconfig', checker=checker),
+ DocTestSuite(checker=checker),
DocFileSuite('../exclude.txt',
checker=renormalizing.RENormalizing([
(re.compile('include [^\n]+zope.configuration[\S+]'),
'include /zope.configuration\2'),
(re.compile(r'\\'), '/'),
- ]))
+ ] + checkers))
))
if __name__ == '__main__':
Index: src/zope/configuration/config.py
===================================================================
--- src/zope/configuration/config.py (.../trunk) (revision 125127)
+++ src/zope/configuration/config.py (.../branches/jinty-python3) (revision 125127)
@@ -16,11 +16,12 @@
See README.txt.
"""
__docformat__ = 'restructuredtext'
-import __builtin__
+from six.moves import builtins
import operator
import os.path
import sys
+import six
import zope.schema
from keyword import iskeyword
@@ -28,7 +29,7 @@
from zope.configuration.interfaces import IConfigurationContext
from zope.configuration.interfaces import IGroupingContext
from zope.interface.adapter import AdapterRegistry
-from zope.interface import Interface, implements, providedBy
+from zope.interface import Interface, implementer, providedBy
from zope.configuration import fields
@@ -121,8 +122,8 @@
1
>>> c.resolve('..interface') is zope.interface
1
- >>> c.resolve('unicode')
- <type 'unicode'>
+ >>> c.resolve('str') is str
+ True
"""
name = dottedname.strip()
@@ -140,7 +141,7 @@
if len(names) == 1:
# Check for built-in objects
marker = object()
- obj = getattr(__builtin__, names[0], marker)
+ obj = getattr(builtins, names[0], marker)
if obj is not marker:
return obj
@@ -176,7 +177,7 @@
try:
mod = __import__(mname, *_import_chickens)
- except ImportError, v:
+ except ImportError as v:
if sys.exc_info()[2].tb_next is not None:
# ImportError was caused deeper
raise
@@ -259,7 +260,7 @@
>>> c.checkDuplicate('/foo.zcml')
>>> try:
... c.checkDuplicate('/foo.zcml')
- ... except ConfigurationError, e:
+ ... except ConfigurationError as e:
... # On Linux the exact msg has /foo, on Windows \foo.
... str(e).endswith("foo.zcml' included more than once")
True
@@ -273,7 +274,7 @@
>>> c.checkDuplicate('bar.zcml')
>>> try:
... c.checkDuplicate(d + os.path.normpath('/bar.zcml'))
- ... except ConfigurationError, e:
+ ... except ConfigurationError as e:
... str(e).endswith("bar.zcml' included more than once")
...
True
@@ -542,7 +543,7 @@
r.register([interface], Interface, '', factory)
def document(self, name, schema, usedIn, handler, info, parent=None):
- if isinstance(name, (str, unicode)):
+ if isinstance(name, six.string_types):
name = ('', name)
self._docRegistry.append((name, schema, usedIn, handler, info, parent))
@@ -561,6 +562,7 @@
"The directive %s cannot be used in this context" % (name, ))
return f
+ at implementer(IConfigurationContext)
class ConfigurationMachine(ConfigurationAdapterRegistry, ConfigurationContext):
"""Configuration machine
@@ -593,8 +595,6 @@
A more extensive example can be found in the unit tests.
"""
- implements(IConfigurationContext)
-
package = None
basepath = None
includepath = ()
@@ -663,14 +663,10 @@
... ]
>>> try:
... v = context.execute_actions()
- ... except ConfigurationExecutionError, v:
- ... pass
- >>> print v
- exceptions.AttributeError: 'function' object has no attribute 'xxx'
- in:
- oops
+ ... except ConfigurationExecutionError as v:
+ ... six.print_(repr(v))
+ ConfigurationExecutionError()
-
Note that actions executed before the error still have an effect:
>>> output
@@ -696,7 +692,10 @@
raise
t, v, tb = sys.exc_info()
try:
- raise ConfigurationExecutionError(t, v, info), None, tb
+ six.reraise(
+ ConfigurationExecutionError,
+ ConfigurationExecutionError(t, v, info),
+ tb)
finally:
del t, v, tb
@@ -741,6 +740,7 @@
"""Finish processing a directive
"""
+ at implementer(IStackItem)
class SimpleStackItem(object):
"""Simple stack item
@@ -752,8 +752,6 @@
has been reached.
"""
- implements(IStackItem)
-
def __init__(self, context, handler, info, *argdata):
newcontext = GroupingContextDecorator(context)
newcontext.info = info
@@ -800,6 +798,7 @@
def finish(self):
pass
+ at implementer(IStackItem)
class GroupingStackItem(RootStackItem):
"""Stack item for a grouping directive
@@ -950,8 +949,6 @@
'order': 0}]
"""
- implements(IStackItem)
-
def __init__(self, context):
super(GroupingStackItem, self).__init__(context)
@@ -980,6 +977,7 @@
def noop():
pass
+ at implementer(IStackItem)
class ComplexStackItem(object):
"""Complex stack item
@@ -1056,25 +1054,22 @@
Note that the name passed to ``contained`` is a 2-part name, consisting of
a namespace and a name within the namespace.
- >>> from pprint import PrettyPrinter
- >>> pprint=PrettyPrinter(width=60).pprint
+ >>> context.actions == [{'args': (),
+ ... 'callable': f,
+ ... 'discriminator': 'init',
+ ... 'includepath': (),
+ ... 'info': 'foo',
+ ... 'kw': {},
+ ... 'order': 0},
+ ... {'args': (),
+ ... 'callable': f,
+ ... 'discriminator': ('sub', u'av', u'bv'),
+ ... 'includepath': (),
+ ... 'info': 'baz',
+ ... 'kw': {},
+ ... 'order': 0}]
+ True
- >>> pprint(context.actions)
- [{'args': (),
- 'callable': f,
- 'discriminator': 'init',
- 'includepath': (),
- 'info': 'foo',
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': f,
- 'discriminator': ('sub', u'av', u'bv'),
- 'includepath': (),
- 'info': 'baz',
- 'kw': {},
- 'order': 0}]
-
The new stack item returned by contained is one that doesn't allow
any more subdirectives,
@@ -1085,32 +1080,30 @@
The stack item will call the handler if it is callable.
- >>> pprint(context.actions)
- [{'args': (),
- 'callable': f,
- 'discriminator': 'init',
- 'includepath': (),
- 'info': 'foo',
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': f,
- 'discriminator': ('sub', u'av', u'bv'),
- 'includepath': (),
- 'info': 'baz',
- 'kw': {},
- 'order': 0},
- {'args': (),
- 'callable': f,
- 'discriminator': ('call', u'xv', u'yv'),
- 'includepath': (),
- 'info': 'foo',
- 'kw': {},
- 'order': 0}]
+ >>> context.actions == [{'args': (),
+ ... 'callable': f,
+ ... 'discriminator': 'init',
+ ... 'includepath': (),
+ ... 'info': 'foo',
+ ... 'kw': {},
+ ... 'order': 0},
+ ... {'args': (),
+ ... 'callable': f,
+ ... 'discriminator': ('sub', u'av', u'bv'),
+ ... 'includepath': (),
+ ... 'info': 'baz',
+ ... 'kw': {},
+ ... 'order': 0},
+ ... {'args': (),
+ ... 'callable': f,
+ ... 'discriminator': ('call', u'xv', u'yv'),
+ ... 'includepath': (),
+ ... 'info': 'foo',
+ ... 'kw': {},
+ ... 'order': 0}]
+ True
"""
- implements(IStackItem)
-
def __init__(self, meta, context, data, info):
newcontext = GroupingContextDecorator(context)
newcontext.info = info
@@ -1142,7 +1135,7 @@
try:
actions = self.handler()
- except AttributeError, v:
+ except AttributeError as v:
if v[0] == '__call__':
return # noncallable
raise
@@ -1159,14 +1152,13 @@
##############################################################################
# Helper classes
+ at implementer(IConfigurationContext, IGroupingContext)
class GroupingContextDecorator(ConfigurationContext):
"""Helper mix-in class for building grouping directives
See the discussion (and test) in GroupingStackItem.
"""
- implements(IConfigurationContext, IGroupingContext)
-
def __init__(self, context, **kw):
self.context = context
for name, v in kw.items():
@@ -1204,6 +1196,7 @@
class IDirectivesContext(IDirectivesInfo, IConfigurationContext):
pass
+ at implementer(IDirectivesContext)
class DirectivesHandler(GroupingContextDecorator):
"""Handler for the directives directive
@@ -1211,9 +1204,7 @@
to the normal directive context.
"""
- implements(IDirectivesContext)
-
class IDirectiveInfo(Interface):
"""Information common to all directive definitions have
"""
@@ -1377,14 +1368,13 @@
class IComplexDirectiveContext(IFullInfo, IConfigurationContext):
pass
+ at implementer(IComplexDirectiveContext)
class ComplexDirectiveDefinition(GroupingContextDecorator, dict):
"""Handler for defining complex directives
See the description and tests for ComplexStackItem.
"""
- implements(IComplexDirectiveContext)
-
def before(self):
def factory(context, data, info):
@@ -1557,14 +1547,16 @@
s = data.get(n, data)
if s is not data:
- s = unicode(s)
+ s = six.text_type(s)
del data[n]
try:
args[str(name)] = field.fromUnicode(s)
- except zope.schema.ValidationError, v:
- raise ConfigurationError(
- "Invalid value for", n, str(v)), None, sys.exc_info()[2]
+ except zope.schema.ValidationError as v:
+ six.reraise(
+ ConfigurationError,
+ ConfigurationError("Invalid value for", n, str(v)),
+ sys.exc_info()[2])
elif field.required:
# if the default is valid, we can use that:
default = field.default
@@ -1697,12 +1689,11 @@
def __str__(self):
r = ["Conflicting configuration actions"]
- items = self._conflicts.items()
- items.sort()
+ items = sorted(self._conflicts.items())
for discriminator, infos in items:
r.append(" For: %s" % (discriminator, ))
for info in infos:
- for line in unicode(info).rstrip().split(u'\n'):
+ for line in six.text_type(info).rstrip().split(u'\n'):
r.append(u" "+line)
return "\n".join(r)
Index: src/zope/configuration/docutils.py
===================================================================
--- src/zope/configuration/docutils.py (.../trunk) (revision 125127)
+++ src/zope/configuration/docutils.py (.../branches/jinty-python3) (revision 125127)
@@ -25,15 +25,16 @@
Examples:
- >>> print wrap('foo bar')[:-2]
+ >>> from six import print_
+ >>> print_(wrap('foo bar')[:-2])
foo bar
- >>> print wrap('foo bar', indent=2)[:-2]
+ >>> print_(wrap('foo bar', indent=2)[:-2])
foo bar
- >>> print wrap('foo bar, more foo bar', 10)[:-2]
+ >>> print_(wrap('foo bar, more foo bar', 10)[:-2])
foo bar,
more foo
bar
- >>> print wrap('foo bar, more foo bar', 10, 2)[:-2]
+ >>> print_(wrap('foo bar, more foo bar', 10, 2)[:-2])
foo bar,
more foo
bar
Index: src/zope/configuration/fields.py
===================================================================
--- src/zope/configuration/fields.py (.../trunk) (revision 125127)
+++ src/zope/configuration/fields.py (.../branches/jinty-python3) (revision 125127)
@@ -19,12 +19,13 @@
from zope.schema.interfaces import IFromUnicode
from zope.schema.interfaces import ConstraintNotSatisfied
from zope.configuration.exceptions import ConfigurationError
-from zope.interface import implements
+from zope.interface import implementer
from zope.configuration.interfaces import InvalidToken
PYIDENTIFIER_REGEX = u'\\A[a-zA-Z_]+[a-zA-Z0-9_]*\\Z'
pyidentifierPattern = re.compile(PYIDENTIFIER_REGEX)
+ at implementer(IFromUnicode)
class PythonIdentifier(schema.TextLine):
r"""This field describes a python identifier, i.e. a variable name.
@@ -50,20 +51,19 @@
... field._validate(value)
>>>
>>> from zope import schema
+ >>> from six import print_
>>>
>>> for value in (u'3foo', u'foo:', u'\\', u''):
... try:
... field._validate(value)
... except schema.ValidationError:
- ... print 'Validation Error'
+ ... print_('Validation Error')
Validation Error
Validation Error
Validation Error
Validation Error
"""
- implements(IFromUnicode)
-
def fromUnicode(self, u):
return u.strip()
@@ -72,6 +72,7 @@
if pyidentifierPattern.match(value) is None:
raise schema.ValidationError(value)
+ at implementer(IFromUnicode)
class GlobalObject(schema.Field):
"""An object that can be accessed as a module global.
@@ -115,8 +116,6 @@
"""
- implements(IFromUnicode)
-
def __init__(self, value_type=None, **kw):
self.value_type = value_type
super(GlobalObject, self).__init__(**kw)
@@ -135,7 +134,7 @@
try:
value = self.context.resolve(name)
- except ConfigurationError, v:
+ except ConfigurationError as v:
raise schema.ValidationError(v)
self.validate(value)
@@ -175,6 +174,7 @@
def __init__(self, **kw):
super(GlobalInterface, self).__init__(schema.InterfaceField(), **kw)
+ at implementer(IFromUnicode)
class Tokens(schema.List):
"""A list that can be read from a space-separated string
@@ -215,7 +215,6 @@
>>>
"""
- implements(IFromUnicode)
def fromUnicode(self, u):
u = u.strip()
@@ -225,7 +224,7 @@
for s in u.split():
try:
v = vt.fromUnicode(s)
- except schema.ValidationError, v:
+ except schema.ValidationError as v:
raise InvalidToken("%s in %s" % (v, u))
else:
values.append(v)
@@ -236,6 +235,7 @@
return values
+ at implementer(IFromUnicode)
class Path(schema.Text):
r"""A file path name, which may be input as a relative path
@@ -248,6 +248,7 @@
We'll be careful to do this in an os-independent fashion.
+ >>> import six
>>> class FauxContext(object):
... def path(self, p):
... return os.path.join(os.sep, 'faux', 'context', p)
@@ -257,7 +258,7 @@
Lets try an absolute path first:
- >>> p = unicode(os.path.join(os.sep, 'a', 'b'))
+ >>> p = six.text_type(os.path.join(os.sep, 'a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
[u'', u'a', u'b']
@@ -271,7 +272,7 @@
Now try a relative path:
- >>> p = unicode(os.path.join('a', 'b'))
+ >>> p = six.text_type(os.path.join('a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
[u'', u'faux', u'context', u'a', u'b']
@@ -279,8 +280,6 @@
"""
- implements(IFromUnicode)
-
def fromUnicode(self, u):
u = u.strip()
if os.path.isabs(u):
@@ -289,6 +288,7 @@
return self.context.path(u)
+ at implementer(IFromUnicode)
class Bool(schema.Bool):
"""A boolean value
@@ -305,8 +305,6 @@
0
"""
- implements(IFromUnicode)
-
def fromUnicode(self, u):
u = u.lower()
if u in ('1', 'true', 'yes', 't', 'y'):
@@ -315,6 +313,7 @@
return False
raise schema.ValidationError
+ at implementer(IFromUnicode)
class MessageID(schema.Text):
"""Text string that should be translated.
@@ -377,15 +376,13 @@
>>> i = field.fromUnicode(u"Foo Bar")
>>> i = field.fromUnicode(u"Hello world!")
- >>> from pprint import PrettyPrinter
- >>> pprint=PrettyPrinter(width=70).pprint
- >>> pprint(context.i18n_strings)
- {'testing': {u'Foo Bar': [('file location', 8)],
- u'Hello world!': [('file location', 8),
- ('file location', 8)]}}
+ >>> context.i18n_strings == {'testing': {u'Foo Bar': [('file location', 8)],
+ ... u'Hello world!': [('file location', 8),
+ ... ('file location', 8)]}}
+ True
>>> from zope.i18nmessageid import Message
- >>> isinstance(context.i18n_strings['testing'].keys()[0], Message)
+ >>> isinstance(list(context.i18n_strings['testing'].keys())[0], Message)
1
Explicit Message IDs
@@ -403,8 +400,6 @@
True
"""
- implements(IFromUnicode)
-
__factories = {}
def fromUnicode(self, u):
Index: src/zope/configuration/xmlconfig.py
===================================================================
--- src/zope/configuration/xmlconfig.py (.../trunk) (revision 125127)
+++ src/zope/configuration/xmlconfig.py (.../branches/jinty-python3) (revision 125127)
@@ -25,6 +25,7 @@
import logging
import zope.configuration.config as config
+import six
from glob import glob
from xml.sax import make_parser
from xml.sax.xmlreader import InputSource
@@ -48,7 +49,7 @@
info and the wrapped error type and value:
>>> v = ZopeXMLConfigurationError("blah", AttributeError, "xxx")
- >>> print v
+ >>> six.print_(v)
'blah'
AttributeError: xxx
@@ -61,13 +62,13 @@
# Only use the repr of the info. This is because we expect to
# get a parse info and we only want the location information.
return "%s\n %s: %s" % (
- `self.info`, self.etype.__name__, self.evalue)
+ repr(self.info), self.etype.__name__, self.evalue)
class ZopeSAXParseException(ConfigurationError):
"""Sax Parser errors, reformatted in an emacs friendly way
>>> v = ZopeSAXParseException("foo.xml:12:3:Not well formed")
- >>> print v
+ >>> six.print_(v)
File "foo.xml", line 12.3, Not well formed
"""
@@ -93,7 +94,7 @@
>>> info
File "tests//sample.zcml", line 1.0
- >>> print info
+ >>> six.print_(info)
File "tests//sample.zcml", line 1.0
>>> info.characters("blah\\n")
@@ -105,7 +106,7 @@
>>> info
File "tests//sample.zcml", line 1.0-7.0
- >>> print info
+ >>> six.print_(info)
File "tests//sample.zcml", line 1.0-7.0
<configure xmlns='http://namespaces.zope.org/zope'>
<!-- zope.configure -->
@@ -151,7 +152,8 @@
except IOError:
src = " Could not read source."
else:
- lines = f.readlines()[self.line-1:self.eline]
+ with f:
+ lines = f.readlines()[self.line-1:self.eline]
ecolumn = self.ecolumn
if lines[-1][ecolumn:ecolumn+2] == '</':
# We're pointing to the start of an end tag. Try to find
@@ -177,7 +179,7 @@
# unicode won't be printable, at least on my console
src = src.encode('ascii','replace')
- return "%s\n%s" % (`self`, src)
+ return "%s\n%s" % (repr(self), src)
def characters(self, characters):
self.text += characters
@@ -235,8 +237,10 @@
except:
if self.testing:
raise
- raise ZopeXMLConfigurationError(info, sys.exc_info()[0],
- sys.exc_info()[1]), None, sys.exc_info()[2]
+ six.reraise(
+ ZopeXMLConfigurationError,
+ ZopeXMLConfigurationError(info, sys.exc_info()[0], sys.exc_info()[1]),
+ sys.exc_info()[2])
self.context.setInfo(info)
@@ -362,8 +366,9 @@
except:
if self.testing:
raise
- raise ZopeXMLConfigurationError(info, sys.exc_info()[0],
- sys.exc_info()[1]), None, sys.exc_info()[2]
+ six.reraise(ZopeXMLConfigurationError,
+ ZopeXMLConfigurationError(info, sys.exc_info()[0], sys.exc_info()[1]),
+ sys.exc_info()[2])
def processxmlfile(file, context, testing=False):
@@ -379,7 +384,10 @@
try:
parser.parse(src)
except SAXParseException:
- raise ZopeSAXParseException(sys.exc_info()[1]), None, sys.exc_info()[2]
+ six.reraise(
+ ZopeSAXParseException,
+ ZopeSAXParseException(sys.exc_info()[1]),
+ sys.exc_info()[2])
def openInOrPlain(filename):
@@ -399,16 +407,16 @@
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, 'tests', 'samplepackage', 'configure.zcml')
- >>> f = openInOrPlain(path)
- >>> f.name[-14:]
+ >>> with openInOrPlain(path) as f:
+ ... f.name[-14:]
'configure.zcml'
But if we open foo.zcml, we'll get foo.zcml.in, since there isn't a
foo.zcml:
>>> path = os.path.join(here, 'tests', 'samplepackage', 'foo.zcml')
- >>> f = openInOrPlain(path)
- >>> f.name[-11:]
+ >>> with openInOrPlain(path) as f:
+ ... f.name[-11:]
'foo.zcml.in'
Make sure other IOErrors are re-raised. We need to do this in a
@@ -418,17 +426,17 @@
>>> try:
... f = openInOrPlain('.')
... except IOError:
- ... print "passed"
+ ... six.print_("passed")
... else:
- ... print "failed"
...
+ ... six.print_("failed")
passed
"""
try:
fp = open(filename)
- except IOError, (code, msg):
- if code == errno.ENOENT:
+ except IOError as e:
+ if e.errno == errno.ENOENT:
fn = filename + ".in"
if os.path.exists(fn):
fp = open(fn)
@@ -446,7 +454,7 @@
files in each package and then link them together.
"""
- file = schema.BytesLine(
+ file = schema.NativeStringLine(
title=u"Configuration file name",
description=u"The name of a configuration file to be included/excluded, "
u"relative to the directive containing the "
@@ -454,7 +462,7 @@
required=False,
)
- files = schema.BytesLine(
+ files = schema.NativeStringLine(
title=u"Configuration file name pattern",
description=u"""
The names of multiple configuration files to be included/excluded,
@@ -530,23 +538,21 @@
if files:
paths = glob(context.path(files))
- paths = zip([path.lower() for path in paths], paths)
- paths.sort()
+ paths = sorted(zip([path.lower() for path in paths], paths))
paths = [path for (l, path) in paths]
else:
paths = [context.path(file)]
for path in paths:
if context.processFile(path):
- f = openInOrPlain(path)
- logger.debug("include %s" % f.name)
+ with openInOrPlain(path) as f:
+ logger.debug("include %s" % f.name)
- context.basepath = os.path.dirname(path)
- context.includepath = _context.includepath + (f.name, )
- _context.stack.append(config.GroupingStackItem(context))
+ context.basepath = os.path.dirname(path)
+ context.includepath = _context.includepath + (f.name, )
+ _context.stack.append(config.GroupingStackItem(context))
- processxmlfile(f, context)
- f.close()
+ processxmlfile(f, context)
assert _context.stack[-1].context is context
_context.stack.pop()
@@ -571,8 +577,7 @@
if files:
paths = glob(context.path(files))
- paths = zip([path.lower() for path in paths], paths)
- paths.sort()
+ paths = sorted(zip([path.lower() for path in paths], paths))
paths = [path for (l, path) in paths]
else:
paths = [context.path(file)]
@@ -652,7 +657,7 @@
def string(s, context=None, name="<string>", execute=True):
"""Execute a zcml string
"""
- from StringIO import StringIO
+ from six import StringIO
if context is None:
context = config.ConfigurationMachine()
Index: src/zope/configuration/stxdocs.py
===================================================================
--- src/zope/configuration/stxdocs.py (.../trunk) (revision 125127)
+++ src/zope/configuration/stxdocs.py (.../branches/jinty-python3) (revision 125127)
@@ -28,6 +28,7 @@
sub-directories with files in them.
"""
import sys, os, getopt
+from six import print_
import zope.configuration
from zope.schema import getFieldsInOrder
from zope.configuration import config, xmlconfig
@@ -35,9 +36,9 @@
def usage(code, msg=''):
# Python 2.1 required
- print >> sys.stderr, __doc__
+ print_(__doc__, file=sys.stderr)
if msg:
- print >> sys.stderr, msg
+ print_(msg, file=sys.stderr)
sys.exit(code)
def _directiveDocs(name, schema, handler, info, indent_offset=0):
@@ -88,7 +89,7 @@
def _subDirectiveDocs(subdirs, namespace, name):
"""Appends a list of sub-directives and their full specification."""
- if subdirs.has_key((namespace, name)):
+ if (namespace, name) in subdirs:
text = '\n Subdirectives\n\n'
sub_dirs = []
# Simply walk through all sub-directives here.
@@ -127,7 +128,7 @@
if not path == os.path.abspath(path):
cwd = os.getcwd()
# This is for symlinks.
- if os.environ.has_key('PWD'):
+ if 'PWD' in os.environ:
cwd = os.environ['PWD']
path = os.path.normpath(os.path.join(cwd, path))
return path
@@ -138,7 +139,7 @@
sys.argv[1:],
'h:f:o:',
['help'])
- except getopt.error, msg:
+ except getopt.error as msg:
usage(1, msg)
zcml_file = None
Index: MANIFEST.in
===================================================================
--- MANIFEST.in (.../trunk) (revision 0)
+++ MANIFEST.in (.../branches/jinty-python3) (revision 125127)
@@ -0,0 +1,2 @@
+include *.txt
+recursive-include src/zope/configuration *.txt *.zcml *.zcml.in
More information about the Zope-Dev
mailing list