[Checkins] SVN: grok/branches/wosc-utility-subclassing/src/grok/
work-in-progress about subclassing and local utilities.
failing tests, buyer beware
Wolfgang Schnerring
wosc at wosc.de
Sun Jan 7 09:33:22 EST 2007
Log message for revision 71768:
work-in-progress about subclassing and local utilities. failing tests, buyer beware
Changed:
U grok/branches/wosc-utility-subclassing/src/grok/directive.py
A grok/branches/wosc-utility-subclassing/src/grok/ftests/utility/subclass.py
U grok/branches/wosc-utility-subclassing/src/grok/meta.py
U grok/branches/wosc-utility-subclassing/src/grok/tests/test_grok.py
A grok/branches/wosc-utility-subclassing/src/grok/tests/util/
A grok/branches/wosc-utility-subclassing/src/grok/tests/util/__init__.py
A grok/branches/wosc-utility-subclassing/src/grok/tests/util/class_annotation.py
U grok/branches/wosc-utility-subclassing/src/grok/util.py
-=-
Modified: grok/branches/wosc-utility-subclassing/src/grok/directive.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/directive.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/directive.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -190,7 +190,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)
@@ -200,14 +200,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
# Define grok directives
Added: grok/branches/wosc-utility-subclassing/src/grok/ftests/utility/subclass.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/ftests/utility/subclass.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/ftests/utility/subclass.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -0,0 +1,73 @@
+"""
+Subclassed sites inherit all local utilities of their base classes:
+
+ >>> import grok
+ >>> from zope import component
+ >>> from grok.ftests.utility.subclass import *
+
+ >>> grok.grok('grok.ftests.utility.subclass')
+
+ >>> cave = BigCave()
+ >>> getRootFolder()["cave"] = cave
+
+ >>> from zope.app.component.hooks import getSite, setSite
+
+ >>> setSite(cave)
+ >>> fireplace = component.getUtility(IFireplace)
+ >>> IFireplace.providedBy(fireplace)
+ True
+ >>> isinstance(fireplace, Fireplace)
+ True
+
+Additional utilities can be registered in the subclass:
+
+ >>> hollow = HollowCave()
+ >>> getRootFolder()["hollow"] = hollow
+
+ >>> setSite(hollow)
+ >>> fireplace = component.getUtility(IFireplace)
+ >>> IFireplace.providedBy(fireplace)
+ True
+ >>> isinstance(fireplace, Fireplace)
+ True
+
+ >>> painting = component.getUtility(IPainting)
+ >>> IPainting.providedBy(painting)
+ True
+ >>> isinstance(painting, Painting)
+ True
+
+Those do not influence the base class:
+
+ >>> setSite(cave)
+ >>> painting = component.getUtility(IPainting)
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: (<InterfaceClass grok.ftests.utility.subclass.IPainting>, '')
+"""
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+ pass
+
+class IPainting(interface.Interface):
+ pass
+
+class Fireplace(grok.LocalUtility):
+ grok.implements(IFireplace)
+
+class Painting(grok.LocalUtility):
+ grok.implements(IPainting)
+
+class Cave(grok.Model, grok.Site):
+ # we use name_in_container here to prevent multiple registrations
+ # since storing the utilities multiple times under the same name
+ # would raise a DuplicationError
+ grok.local_utility(Fireplace, name_in_container='fireplace')
+
+class BigCave(Cave):
+ pass
+
+class HollowCave(Cave):
+ grok.local_utility(Painting)
Modified: grok/branches/wosc-utility-subclassing/src/grok/meta.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/meta.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/meta.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -259,7 +259,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
@@ -295,12 +295,18 @@
self.infos = infos
def __call__(self, site, event):
+ processed = util.class_annotation(site,
+ 'grok.' + self.__class__.__name__, [])
+ if site.__class__ in processed:
+ import pdb; pdb.set_trace()
+ return
+
for info in self.infos:
utility = info.factory()
site_manager = site.getSiteManager()
# store utility
- if info.hide:
+ if info.hidden:
container = site_manager['default']
else:
container = site
@@ -320,6 +326,10 @@
site_manager.registerUtility(utility, provided=info.provides,
name=info.name)
+ processed = processed[:]
+ processed.append(site.__class__)
+ setattr(site, '__grok_' + self.__class__.__name__ + '__', processed)
+
class DefinePermissionGrokker(grok.ModuleGrokker):
def register(self, context, module_info, templates):
Modified: grok/branches/wosc-utility-subclassing/src/grok/tests/test_grok.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/tests/test_grok.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/tests/test_grok.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -34,7 +34,7 @@
suite = unittest.TestSuite()
for name in ['adapter', 'error', 'view', 'scan', 'event',
'zcml', 'static', 'utility', 'xmlrpc', 'container',
- 'traversal', 'form', 'site', 'grokker', 'directive']:
+ 'traversal', 'form', 'site', 'grokker', 'directive', 'util']:
suite.addTest(suiteFromPackage(name))
return suite
Added: grok/branches/wosc-utility-subclassing/src/grok/tests/util/__init__.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/tests/util/__init__.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/tests/util/__init__.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -0,0 +1 @@
+# this is a package
Added: grok/branches/wosc-utility-subclassing/src/grok/tests/util/class_annotation.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/tests/util/class_annotation.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/tests/util/class_annotation.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -0,0 +1,28 @@
+"""
+ >>> util.class_annotation_list(B, 'grok.foo', None)
+ [7, 5]
+ >>> util.class_annotation_list(B2, 'grok.foo', None)
+ [5]
+ >>> util.class_annotation_list(C, 'grok.foo', None)
+ [8, 7, 5]
+ >>> util.class_annotation_list(C2, 'grok.foo', None)
+ [9, 5, 7]
+
+"""
+import grok
+from grok import util
+
+class A(object):
+ __grok_foo__ = [5]
+
+class B(A):
+ __grok_foo__ = [7]
+
+class B2(A):
+ pass
+
+class C(B, B2):
+ __grok_foo__ = [8]
+
+class C2(B2, B):
+ __grok_foo__ = [9]
Modified: grok/branches/wosc-utility-subclassing/src/grok/util.py
===================================================================
--- grok/branches/wosc-utility-subclassing/src/grok/util.py 2007-01-07 14:31:29 UTC (rev 71767)
+++ grok/branches/wosc-utility-subclassing/src/grok/util.py 2007-01-07 14:33:21 UTC (rev 71768)
@@ -52,7 +52,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