summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2018-09-22 09:33:59 -0500
committerJason Madden <jamadden@gmail.com>2018-09-22 09:45:01 -0500
commitf4af820b7d11f421e0dbe06c603a16180ad7aa0a (patch)
treebce500165e5b9f6ccbed0cf157c07f057638c936
parent7174ee9d98d09d817b12ad3be585ba08e2b33614 (diff)
downloadzope-configuration-f4af820b7d11f421e0dbe06c603a16180ad7aa0a.tar.gz
Fix the doctests with newer zope.schema; run them on Py 2 and Py3
Fixes #21 Include them as part of the normal test run (using manuel, because plain doctest doesn't accept absolute paths). Switch Sphinx to run them under Python 3. We can use a checker as part of the normal test run, but not under Sphinx, so normalize the output for Python 3.
-rw-r--r--CHANGES.rst3
-rw-r--r--docs/api/config.rst50
-rw-r--r--docs/api/docutils.rst8
-rw-r--r--docs/api/fields.rst39
-rw-r--r--docs/api/xmlconfig.rst18
-rw-r--r--docs/narr.rst169
-rw-r--r--setup.py5
-rw-r--r--src/zope/__init__.py2
-rw-r--r--src/zope/configuration/tests/directives.py19
-rw-r--r--src/zope/configuration/tests/nested.py12
-rw-r--r--src/zope/configuration/tests/schema.zcml10
-rw-r--r--src/zope/configuration/tests/test_config.py8
-rw-r--r--src/zope/configuration/tests/test_docs.py87
-rw-r--r--src/zope/configuration/tests/test_xmlconfig.py16
-rw-r--r--tox.ini2
15 files changed, 271 insertions, 177 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index e242fea..3bab7f1 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -17,6 +17,9 @@ Changes
``__getattr__``. These were not intended as arguments to be used by
subclasses, and the signature caused confusion.
+- Fix the doctests with zope.schema 4.7 and above, and run the
+ doctests on both Python 2 and Python 3. See `issue 21
+ <https://github.com/zopefoundation/zope.configuration/issues/21>`_.
4.1.0 (2017-04-26)
------------------
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 1c37ec0..c1a5662 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -37,8 +37,8 @@
True
>>> c.resolve('..interface') is zope.interface
True
- >>> c.resolve('str')
- <type 'str'>
+ >>> c.resolve('str') is str
+ True
.. automethod:: path
@@ -349,9 +349,9 @@
>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(width=60).pprint
>>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
+ [{'args': ('aa', 'xxx', 'cc'),
'callable': f,
- 'discriminator': ('simple', u'aa', u'xxx', 'cc'),
+ 'discriminator': ('simple', 'aa', 'xxx', 'cc'),
'includepath': (),
'info': None,
'kw': {},
@@ -404,10 +404,10 @@
... ]
>>> try:
... v = context.execute_actions()
- ... except ConfigurationExecutionError as v:
- ... pass
+ ... except ConfigurationExecutionError as e:
+ ... v = e
>>> lines = str(v).splitlines()
- >>> 'exceptions.AttributeError' in lines[0]
+ >>> 'AttributeError' in lines[0]
True
>>> lines[0].endswith("'function' object has no attribute 'xxx'")
True
@@ -708,7 +708,7 @@
'order': 0},
{'args': (),
'callable': f,
- 'discriminator': ('sub', u'av', u'bv'),
+ 'discriminator': ('sub', 'av', 'bv'),
'includepath': (),
'info': 'baz',
'kw': {},
@@ -738,14 +738,14 @@
'order': 0},
{'args': (),
'callable': f,
- 'discriminator': ('sub', u'av', u'bv'),
+ 'discriminator': ('sub', 'av', 'bv'),
'includepath': (),
'info': 'baz',
'kw': {},
'order': 0},
{'args': (),
'callable': f,
- 'discriminator': ('call', u'xv', u'yv'),
+ 'discriminator': ('call', 'xv', 'yv'),
'includepath': (),
'info': 'foo',
'kw': {},
@@ -809,7 +809,7 @@
>>> pprint(context.actions)
[{'args': (),
'callable': f,
- 'discriminator': ('s', u'vx', u'vy'),
+ 'discriminator': ('s', 'vx', 'vy'),
'includepath': (),
'info': None,
'kw': {},
@@ -827,7 +827,7 @@
>>> pprint(context.actions)
[{'args': (),
'callable': f,
- 'discriminator': ('s', u'vx', u'vy'),
+ 'discriminator': ('s', 'vx', 'vy'),
'includepath': (),
'info': None,
'kw': {},
@@ -861,9 +861,9 @@
>>> context.begin((testns, "g"), x=u"vx", y=u"vy")
>>> context.stack[-1].context.x
- u'vx'
+ 'vx'
>>> context.stack[-1].context.y
- u'vy'
+ 'vy'
>>> context(('http://www.zope.com/t1', "g"), x=u"vx", y=u"vy")
Traceback (most recent call last):
@@ -876,9 +876,9 @@
>>> context.begin(('http://www.zope.com/t1', "g"), x=u"vx", y=u"vy")
>>> context.stack[-1].context.x
- u'vx'
+ 'vx'
>>> context.stack[-1].context.y
- u'vy'
+ 'vy'
.. autointerface:: IComplexDirectiveContext
:members:
@@ -948,9 +948,9 @@
... 'u': u'http://www.zope.org' }))
{'f': 1.2,
'in_': 1,
- 'n': u'bob',
+ 'n': 'bob',
'u': 'http://www.zope.org',
- 'x': 'x.y.z'}
+ 'x': b'x.y.z'}
If we have extra data, we'll get an error:
@@ -972,12 +972,12 @@
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob', 'x': u'x.y.z',
... 'u': u'http://www.zope.org', 'a': u'1'}))
- {'a': u'1',
+ {'a': '1',
'f': 1.2,
'in_': 1,
- 'n': u'bob',
+ 'n': 'bob',
'u': 'http://www.zope.org',
- 'x': 'x.y.z'}
+ 'x': b'x.y.z'}
If we omit required data we get an error telling us what was omitted:
@@ -996,10 +996,10 @@
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2', 'n': u'bob',
... 'u': u'http://www.zope.org', 'a': u'1'}))
- {'a': u'1',
+ {'a': '1',
'f': 1.2,
'in_': 1,
- 'n': u'bob',
+ 'n': 'bob',
'u': 'http://www.zope.org'}
And we can omit required fields if they have valid defaults
@@ -1010,10 +1010,10 @@
>>> pprint(toargs(context, schema,
... {'in': u'1', 'f': u'1.2',
... 'u': u'http://www.zope.org', 'a': u'1'}))
- {'a': u'1',
+ {'a': '1',
'f': 1.2,
'in_': 1,
- 'n': u'rob',
+ 'n': 'rob',
'u': 'http://www.zope.org'}
We also get an error if any data was invalid:
diff --git a/docs/api/docutils.rst b/docs/api/docutils.rst
index d83c213..b75830c 100644
--- a/docs/api/docutils.rst
+++ b/docs/api/docutils.rst
@@ -10,15 +10,15 @@
.. doctest::
>>> from zope.configuration.docutils import wrap
- >>> print wrap('foo bar')[:-2]
+ >>> 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
diff --git a/docs/api/fields.rst b/docs/api/fields.rst
index c4e0995..f7c65cd 100644
--- a/docs/api/fields.rst
+++ b/docs/api/fields.rst
@@ -22,11 +22,11 @@
.. doctest::
>>> field.fromUnicode(u'foo')
- u'foo'
+ 'foo'
>>> field.fromUnicode(u'foo3')
- u'foo3'
+ 'foo3'
>>> field.fromUnicode(u'_foo3')
- u'_foo3'
+ '_foo3'
Now let's see whether validation works alright
@@ -39,7 +39,7 @@
... try:
... field._validate(value)
... except ValidationError:
- ... print 'Validation Error'
+ ... print('Validation Error')
Validation Error
Validation Error
Validation Error
@@ -84,7 +84,7 @@
42
>>> g = GlobalObject()
>>> gg = g.bind(fake)
- >>> print gg.fromUnicode('*')
+ >>> print(gg.fromUnicode('*'))
None
.. autoclass:: GlobalInterface
@@ -122,7 +122,7 @@
>>> gg.fromUnicode('Foo')
Traceback (most recent call last):
...
- WrongType: ('An interface is required', ...
+ NotAnInterface: (<class 'Foo'>, ...
.. autoclass:: Tokens
:members:
@@ -189,10 +189,11 @@
.. doctest::
>>> import os
+ >>> from zope.configuration._compat import u as unicode
>>> p = unicode(os.path.join(os.sep, 'a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
- [u'', u'a', u'b']
+ ['', 'a', 'b']
This should also work with extra spaces around the path:
@@ -201,7 +202,7 @@
>>> p = " \n %s \n\n " % p
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
- [u'', u'a', u'b']
+ ['', 'a', 'b']
Now try a relative path:
@@ -210,7 +211,7 @@
>>> p = unicode(os.path.join('a', 'b'))
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
- [u'', u'faux', u'context', u'a', u'b']
+ ['', 'faux', 'context', 'a', 'b']
.. autoclass:: Bool
:members:
@@ -262,7 +263,7 @@
>>> i = field.fromUnicode(u"Hello world!")
>>> i
- u'Hello world!'
+ 'Hello world!'
>>> i.domain
'untranslated'
>>> warned
@@ -283,7 +284,7 @@
>>> i = field.fromUnicode(u"Hello world!")
>>> i
- u'Hello world!'
+ 'Hello world!'
>>> i.domain
'testing'
@@ -292,19 +293,19 @@
.. doctest::
>>> context.i18n_strings
- {'testing': {u'Hello world!': [('file location', 8)]}}
+ {'testing': {'Hello world!': [('file location', 8)]}}
>>> 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)]}}
+ {'testing': {'Foo Bar': [('file location', 8)],
+ 'Hello world!': [('file location', 8),
+ ('file location', 8)]}}
>>> from zope.i18nmessageid import Message
- >>> isinstance(context.i18n_strings['testing'].keys()[0], Message)
+ >>> isinstance(list(context.i18n_strings['testing'].keys())[0], Message)
True
Explicit Message IDs
@@ -313,12 +314,12 @@
>>> i = field.fromUnicode(u'[View-Permission] View')
>>> i
- u'View-Permission'
+ 'View-Permission'
>>> i.default
- u'View'
+ 'View'
>>> i = field.fromUnicode(u'[] [Some] text')
>>> i
- u'[Some] text'
+ '[Some] text'
>>> i.default is None
True
diff --git a/docs/api/xmlconfig.rst b/docs/api/xmlconfig.rst
index 943ee22..63b94f5 100644
--- a/docs/api/xmlconfig.rst
+++ b/docs/api/xmlconfig.rst
@@ -11,7 +11,7 @@
>>> from zope.configuration.xmlconfig import ZopeXMLConfigurationError
>>> v = ZopeXMLConfigurationError("blah", AttributeError, "xxx")
- >>> print v
+ >>> print(v)
'blah'
AttributeError: xxx
@@ -23,7 +23,7 @@
>>> from zope.configuration.xmlconfig import ZopeSAXParseException
>>> v = ZopeSAXParseException("foo.xml:12:3:Not well formed")
- >>> print v
+ >>> print(v)
File "foo.xml", line 12.3, Not well formed
.. autoclass:: ParserInfo
@@ -39,19 +39,19 @@
>>> info
File "tests//sample.zcml", line 1.0
- >>> print info
+ >>> print(info)
File "tests//sample.zcml", line 1.0
>>> info.characters("blah\\n")
>>> info.characters("blah")
>>> info.text
- u'blah\\nblah'
+ 'blah\\nblah'
>>> info.end(7, 0)
>>> info
File "tests//sample.zcml", line 1.0-7.0
- >>> print info
+ >>> print(info)
File "tests//sample.zcml", line 1.0-7.0
<configure xmlns='http://namespaces.zope.org/zope'>
<!-- zope.configure -->
@@ -106,7 +106,7 @@
The ``installed`` and ``not-installed`` verbs each take one argument:
the dotted name of a pacakge.
-
+
If the pacakge is found, in other words, can be imported,
then the condition will return true / false:
@@ -159,6 +159,7 @@
>>> f = openInOrPlain(path)
>>> f.name[-14:]
'configure.zcml'
+ >>> f.close()
But if we open foo.zcml, we'll get foo.zcml.in, since there isn't a
foo.zcml:
@@ -169,6 +170,7 @@
>>> f = openInOrPlain(path)
>>> f.name[-11:]
'foo.zcml.in'
+ >>> f.close()
Make sure other IOErrors are re-raised. We need to do this in a
try-except block because different errors are raised on Windows and
@@ -179,9 +181,9 @@
>>> try:
... f = openInOrPlain('.')
... except IOError:
- ... print "passed"
+ ... print("passed")
... else:
- ... print "failed"
+ ... print("failed")
passed
.. autointerface:: IInclude
diff --git a/docs/narr.rst b/docs/narr.rst
index 8cbb8a7..0a0dba1 100644
--- a/docs/narr.rst
+++ b/docs/narr.rst
@@ -57,7 +57,7 @@ the directive. There are four kinds of directives:
To learn how to implement nested directives, look at the
documentation in the "Creating Nested Directives" section below.
-- Complex directives are directives that have subdirectives.
+- Complex directives are directives that have subdirectives.
Subdirectives have handlers that are simply methods of complex
directives. Complex diretives are handled by factories, typically
classes, that create objects that have methods for handling
@@ -76,7 +76,7 @@ the directive. There are four kinds of directives:
.. todo::
Flesh out narrative docs.
-
+
Using the configuration machinery programatically
==================================================
@@ -132,24 +132,24 @@ and try them out:
>>> machine((ns, "newsimple"), "second", a=u"naa", c=u"ncc", b=u"nbb")
>>> from pprint import PrettyPrinter
- >>> pprint = PrettyPrinter(width=50).pprint
+ >>> pprint = PrettyPrinter(width=48).pprint
>>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
+ [{'args': ('aa', 'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
- u'aa',
- u'xxx',
+ 'aa',
+ 'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
+ {'args': ('naa', 'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
- u'naa',
- u'nbb',
+ 'naa',
+ 'nbb',
'ncc'),
'includepath': (),
'info': 'second',
@@ -204,21 +204,21 @@ it:
>>> machine.end()
>>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
+ [{'args': ('aa', 'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
- u'aa',
- u'xxx',
+ 'aa',
+ 'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
+ {'args': ('naa', 'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
- u'naa',
- u'nbb',
+ 'naa',
+ 'nbb',
'ncc'),
'includepath': (),
'info': 'second',
@@ -238,14 +238,14 @@ it:
'info': 'third',
'kw': {},
'order': 0},
- {'args': (u'ca',),
+ {'args': ('ca',),
'callable': f,
'discriminator': ('Complex.factory', 1, 2),
'includepath': (),
'info': 'fourth',
'kw': {},
'order': 0},
- {'args': (u'xxx', 'cc'),
+ {'args': ('xxx', 'cc'),
'callable': f,
'discriminator': ('Complex', 1, 2),
'includepath': (),
@@ -278,21 +278,21 @@ inside a package directive:
""" "Can't use leading dots in dotted names, no package has been set.")
>>> pprint(machine.actions)
- [{'args': (u'aa', u'xxx', 'cc'),
+ [{'args': ('aa', 'xxx', 'cc'),
'callable': f,
'discriminator': ('simple',
- u'aa',
- u'xxx',
+ 'aa',
+ 'xxx',
'cc'),
'includepath': (),
'info': 'first',
'kw': {},
'order': 0},
- {'args': (u'naa', u'nbb', 'ncc'),
+ {'args': ('naa', 'nbb', 'ncc'),
'callable': f,
'discriminator': ('newsimple',
- u'naa',
- u'nbb',
+ 'naa',
+ 'nbb',
'ncc'),
'includepath': (),
'info': 'second',
@@ -312,25 +312,25 @@ inside a package directive:
'info': 'third',
'kw': {},
'order': 0},
- {'args': (u'ca',),
+ {'args': ('ca',),
'callable': f,
'discriminator': ('Complex.factory', 1, 2),
'includepath': (),
'info': 'fourth',
'kw': {},
'order': 0},
- {'args': (u'xxx', 'cc'),
+ {'args': ('xxx', 'cc'),
'callable': f,
'discriminator': ('Complex', 1, 2),
'includepath': (),
'info': 'third',
'kw': {},
'order': 0},
- {'args': (u'oaa', u'obb', 'occ'),
+ {'args': ('oaa', 'obb', 'occ'),
'callable': f,
'discriminator': ('simple',
- u'oaa',
- u'obb',
+ 'oaa',
+ 'obb',
'occ'),
'includepath': (),
'info': None,
@@ -355,10 +355,10 @@ Look at the file ``bar.zcml`` (in ``zope/configuration/tests/samplepackage``):
- ``bar1.zcml`` includes ``configure.zcml`` and has a ``foo``
directive.
-
+
- ``bar2.zcml`` includes ``bar21.zcml``, and has a ``foo``
directive that conflicts with one in ``bar1.zcml``.
-
+
- ``bar2.zcml`` also overrides a foo directive in ``bar21.zcml``.
- ``bar21.zcml`` has a ``foo`` directive that conflicts with one in in
@@ -385,32 +385,32 @@ So far so good, let's look at the configuration actions:
.. doctest::
>>> from zope.configuration.tests.test_xmlconfig import clean_actions
- >>> pprint = PrettyPrinter(width=70).pprint
+ >>> pprint = PrettyPrinter(width=72).pprint
>>> pprint(clean_actions(context.actions))
- [{'discriminator': (('x', 'blah'), ('y', 0)),
+ [{'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 0)),
+ {'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml',
'tests/samplepackage/bar21.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
- {'discriminator': (('x', 'blah'), ('y', 2)),
+ {'discriminator': (('x', b'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml',
'tests/samplepackage/bar21.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 4.2-4.24'},
- {'discriminator': (('x', 'blah'), ('y', 2)),
+ {'discriminator': (('x', b'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/bar.zcml',
'tests/samplepackage/bar2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
@@ -425,16 +425,16 @@ we'll find if we try to execuse the actions:
>>> from zope.configuration.tests.test_xmlconfig import clean_text_w_paths
>>> try:
... v = context.execute_actions()
- ... except ConfigurationConflictError, v:
- ... pass
- >>> print clean_text_w_paths(str(v))
+ ... except ConfigurationConflictError as e:
+ ... v = e
+ >>> print(clean_text_w_paths(str(v)))
Conflicting configuration actions
- For: (('x', 'blah'), ('y', 0))
+ For: (('x', b'blah'), ('y', 0))
File "tests/samplepackage/configure.zcml", line 12.2-12.29
<test:foo x="blah" y="0" />
File "tests/samplepackage/bar21.zcml", line 3.2-3.24
<foo x="blah" y="0" />
- For: (('x', 'blah'), ('y', 1))
+ For: (('x', b'blah'), ('y', 1))
File "tests/samplepackage/bar1.zcml", line 5.2-5.24
<foo x="blah" y="1" />
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
@@ -458,22 +458,22 @@ Now, if we look at the actions:
.. doctest::
>>> pprint(clean_actions(context.actions))
- [{'discriminator': (('x', 'blah'), ('y', 0)),
+ [{'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 0)),
+ {'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
- {'discriminator': (('x', 'blah'), ('y', 2)),
+ {'discriminator': (('x', b'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
@@ -505,20 +505,20 @@ We should now have three entries in foo.data:
>>> data = foo.data.pop(0)
>>> data.args
- (('x', 'blah'), ('y', 0))
- >>> print clean_info_path(`data.info`)
+ (('x', b'blah'), ('y', 0))
+ >>> 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`)
+ (('x', b'blah'), ('y', 2))
+ >>> 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`)
+ (('x', b'blah'), ('y', 1))
+ >>> print(clean_info_path(repr(data.info)))
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
@@ -538,22 +538,22 @@ Actions look like above:
.. doctest::
>>> pprint(clean_actions(context.actions))
- [{'discriminator': (('x', 'blah'), ('y', 0)),
+ [{'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro2.zcml',
'tests/samplepackage/bar1.zcml',
'tests/samplepackage/configure.zcml'],
'info': 'File "tests/samplepackage/configure.zcml", line 12.2-12.29'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro2.zcml',
'tests/samplepackage/bar1.zcml'],
'info': 'File "tests/samplepackage/bar1.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 0)),
+ {'discriminator': (('x', b'blah'), ('y', 0)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
- {'discriminator': (('x', 'blah'), ('y', 2)),
+ {'discriminator': (('x', b'blah'), ('y', 2)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
- {'discriminator': (('x', 'blah'), ('y', 1)),
+ {'discriminator': (('x', b'blah'), ('y', 1)),
'includepath': ['tests/samplepackage/baro2.zcml'],
'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]
@@ -676,7 +676,7 @@ We'll set a log handler so we can see what's going on:
>>> logger.setLevel(logging.DEBUG)
>>> handler = logging.handlers.MemoryHandler(10)
>>> logger.addHandler(handler)
-
+
Now, we'll include the zope.configuration.tests.excludedemo config:
.. doctest::
@@ -809,7 +809,7 @@ Our handler is given in the function,
It takes a context, a path and a title. All directive handlers take the
directive context as the first argument. A directive context, at a minimim,
-implements, ``zope.configuration.IConfigurationContext``.
+implements, ``zope.configuration.IConfigurationContext``.
(Specialized contexts can implement more specific interfaces. We'll say more
about that when we talk about grouping directives.) The title argument
must have a default value, because we indicated that the title was not
@@ -883,13 +883,13 @@ Now we should see some file information in the registry:
>>> from zope.configuration.tests.test_xmlconfig import clean_text_w_paths
>>> from zope.configuration.tests.test_xmlconfig import clean_path
- >>> print clean_path(file_registry[0].path)
+ >>> print(clean_path(file_registry[0].path))
tests/simple.py
- >>> print file_registry[0].title
+ >>> print(file_registry[0].title)
How to create a simple directive
- >>> print file_registry[0].description
+ >>> print(file_registry[0].description)
Describes how to implement a simple directive
- >>> print clean_text_w_paths(file_registry[0].info)
+ >>> print(clean_text_w_paths(file_registry[0].info))
File "tests/simple.zcml", line 19.2-24.2
<files:register
path="simple.py"
@@ -897,29 +897,29 @@ Now we should see some file information in the registry:
>
Describes how to implement a simple directive
</files:register>
- >>> print clean_path(file_registry[1].path)
+ >>> print(clean_path(file_registry[1].path))
tests/simple.zcml
- >>> print file_registry[1].title
+ >>> print(file_registry[1].title)
<BLANKLINE>
>>> desc = file_registry[1].description
- >>> print '\n'.join([l.rstrip()
+ >>> print('\n'.join([l.rstrip()
... for l in desc.strip().splitlines()
- ... if l.rstrip()])
+ ... if l.rstrip()]))
Shows the ZCML directives needed to register a simple directive.
Also show some usage examples,
- >>> print clean_text_w_paths(file_registry[1].info)
+ >>> print(clean_text_w_paths(file_registry[1].info))
File "tests/simple.zcml", line 26.2-30.2
<files:register path="simple.zcml">
Shows the ZCML directives needed to register a simple directive.
Also show some usage examples,
</files:register>
- >>> print clean_path(file_registry[2].path)
+ >>> print(clean_path(file_registry[2].path))
tests/__init__.py
- >>> print file_registry[2].title
+ >>> print(file_registry[2].title)
Make this a package
- >>> print file_registry[2].description
+ >>> print(file_registry[2].description)
<BLANKLINE>
- >>> print clean_text_w_paths(file_registry[2].info)
+ >>> print(clean_text_w_paths(file_registry[2].info))
File "tests/simple.zcml", line 32.2-32.67
<files:register path="__init__.py" title="Make this a package" />
@@ -1026,10 +1026,10 @@ which it uses for the field description.
After computing the field instance, it gets the ``Schema`` instance,
which is the context of the context passed to the function. The
function checks to see if there is already a field with that name. If
-there is, it raises an error. Otherwise, it saves the field.
+there is, it raises an error. Otherwise, it saves the field.
We also define an ``IIntInfo`` schema and ``intField`` handler
-function to support defining integer fields.
+function to support defining integer fields.
We register the ``text`` and ``int`` directives in ``schema.zcml``.
These are like the simple directive definition we saw in
@@ -1066,13 +1066,13 @@ And verify that the schema registery has the schemas we expect:
>>> i1['a'].__class__.__name__
'Text'
>>> i1['a'].description.strip()
- u'A\n\n Blah blah'
+ 'A\n\n Blah blah'
>>> i1['a'].min_length
1
>>> i1['b'].__class__.__name__
'Int'
>>> i1['b'].description.strip()
- u'B\n\n Not feeling very creative'
+ 'B\n\n Not feeling very creative'
>>> i1['b'].min
1
>>> i1['b'].max
@@ -1096,11 +1096,11 @@ redefine our directives:
... v = string(
... '<text xmlns="http://sample.namespaces.zope.org/schema" name="x" />',
... context)
- ... except ZopeXMLConfigurationError, v:
- ... pass
- >>> print v
+ ... except ZopeXMLConfigurationError as e:
+ ... v = e
+ >>> print(v)
File "<string>", line 1.0
- ConfigurationError: The directive (u'http://sample.namespaces.zope.org/schema', u'text') cannot be used in this context
+ ConfigurationError: The directive ('http://sample.namespaces.zope.org/schema', 'text') cannot be used in this context
Let's see what happens if we declare duplicate fields:
@@ -1116,9 +1116,8 @@ Let's see what happens if we declare duplicate fields:
... </schema>
... ''',
... context)
- ... except ZopeXMLConfigurationError, v:
- ... pass
- >>> print v
+ ... except ZopeXMLConfigurationError as e:
+ ... v = e
+ >>> print(v)
File "<string>", line 5.7-5.24
ValueError: ('Duplicate field', 'x')
-
diff --git a/setup.py b/setup.py
index fe4d906..fc9a6b9 100644
--- a/setup.py
+++ b/setup.py
@@ -25,6 +25,11 @@ def read(*rnames):
return f.read()
TESTS_REQUIRE = [
+ 'manuel',
+ # We test the specific exceptions raised, which
+ # chang from version to version.
+ 'zope.schema >= 4.8.0',
+ 'zope.testing',
'zope.testrunner',
]
diff --git a/src/zope/__init__.py b/src/zope/__init__.py
index de40ea7..2cdb0e4 100644
--- a/src/zope/__init__.py
+++ b/src/zope/__init__.py
@@ -1 +1 @@
-__import__('pkg_resources').declare_namespace(__name__)
+__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
diff --git a/src/zope/configuration/tests/directives.py b/src/zope/configuration/tests/directives.py
index 679f9e3..869d410 100644
--- a/src/zope/configuration/tests/directives.py
+++ b/src/zope/configuration/tests/directives.py
@@ -15,13 +15,12 @@
"""
from zope.interface import Interface
from zope.interface import implementer
-from zope.schema import BytesLine
+from zope.schema import NativeStringLine
from zope.schema import Text
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.interfaces import IConfigurationContext
from zope.configuration.fields import GlobalObject
-from zope.configuration._compat import u
class F(object):
@@ -36,12 +35,12 @@ class ISimple(Interface):
a = Text()
b = Text(required=False)
- c = BytesLine()
+ c = NativeStringLine()
-def simple(context, a=None, c=None, b=u("xxx")):
+def simple(context, a=None, c=None, b=u"xxx"):
return [(('simple', a, b, c), f, (a, b, c))]
-def newsimple(context, a, c, b=u("xxx")):
+def newsimple(context, a, c, b=u"xxx"):
context.action(('newsimple', a, b, c), f, (a, b, c))
@@ -68,7 +67,7 @@ def factory(context, factory):
class Complex(object):
- def __init__(self, context, a, c, b=u("xxx")):
+ def __init__(self, context, a, c, b=u"xxx"):
self.a, self.b, self.c = a, b, c
context.action("Complex.__init__")
@@ -83,10 +82,10 @@ class Complex(object):
class Ik(Interface):
- for_ = BytesLine()
- class_ = BytesLine()
- x = BytesLine()
-
+ for_ = NativeStringLine()
+ class_ = NativeStringLine()
+ x = NativeStringLine()
+
def k(context, for_, class_, x):
context.action(('k', for_), f, (for_, class_, x))
diff --git a/src/zope/configuration/tests/nested.py b/src/zope/configuration/tests/nested.py
index 0a7b61e..3d63f9b 100644
--- a/src/zope/configuration/tests/nested.py
+++ b/src/zope/configuration/tests/nested.py
@@ -17,7 +17,7 @@
from zope.interface import Attribute
from zope.interface import Interface
from zope.interface import implementer
-from zope.schema import BytesLine
+from zope.schema import NativeStringLine
from zope.schema import Id
from zope.schema import Int
from zope.schema import Text
@@ -46,7 +46,7 @@ class ISchema(Interface):
"""
fields = Attribute("Dictionary of field definitions")
-
+
@implementer(IConfigurationContext, ISchema)
class Schema(GroupingContextDecorator):
@@ -70,11 +70,11 @@ class Schema(GroupingContextDecorator):
callable=schema_registry.__setitem__,
args=(self.id, schema),
)
-
+
class IFieldInfo(Interface):
- name = BytesLine(
+ name = NativeStringLine(
title=u("The field name"),
)
@@ -127,7 +127,7 @@ def field(context, constructor, name, **kw):
raise ValueError("Duplicate field", name)
schema.fields[name] = field
-
+
def textField(context, **kw):
field(context, Text, **kw)
@@ -144,6 +144,6 @@ class IIntInfo(IFieldInfo):
required=False,
default=None
)
-
+
def intField(context, **kw):
field(context, Int, **kw)
diff --git a/src/zope/configuration/tests/schema.zcml b/src/zope/configuration/tests/schema.zcml
index 327378c..d35cf15 100644
--- a/src/zope/configuration/tests/schema.zcml
+++ b/src/zope/configuration/tests/schema.zcml
@@ -25,7 +25,7 @@
schema=".nested.ITextInfo"
handler=".nested.textField"
>
-
+
Define a text field
</meta:directive>
@@ -36,19 +36,19 @@
schema=".nested.IIntInfo"
handler=".nested.intField"
>
-
+
Define an integer field
</meta:directive>
<schema:schema name="I1" id="zope.configuration.tests.nested.I1">
Sample interface I1
-
+
<schema:text name="a" min_length="1">
A
Blah blah
</schema:text>
-
+
<schema:int name="b" min="1" max="10">
B
@@ -58,7 +58,7 @@
<schema:schema name="I2" id="zope.configuration.tests.nested.I2">
Sample interface I2
-
+
<schema:text name="x">X</schema:text>
<schema:text name="y" min_length="1" />
</schema:schema>
diff --git a/src/zope/configuration/tests/test_config.py b/src/zope/configuration/tests/test_config.py
index fbfdeb0..f894812 100644
--- a/src/zope/configuration/tests/test_config.py
+++ b/src/zope/configuration/tests/test_config.py
@@ -745,8 +745,6 @@ class ConfigurationMachineTests(_ConformsToIConfigurationContext,
# This is really an integraiton test.
from zope.configuration.config import metans
from zope.configuration.tests.directives import f
- from zope.configuration._compat import b
- from zope.configuration._compat import u
machine = self._makeOne()
ns = "http://www.zope.org/testing"
@@ -770,13 +768,13 @@ class ConfigurationMachineTests(_ConformsToIConfigurationContext,
schema=".Ik", handler=".k")
machine((ns, "k"), "yee ha",
- **{"for": u("f"), "class": u("c"), "x": u("x")})
+ **{"for": u"f", "class": u"c", "x": u"x"})
self.assertEqual(len(machine.actions), 1)
self.assertEqual(machine.actions[0],
- {'args': (b('f'), b('c'), b('x')),
+ {'args': ('f', 'c', 'x'),
'callable': f,
- 'discriminator': ('k', b('f')),
+ 'discriminator': ('k', 'f'),
'includepath': (),
'info': 'yee ha',
'kw': {},
diff --git a/src/zope/configuration/tests/test_docs.py b/src/zope/configuration/tests/test_docs.py
new file mode 100644
index 0000000..915d2f0
--- /dev/null
+++ b/src/zope/configuration/tests/test_docs.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2018 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.
+#
+##############################################################################
+"""
+Tests for the documentation.
+"""
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import re
+import os.path
+import unittest
+import doctest
+
+import manuel.capture
+import manuel.codeblock
+import manuel.doctest
+import manuel.ignore
+import manuel.testing
+
+from zope.testing import renormalizing
+
+checker = renormalizing.RENormalizing([
+ # Python 3 unicode removed the "u".
+ (re.compile("u('.*?')"), r"\1"),
+ (re.compile('u(".*?")'), r"\1"),
+ # Python 3 bytes added the "b".
+ (re.compile("b('.*?')"), r"\1"),
+ (re.compile('b(".*?")'), r"\1"),
+])
+
+
+def test_suite():
+ here = os.path.dirname(os.path.abspath(__file__))
+ while not os.path.exists(os.path.join(here, 'setup.py')):
+ prev, here = here, os.path.dirname(here)
+ if here == prev:
+ # Let's avoid infinite loops at root
+ raise AssertionError('could not find my setup.py')
+
+ docs = os.path.join(here, 'docs')
+ api_docs = os.path.join(docs, 'api')
+
+ doc_files_to_test = (
+ 'narr.rst',
+ )
+
+ api_files_to_test = (
+ 'config.rst',
+ 'docutils.rst',
+ 'fields.rst',
+ 'xmlconfig.rst',
+ )
+
+ paths = [os.path.join(docs, f) for f in doc_files_to_test]
+ paths += [os.path.join(api_docs, f) for f in api_files_to_test]
+
+ m = manuel.ignore.Manuel()
+ m += manuel.doctest.Manuel(checker=checker, optionflags=(
+ doctest.NORMALIZE_WHITESPACE
+ | doctest.ELLIPSIS
+ | doctest.IGNORE_EXCEPTION_DETAIL
+ ))
+ m += manuel.codeblock.Manuel()
+ m += manuel.capture.Manuel()
+
+ suite = unittest.TestSuite()
+ suite.addTest(
+ manuel.testing.TestSuite(
+ m,
+ *paths
+ )
+ )
+
+ return suite
diff --git a/src/zope/configuration/tests/test_xmlconfig.py b/src/zope/configuration/tests/test_xmlconfig.py
index 6fbb120..66c9341 100644
--- a/src/zope/configuration/tests/test_xmlconfig.py
+++ b/src/zope/configuration/tests/test_xmlconfig.py
@@ -1128,14 +1128,14 @@ def clean_actions(actions):
def clean_text_w_paths(error):
r = []
- for line in unicode(error).split("\n"):
- line = line.rstrip()
- if not line:
- continue
- l = line.find('File "')
- if l >= 0:
- line = line[:l] + clean_info_path(line[l:])
- r.append(line)
+ for line in str(error).split("\n"):
+ line = line.rstrip()
+ if not line:
+ continue
+ l = line.find('File "')
+ if l >= 0:
+ line = line[:l] + clean_info_path(line[l:])
+ r.append(line)
return '\n'.join(r)
diff --git a/tox.ini b/tox.ini
index 47f7ed1..c2a018d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -21,7 +21,7 @@ deps =
[testenv:docs]
basepython =
- python2.7
+ python3.6
commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest