[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