Package zope :: Package configuration :: Package tests :: Module test_xmlconfig
[show private | hide private]
[frames | no frames]

Module zope.configuration.tests.test_xmlconfig

Test XML configuration (ZCML) machinery.

$Id: test_xmlconfig.py,v 1.2 2005/06/24 16:52:28 nyergler Exp $
Classes
FauxContext  
FauxLocator  

Function Summary
  clean_actions(actions)
  clean_info_path(s)
  clean_path(s)
  clean_text_w_paths(error)
  path(*p)
  test_ConfigurationHandler_err_end()
  test_ConfigurationHandler_err_start()
  test_ConfigurationHandler_normal()
  test_file()
  test_include_by_file()
  test_include_by_file_glob()
  test_include_by_package()
  test_includeOverrides()
When we have conflicting directives, we can resolve them if one of the conflicting directives was from a file that included all of the others.
  test_processxmlfile()
  test_suite()
  test_XMLConfig()
Test processing a configuration file.
  test_XMLConfig_w_module()
Test processing a configuration file for a module.

Function Details

test_ConfigurationHandler_err_end()

>>> class FauxContext(FauxContext):
...   def end(self):
...     raise AttributeError("xxx")
>>> 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",
...                        })
>>> locator.line, locator.column = 7, 16
>>> try:
...   v = handler.endElementNS((u"ns", u"foo"), u"foo")
... except xmlconfig.ZopeXMLConfigurationError, v:
...   pass
>>> print v
File "tests//sample.zcml", line 1.1-7.16
    AttributeError: xxx

test_ConfigurationHandler_err_start()

>>> class FauxContext(FauxContext):
...   def begin(self, *args):
...     raise AttributeError("xxx")
>>> context = FauxContext()
>>> locator = FauxLocator('tests//sample.zcml', 1, 1)
>>> handler = xmlconfig.ConfigurationHandler(context)
>>> handler.setDocumentLocator(locator)
>>> try:
...   v = handler.startElementNS((u"ns", u"foo"), u"foo",
...                              {(u"xxx", u"splat"): u"splatv",
...                               (None, u"a"): u"avalue",
...                               (None, u"b"): u"bvalue",
...                              })
... except xmlconfig.ZopeXMLConfigurationError, v:
...   pass
>>> print v
File "tests//sample.zcml", line 1.1
    AttributeError: xxx

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
>>> 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

test_file()

>>> file_name = path("samplepackage", "configure.zcml")
>>> context = xmlconfig.file(file_name)
>>> data = foo.data.pop()
>>> data.args
(('x', 'blah'), ('y', 0))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/configure.zcml", line 12.2-12.29
>>> 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)
tests/samplepackage

test_include_by_file()

>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, "samplepackage", "foo.zcml")
>>> xmlconfig.include(context, path)
>>> context.execute_actions()
>>> data = foo.data.pop()
>>> data.args
(('x', 'foo'), ('y', 2))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/foo.zcml.in", line 12.2-12.28
>>> print clean_info_path(str(data.info))
File "tests/samplepackage/foo.zcml.in", line 12.2-12.28
    <test:foo x="foo" y="2" />
>>> data.package
>>> data.basepath[-13:]
'samplepackage'
>>> [clean_path(p) for p in data.includepath]
['tests/samplepackage/foo.zcml.in']

test_include_by_file_glob()

>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, "samplepackage/baz*.zcml")
>>> xmlconfig.include(context, files=path)
>>> context.execute_actions()
>>> data = foo.data.pop()
>>> data.args
(('x', 'foo'), ('y', 3))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/baz3.zcml", line 5.2-5.28
>>> print clean_info_path(str(data.info))
File "tests/samplepackage/baz3.zcml", line 5.2-5.28
    <test:foo x="foo" y="3" />
>>> data.package
>>> data.basepath[-13:]
'samplepackage'
>>> [clean_path(p) for p in data.includepath]
['tests/samplepackage/baz3.zcml']
>>> data = foo.data.pop()
>>> data.args
(('x', 'foo'), ('y', 2))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/baz2.zcml", line 5.2-5.28
>>> print clean_info_path(str(data.info))
File "tests/samplepackage/baz2.zcml", line 5.2-5.28
    <test:foo x="foo" y="2" />
>>> data.package
>>> data.basepath[-13:]
'samplepackage'
>>> [clean_path(p) for p in data.includepath]
['tests/samplepackage/baz2.zcml']

test_include_by_package()

>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)
>>> import zope.configuration.tests.samplepackage as package
>>> xmlconfig.include(context, 'configure.zcml', package)
>>> context.execute_actions()
>>> data = foo.data.pop()
>>> data.args
(('x', 'blah'), ('y', 0))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/configure.zcml", line 12.2-12.29
>>> 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 is package
1
>>> data.basepath[-13:]
'samplepackage'
>>> [clean_path(p) for p in data.includepath]
['tests/samplepackage/configure.zcml']

test_includeOverrides()

