[Checkins] SVN: grok/trunk/src/grok/ Fix https://launchpad.net/grok/+bug/83953:

Philipp von Weitershausen philikon at philikon.de
Thu Feb 8 12:43:25 EST 2007


Log message for revision 72468:
  Fix https://launchpad.net/grok/+bug/83953:
  Custom grokkers should be registered only once.
  

Changed:
  U   grok/trunk/src/grok/grokker.py
  A   grok/trunk/src/grok/tests/grokker/onlyonce.py
  A   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/
  A   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/__init__.py
  A   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
  A   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/component.py
  A   grok/trunk/src/grok/tests/grokker/onlyonce_fixture/implementation.py

-=-
Modified: grok/trunk/src/grok/grokker.py
===================================================================
--- grok/trunk/src/grok/grokker.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/grokker.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -7,18 +7,24 @@
         self.clear()
 
     def clear(self):
-        self._grokkers = []
+        self._grokkers = {}
         # register the meta grokkers manually as we can't grok those
         self.registerGrokker(ClassGrokkerGrokker())
         self.registerGrokker(InstanceGrokkerGrokker())
         self.registerGrokker(ModuleGrokkerGrokker())
-        
+
     def registerGrokker(self, grokker):
-        self._grokkers.append(grokker)
+        # we're using a dictionary to make sure each type of grokker
+        # is registered only once (e.g. during meta-grok-time, and not again
+        # during grok-time).
+        key = grokker.__class__
+        if key in self._grokkers:
+            return
+        self._grokkers[key] = grokker
 
     def _getGrokkersInOrder(self):
         # sort grokkers by priority
-        grokkers = sorted(self._grokkers, 
+        grokkers = sorted(self._grokkers.values(),
                           key=lambda grokker: grokker.priority)
         # we want to handle high priority first
         grokkers.reverse()
@@ -26,7 +32,7 @@
 
     def scan(self, module_info):
         components = {}
-        for grokker in self._grokkers:
+        for grokker in self._grokkers.values():
             if isinstance(grokker, grok.ModuleGrokker):
                 continue
             components[grokker.component_class] = []
@@ -34,9 +40,9 @@
         grokkers = self._getGrokkersInOrder()
         module = module_info.getModule()
         for name in dir(module):
-            obj = getattr(module, name)
             if name.startswith('__grok_'):
                 continue
+            obj = getattr(module, name)
             if not util.defined_locally(obj, module_info.dotted_name):
                 continue
             # XXX find way to get rid of this inner loop by doing hash table
@@ -59,9 +65,9 @@
                               scanned_results.get(grok.LocalUtility, []) +
                               scanned_results.get(grok.Container, []))]
         context = util.determine_module_context(module_info, possible_contexts)
-        
+
         templates = templatereg.TemplateRegistry()
-   
+
         # run through all grokkers registering found components in order
         for grokker in self._getGrokkersInOrder():
             # if we run into a ModuleGrokker, just do simple registration.
@@ -71,8 +77,9 @@
             if isinstance(grokker, grok.ModuleGrokker):
                 grokker.register(context, module_info, templates)
                 continue
-            
+
             components = scanned_results.get(grokker.component_class, [])
+
             for name, component in components:
                 # this is a base class as it ends with Base, skip
                 if type(component) is type:
@@ -100,7 +107,7 @@
 class MetaGrokker(grok.ClassGrokker):
     def register(self, context, name, factory, module_info, templates):
         grokkerRegistry.registerGrokker(factory())
-    
+
 class ClassGrokkerGrokker(MetaGrokker):
     component_class = grok.ClassGrokker
 
@@ -109,7 +116,7 @@
 
 class ModuleGrokkerGrokker(MetaGrokker):
     component_class = grok.ModuleGrokker
-    
+
 # the global grokker registry
 grokkerRegistry = GrokkerRegistry()
 

Added: grok/trunk/src/grok/tests/grokker/onlyonce.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/tests/grokker/onlyonce.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -0,0 +1,27 @@
+"""
+
+We define a grokker AlphaGrokker for a component called Alpha. We first need to
+grok the module defining the grokkers, in order to get them registered.
+
+Usually this would be triggered from a meta.zcml in a package, that would grok
+the module containing the grokkers (e.g. meta.py).
+
+We do it manually now::
+
+  >>> import grok
+  >>> grok.grok('grok.tests.grokker.onlyonce_fixture._meta')
+
+This _meta.py module then will be grokked again during 'normal' grok time. Grok
+will not re-register the grokkers as this could have unwanted side-effects. It
+will grok the components of course.
+
+NOTE: the module is called _meta to make sure it is grokked (although its
+grokker registration should be ignored) before the other files. The modules are
+picked up in alphabetical order.
+
+To simulate this, we grok the whole package::
+
+  >>> grok.grok('grok.tests.grokker.onlyonce_fixture')
+  alpha
+
+"""


Property changes on: grok/trunk/src/grok/tests/grokker/onlyonce.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/__init__.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/__init__.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -0,0 +1 @@
+# fixture package
\ No newline at end of file


Property changes on: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -0,0 +1,8 @@
+import grok
+from component import Alpha
+
+class AlphaGrokker(grok.ClassGrokker):
+    component_class = Alpha
+
+    def register(self, context, name, factory, module_info, templates):
+        print "alpha"


Property changes on: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/_meta.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/component.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/component.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/component.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -0,0 +1,4 @@
+import grok
+
+class Alpha(object):
+    grok.baseclass()


Property changes on: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/component.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/implementation.py
===================================================================
--- grok/trunk/src/grok/tests/grokker/onlyonce_fixture/implementation.py	2007-02-08 17:31:12 UTC (rev 72467)
+++ grok/trunk/src/grok/tests/grokker/onlyonce_fixture/implementation.py	2007-02-08 17:43:24 UTC (rev 72468)
@@ -0,0 +1,4 @@
+from component import Alpha
+
+class AlphaSub(Alpha):
+    pass
\ No newline at end of file


Property changes on: grok/trunk/src/grok/tests/grokker/onlyonce_fixture/implementation.py
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list