[Checkins] SVN: zc.resourcelibrary/trunk/ Raise NotImplementedError if we find that a second ZCML declaration would
Brian Sutherland
jinty at web.de
Thu Dec 22 16:23:01 UTC 2011
Log message for revision 123856:
Raise NotImplementedError if we find that a second ZCML declaration would
change the global library_info dict in a way that may (depending on ZCML
ordering) break applications at runtime. These errors were pretty hard to
debug.
Changed:
U zc.resourcelibrary/trunk/CHANGES.txt
U zc.resourcelibrary/trunk/src/zc/resourcelibrary/README.txt
A zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.txt
A zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.zcml
A zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml
U zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/tests.py
U zc.resourcelibrary/trunk/src/zc/resourcelibrary/zcml.py
-=-
Modified: zc.resourcelibrary/trunk/CHANGES.txt
===================================================================
--- zc.resourcelibrary/trunk/CHANGES.txt 2011-12-22 14:09:44 UTC (rev 123855)
+++ zc.resourcelibrary/trunk/CHANGES.txt 2011-12-22 16:23:01 UTC (rev 123856)
@@ -5,6 +5,11 @@
1.3.3 (unreleased)
------------------
+- Raise NotImplementedError if we find that a second ZCML declaration would
+ change the global library_info dict in a way that may (depending on ZCML
+ ordering) break applications at runtime. These errors were pretty hard to
+ debug.
+
- Remove unneeded test dependencies on ``zope.app.authentication`` and
``zope.app.securitypolicy``.
Modified: zc.resourcelibrary/trunk/src/zc/resourcelibrary/README.txt
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/README.txt 2011-12-22 14:09:44 UTC (rev 123855)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/README.txt 2011-12-22 16:23:01 UTC (rev 123856)
@@ -393,7 +393,7 @@
... </resourceLibrary>
...
... </configure>
- ... """)
+ ... """, clear=['my-lib'])
The factory will be called with a source directory, a security checker
and a name. We've created a class that implements a resource
Added: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.txt
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.txt (rev 0)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.txt 2011-12-22 16:23:01 UTC (rev 123856)
@@ -0,0 +1,63 @@
+It used to be that this configuration would result in wierd errors later as the
+global library_info dict would depend on the order declarations appeared in the
+ZCML.
+
+Now it just errors faster:
+
+ >>> zcml("""
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... package="zc.resourcelibrary">
+ ...
+ ... <includeOverrides
+ ... package="zc.resourcelibrary.tests"
+ ... file="duplicate_declarations_overrides.zcml"/>
+ ... <include
+ ... package="zc.resourcelibrary.tests"
+ ... file="duplicate_declarations.zcml"/>
+ ...
+ ... </configure>
+ ... """)
+ Traceback (most recent call last):
+ ...
+ ZopeXMLConfigurationError: File "<string>", line 6.2-8.50
+ ZopeXMLConfigurationError: File "/Users/jinty/src/zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml", line 5.2-10.2
+ NotImplementedError: Can't cope with 2 different registrations of the same library: some-library ([], []) ([], [u'1.js'])
+
+This is what getIncluded woudl have returned if the above had not errored (it
+is wrong as includeOverrides should have take precedence):
+
+ >>> from zc.resourcelibrary import getIncluded
+ >>> getIncluded("some-library") # doctest: +SKIP
+ [u'included.js', u'included.css']
+
+However we work if you load up the same ZCML file twice (as the information in
+library_info is exactly the same):
+
+ >>> zcml("""
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... package="zc.resourcelibrary">
+ ...
+ ... <include
+ ... package="zc.resourcelibrary.tests"
+ ... file="duplicate_declarations_overrides.zcml"/>
+ ...
+ ... </configure>
+ ... """)
+ >>> zcml("""
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... package="zc.resourcelibrary">
+ ...
+ ... <include
+ ... package="zc.resourcelibrary.tests"
+ ... file="duplicate_declarations_overrides.zcml"/>
+ ...
+ ... </configure>
+ ... """)
+
+The correct result from getIncluded is:
+
+ >>> getIncluded("some-library")
+ [u'1.js']
Property changes on: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.zcml
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.zcml (rev 0)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.zcml 2011-12-22 16:23:01 UTC (rev 123856)
@@ -0,0 +1,13 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ package="zc.resourcelibrary">
+
+ <resourceLibrary name="some-library">
+ <directory
+ source="tests/example/my-lib"
+ include="included.js included.css"
+ />
+ </resourceLibrary>
+
+</configure>
+
Property changes on: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations.zcml
___________________________________________________________________
Added: svn:eol-style
+ native
Added: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml (rev 0)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml 2011-12-22 16:23:01 UTC (rev 123856)
@@ -0,0 +1,12 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ package="zc.resourcelibrary">
+
+ <resourceLibrary name="some-library">
+ <directory
+ source="tests/example"
+ include="1.js"
+ />
+ </resourceLibrary>
+
+</configure>
Property changes on: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/duplicate_declarations_overrides.zcml
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/tests.py
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/tests.py 2011-12-22 14:09:44 UTC (rev 123855)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/tests/tests.py 2011-12-22 16:23:01 UTC (rev 123856)
@@ -15,6 +15,7 @@
$Id: ntests.py 3330 2005-09-09 23:05:34Z jim $
"""
from StringIO import StringIO
+from zc.resourcelibrary import resourcelibrary
from zc.resourcelibrary import publication
from zc.resourcelibrary import tal
from zope.app.testing import functional
@@ -54,7 +55,9 @@
#### testing framework ####
-def zcml(s, execute=True):
+def zcml(s, execute=True, clear=()):
+ for i in clear:
+ del resourcelibrary.library_info[i]
from zope.app.appsetup.appsetup import __config_context as context
try:
xmlconfig.string(s, context, execute=execute)
@@ -122,7 +125,7 @@
def test_suite():
suite = functional.FunctionalDocFileSuite(
- '../README.txt',
+ '../README.txt', 'duplicate_declarations.txt',
globs={'zcml': zcml, 'zpt': zpt},
optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS,
)
Modified: zc.resourcelibrary/trunk/src/zc/resourcelibrary/zcml.py
===================================================================
--- zc.resourcelibrary/trunk/src/zc/resourcelibrary/zcml.py 2011-12-22 14:09:44 UTC (rev 123855)
+++ zc.resourcelibrary/trunk/src/zc/resourcelibrary/zcml.py 2011-12-22 16:23:01 UTC (rev 123856)
@@ -98,6 +98,7 @@
self.checker = NamesChecker(allowed_names, permission)
# make note of the library in a global registry
+ self.old_library_info = library_info.get(name)
library_info[name] = LibraryInfo()
library_info[name].required.extend(require)
@@ -126,3 +127,17 @@
args = (self.name, library_info[self.name].required, (self.layer,),
Interface, self.name, factory, _context.info),
)
+
+ def __call__(self):
+ if self.old_library_info is None:
+ return
+ curr_li = library_info[self.name]
+ if self.old_library_info.included != curr_li.included or \
+ self.old_library_info.required != curr_li.required:
+ raise NotImplementedError(
+ "Can't cope with 2 different registrations of the same "
+ "library: %s (%s, %s) (%s, %s)" % (self.name,
+ self.old_library_info.required,
+ self.old_library_info.included,
+ curr_li.required,
+ curr_li.included))
More information about the checkins
mailing list