[Checkins] SVN: grok/trunk/src/grok/ Implement proper behavior for
subclassing of sites that have local utilities.
Martijn Faassen
faassen at infrae.com
Sun Jan 7 10:44:34 EST 2007
Log message for revision 71774:
Implement proper behavior for subclassing of sites that have local utilities.
Changed:
U grok/trunk/src/grok/directive.py
A grok/trunk/src/grok/ftests/utility/subclass.py
U grok/trunk/src/grok/meta.py
U grok/trunk/src/grok/tests/test_grok.py
A grok/trunk/src/grok/tests/util/
U grok/trunk/src/grok/util.py
-=-
Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py 2007-01-07 15:42:30 UTC (rev 71773)
+++ grok/trunk/src/grok/directive.py 2007-01-07 15:44:34 UTC (rev 71774)
@@ -199,7 +199,7 @@
class LocalUtilityDirective(MultipleTimesDirective):
def check_arguments(self, factory, provides=None, name=u'',
- setup=None, hide=True, name_in_container=None):
+ setup=None, hidden=True, name_in_container=None):
if provides is not None and not IInterface.providedBy(provides):
raise GrokImportError("You can only pass an interface to the "
"provides argument of %s." % self.name)
@@ -209,14 +209,14 @@
class LocalUtilityInfo(object):
def __init__(self, factory, provides=None, name=u'',
- setup=None, hide=True, name_in_container=None):
+ setup=None, hidden=True, name_in_container=None):
self.factory = factory
if provides is None:
provides = util.class_annotation(factory, 'grok.provides', None)
self.provides = provides
self.name = name
self.setup = setup
- self.hide = hide
+ self.hidden = hidden
self.name_in_container = name_in_container
class RequireDirective(BaseTextDirective, SingleValue, MultipleTimesDirective):
Copied: grok/trunk/src/grok/ftests/utility/subclass.py (from rev 71771, grok/branches/wosc-utility-subclassing/src/grok/ftests/utility/subclass.py)
Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py 2007-01-07 15:42:30 UTC (rev 71773)
+++ grok/trunk/src/grok/meta.py 2007-01-07 15:44:34 UTC (rev 71774)
@@ -303,7 +303,7 @@
continue_scanning = True
def register(self, context, name, factory, module_info, templates):
- infos = util.class_annotation(factory, 'grok.local_utility', None)
+ infos = util.class_annotation_list(factory, 'grok.local_utility', None)
if infos is None:
return
@@ -329,22 +329,31 @@
util.check_implements_one_from_list(provides, info.factory)
info.provides = provides[0]
-
- subscriber = LocalUtilityRegistrationSubscriber(infos)
+
+ # store infos on site class
+ factory.__grok_utilities_to_install__ = infos
+ subscriber = LocalUtilityRegistrationSubscriber()
component.provideHandler(subscriber,
adapts=(factory, grok.IObjectAddedEvent))
class LocalUtilityRegistrationSubscriber(object):
- def __init__(self, infos):
- self.infos = infos
-
+ """A subscriber that fires to set up local utilities.
+
+ This class is deliberately stateless. This means that there
+ can be no instance variables.
+ """
def __call__(self, site, event):
- for info in self.infos:
+ installed = getattr(site, '__grok_utilities_installed__', False)
+ if installed:
+ return
+
+ for info in util.class_annotation(site.__class__,
+ 'grok.utilities_to_install', []):
utility = info.factory()
site_manager = site.getSiteManager()
# store utility
- if info.hide:
+ if info.hidden:
container = site_manager['default']
else:
container = site
@@ -364,6 +373,10 @@
site_manager.registerUtility(utility, provided=info.provides,
name=info.name)
+ # we are done. If this subscriber gets fired again, we therefore
+ # do not register utilities anymore
+ site.__grok_utilities_installed__ = True
+
class DefinePermissionGrokker(grok.ModuleGrokker):
priority = 1500
Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py 2007-01-07 15:42:30 UTC (rev 71773)
+++ grok/trunk/src/grok/tests/test_grok.py 2007-01-07 15:44:34 UTC (rev 71774)
@@ -34,7 +34,7 @@
suite = unittest.TestSuite()
for name in ['adapter', 'error', 'view', 'scan', 'event', 'security',
'zcml', 'static', 'utility', 'xmlrpc', 'container',
- 'traversal', 'form', 'site', 'grokker', 'directive']:
+ 'traversal', 'form', 'site', 'grokker', 'directive', 'util']:
suite.addTest(suiteFromPackage(name))
return suite
Copied: grok/trunk/src/grok/tests/util (from rev 71771, grok/branches/wosc-utility-subclassing/src/grok/tests/util)
Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py 2007-01-07 15:42:30 UTC (rev 71773)
+++ grok/trunk/src/grok/util.py 2007-01-07 15:44:34 UTC (rev 71774)
@@ -53,7 +53,24 @@
def class_annotation(obj, name, default):
return getattr(obj, '__%s__' % name.replace('.', '_'), default)
+def class_annotation_list(obj, name, default):
+ """This will process annotations that are lists correctly in the face of
+ inheritance.
+ """
+ if class_annotation(obj, name, default) is default:
+ return default
+ result = []
+ for base in obj.mro():
+ list = class_annotation(base, name, [])
+ if list not in result:
+ result.append(list)
+
+ result_flattened = []
+ for entry in result:
+ result_flattened.extend(entry)
+ return result_flattened
+
def defined_locally(obj, dotted_name):
obj_module = getattr(obj, '__grok_module__', None)
if obj_module is None:
More information about the Checkins
mailing list