When we have conflicting directives, we can resolve them if one of
the conflicting directives was from a file that included all of
the others.  The problem with this is that this requires that all
of the overriding directives be in one file, typically the
top-most including file. This isn't very convenient.  Fortunately,
we can overcome this with the includeOverrides directive. Let's
look at an example to see how this works.

Look at the file bar.zcml. It includes bar1.zcml and bar2.zcml.
bar2.zcml includes configure.zcml and has a foo
directive. bar2.zcml includes bar21.zcml.  bar2.zcml 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 configure.zcml. Whew!

Let's see what happens when we try to process bar.zcml.

>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)

>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, "samplepackage", "bar.zcml")
>>> xmlconfig.include(context, path)

So far so good, let's look at the configuration actions:

>>> pprint=PrettyPrinter(width=70).pprint
>>> pprint(clean_actions(context.actions))
[{'discriminator': (('x', '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)),
  '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)),
  '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)),
  '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)),
  '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)),
  'includepath': ['tests/samplepackage/bar.zcml',
                  'tests/samplepackage/bar2.zcml'],
  'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]

As you can see, there are a number of conflicts (actions with the same
discriminator).  Some of these can be resolved, but many can't, as
we'll find if we try to execuse the actions:

>>> try:
...    v = context.execute_actions()
... except config.ConfigurationConflictError, v:
...    pass
>>> 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
        <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))
    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
        <foo x="blah" y="1" />

Note that the conflicts for (('x', 'blah'), ('y', 2)) aren't
included in the error because they could be resolved.

Let's try this again using includeOverrides.  We'll include
baro.zcml which includes bar2.zcml as overrides.

>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)
>>> path = os.path.join(here, "samplepackage", "baro.zcml")
>>> xmlconfig.include(context, path)

Now, if we look at the actions:

>>> pprint(clean_actions(context.actions))
[{'discriminator': (('x', '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)),
  '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)),
  'includepath': ['tests/samplepackage/baro.zcml'],
  'info': 'File "tests/samplepackage/bar21.zcml", line 3.2-3.24'},
 {'discriminator': (('x', 'blah'), ('y', 2)),
  'includepath': ['tests/samplepackage/baro.zcml'],
  'info': 'File "tests/samplepackage/bar2.zcml", line 5.2-5.24'},
 {'discriminator': (('x', 'blah'), ('y', 1)),
  'includepath': ['tests/samplepackage/baro.zcml'],
  'info': 'File "tests/samplepackage/bar2.zcml", line 6.2-6.24'}]

We see that:

- The conflicting actions between bar2.zcml and bar21.zcml have
  been resolves, and

- The remaining (after conflict resolution) actions from bar2.zcml
  and bar21.zcml have the includepath that they would have if they
  were defined in baro.zcml and this override the actions from
  bar1.zcml and configure.zcml.

We can now execute the actions without problem, since the
remaining conflicts are resolvable:

>>> context.execute_actions()

We should now have three entries in foo.data:

>>> len(foo.data)
3

>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))
>>> print clean_info_path(`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`)
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`)
File "tests/samplepackage/bar2.zcml", line 6.2-6.24

test_processxmlfile()

>>> file = open(path("samplepackage", "configure.zcml"))
>>> context = config.ConfigurationMachine()
>>> xmlconfig.registerCommonDirectives(context)
>>> xmlconfig.processxmlfile(file, context)
>>> foo.data
[]
>>> context.execute_actions()
>>> data = foo.data.pop()
>>> data.args
(('x', 'blah'), ('y', 0))
>>> print clean_info_path(`data.info`)
File "tests/samplepackage/configure.zcml", line 12.2-12.29
>>> 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
>>> data.basepath

test_XMLConfig()

Test processing a configuration file.

We'll use the same example from test_includeOverrides:
>>> here = os.path.dirname(__file__)
>>> path = os.path.join(here, "samplepackage", "baro.zcml")
First, process the configuration file:
>>> x = xmlconfig.XMLConfig(path)
Second, call the resulting object to process the actions:
>>> x()
And verify the data as above:
>>> len(foo.data)
3
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))

>>> print clean_info_path(`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`)
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`)
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
Finally, clean up.
>>> from zope.testing.cleanup import CleanUp
>>> CleanUp().cleanUp()

test_XMLConfig_w_module()

Test processing a configuration file for a module.

We'll use the same example from test_includeOverrides:
>>> import zope.configuration.tests.samplepackage as module
First, process the configuration file:
>>> x = xmlconfig.XMLConfig("baro.zcml", module)
Second, call the resulting object to process the actions:
>>> x()
And verify the data as above:
>>> len(foo.data)
3
>>> data = foo.data.pop(0)
>>> data.args
(('x', 'blah'), ('y', 0))

>>> print clean_info_path(`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`)
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`)
File "tests/samplepackage/bar2.zcml", line 6.2-6.24
Finally, clean up.
>>> from zope.testing.cleanup import CleanUp
>>> CleanUp().cleanUp()

Generated by Epydoc 2.1 on Fri Jun 24 12:01:25 2005 http://epydoc.sf.net