[Checkins] SVN: grok/trunk/ Merged the 'philikon-decl-dir-rules' branch:

Philipp von Weitershausen philikon at philikon.de
Wed May 14 12:29:11 EDT 2008


Log message for revision 86746:
  Merged the 'philikon-decl-dir-rules' branch:
  
  * Refactored class grokkers to make use of Martian's new declarative
    way for retrieving directive data from classes.
  
  

Changed:
  U   grok/trunk/CHANGES.txt
  U   grok/trunk/doc/upgrade.txt
  U   grok/trunk/setup.py
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/directive.py
  U   grok/trunk/src/grok/meta.py
  U   grok/trunk/src/grok/templatereg.py
  U   grok/trunk/src/grok/tests/directive/multipleasdict.py
  U   grok/trunk/src/grok/tests/directive/multipletimes.py
  U   grok/trunk/src/grok/util.py
  U   grok/trunk/versions.cfg

-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/CHANGES.txt	2008-05-14 16:29:11 UTC (rev 86746)
@@ -17,6 +17,9 @@
   were removed.  The functionality is mostly available from the
   directives themselves now.
 
+* Refactored class grokkers to make use of Martian's new declarative
+  way for retrieving directive data from classes.
+
 Feature changes
 ---------------
 

Modified: grok/trunk/doc/upgrade.txt
===================================================================
--- grok/trunk/doc/upgrade.txt	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/doc/upgrade.txt	2008-05-14 16:29:11 UTC (rev 86746)
@@ -4,92 +4,141 @@
 This document outlines how to update Grok applications so that they
 continue to work with newer versions of Grok.  This document only
 describes changes involving incompatibilities or deprecations, not new
-features (please see :ref:`changes` below or refer to ``CHANGES.txt``
-for those).
+features (please refer to ``CHANGES.txt`` for those).
 
 Upgrading to 0.13
 -----------------
 
 * The directive implementations changed tremendously with the upgrade
-  to Martian 0.9.4.  Custom implementations of both directives and
-  grokkers will have to be adjusted.
+  to Martian 0.9.6.  Custom implementations of both directives (see
+  next bullet point) and grokkers will have to be adjusted.
 
-  - Since directives now have the ability to retrieve the information
-    that was set by them on a component, grokkers need to be adjusted
-    to use the directive's ``get()`` method, rather than the
-    ``class_annotation`` helper.  So instead of::
+  Since the vast majority of directives are class directives, the most
+  common places where information set by directives has to be red are
+  class grokkers (``martian.ClassGrokker``).  For instance, you may
+  have written something like this to implement a custom class
+  grokker previously::
 
-      name = util.class_annotation(factory, 'grok.name', '')
+    class RobotGrokker(martian.ClassGrokker):
+        component_class = Robot
 
-    you should write::
+        def grok(self, name, factory, module_info, config, **kw):
+            robot_name = martian.util.class_annotation(factory, 'grok.name', '')
+            title = martian.util.class_annotation(factory, 'grok.title', 'A robot')
+            provides = martian.util.class_annotation(factory, 'grok.provides', None)
+            if provides is None:
+                martian.util.check_implements_one(factory)
+                provides = list(zope.interface.implementedBy(factory))[0]
+            config.action(
+                descriminator=('robot', provides, robot_name),
+                callable=provideRobot,
+                args=(factory, provides, robot_name, title),
+                )
+            return True
 
-      name = grok.name.get(factory)
+  As you can see, this grokker needs to retrieve three values from the
+  class it's grokking (``factory``) which are all set by directives:
 
-    If the value may have a module-level fall-back, you should also
-    pass in the module.  So instead of writing::
+  - ``grok.name`` with the standard default, an empty string,
 
-      layer = determine_class_directive('grok.layer', factory, module_info,
-                                        default=IDefaultBrowserLayer)
+  - ``grok.title`` with a custom default, the string ``A robot``,
 
-    you should now write::
+  - ``grok.provides`` with a computed default.
 
-      layer = grok.layer.get(factory, module_info.getModule())
-      if layer is None:
-          layer = IDefaultBrowserLayer
+  With the new directive implementation and the extensions to
+  Martian's ``ClassGrokker``, you're now be able to write::
 
-  - Custom directives need to be re-implemented using Martian's new
-    ``Directive`` base class.  The directive scope, the type of
-    storage, the validator and a potential default value are all
-    defined as class-level variables:
+    def default_provides(factory, module, **data):
+        # This function is available for import from grokcore.component.meta.
+        # It's shown here simply to illustrate how the original grokker would
+        # have been refactored.
+        martian.util.check_implements_one(factory)
+        return list(zope.interface.implementedBy(factory))[0]
 
-    o The directive scope can either one of ``martian.CLASS``,
-      ``martian.MODULE``, ``martian.CLASS_OR_MODULE``.
+    class RobotGrokker(martian.ClassGrokker):
+        component_class = Robot
+        directives = [
+            grok.name.bind(name='robot_name'),
+            grok.title.bind(default='A Robot'),
+            grok.provides.bind(get_default=default_provides),
+            ]
 
-    o The type of storage can be either one of ``martian.ONCE``,
-      ``martian.MULTIPLE``, ``martian.DICT``.
+        def execute(self, factory, config, robot_name, title, provides, **kw):
+            config.action(
+                descriminator=('robot', provides, robot_name),
+                callable=provideRobot,
+                args=(factory, provides, robot_name, title),
+                )
+            return True
 
-    o An optional validator may be one of ``validateText``,
-      ``validateInterface``, ``validateInterfaceOrClass`` or a custom
-      method.
+  Basically, all you need to do is provide a list of *bound*
+  directives in the grokker class and then implement the ``execute``
+  method which will get the class (``factory``) and the configuration
+  context (``config``) as positional arguments and then the values of
+  the directives as keyword parameters.  Note that when binding the
+  directives, you may
 
-    o Unless set with a different value, the default value will be
-      ``None``.  You can either set a different default value or
-      override the ``get_default`` method for a computed default.
+  - set the name of the keyword parameter if you want it to be
+    different than the directive's name,
 
-    For example, consider the implementation of the ``grok.name``
-    directive::
+  - set a default value if you want it to be different from the
+    directive's standard default,
 
-      class name(martian.Directive):
-          scope = martian.CLASS
-          store = martian.ONCE
-          default = u''
-          validate = martian.validateText
+  - pass in a factory for a computed default value (``get_default``).
 
-    Or a bit more involved (and made-up) example::
+  If you need still need to manually retrieve directive values from an
+  object (a class, an instance or a module), you can do so by using
+  the ``get`` method of the bound directive, e.g.::
 
-      class bases(martian.Directive):
-          scope = martian.CLASS
-          scope = martian.ONCE
+    class_context = grok.context.bind().get(factory, module=module)
+    just_module_context = grok.context.bind().get(module=module)
 
-          # The factory is called with the parameters of the directive
-          # and may transform the values into whatever should be stored.
-          def factory(self, *values):
-              return list(values)
+* Custom directives need to be re-implemented using Martian's new
+  ``Directive`` base class.  The directive scope, the type of storage,
+  the validator and a potential default value are all defined as
+  class-level variables:
 
-          # This validator makes sure that the directive can only take
-          # a list of classes an argument
-          def validate(self, *values):
-              for value in values:
-                  if not isinstance(value, type):
-                      raise GrokError("%r is not a class!" % value)
+  - The directive scope can either one of ``martian.CLASS``,
+    ``martian.MODULE``, ``martian.CLASS_OR_MODULE``.
 
-          # If the directive wasn't used on a class, the directive's
-          # getter will return this computed default: a list of the
-          # class's bases
-          def get_default(self, component):
-              return list(component.__bases__)
+  - The type of storage can be either one of ``martian.ONCE``,
+    ``martian.MULTIPLE``, ``martian.DICT``.
 
+  - An optional validator may be one of ``validateText``,
+    ``validateInterface``, ``validateInterfaceOrClass`` or a custom
+    method.
 
+  - Unless set with a different value, the standard default value will
+    be ``None``.
+
+  For example, consider the implementation of the ``grok.name``
+  directive::
+
+    class name(martian.Directive):
+        scope = martian.CLASS
+        store = martian.ONCE
+        default = u''
+        validate = martian.validateText
+
+  Or a bit more involved (and made-up) example::
+
+    class bases(martian.Directive):
+        scope = martian.CLASS
+        scope = martian.ONCE
+        default = []
+
+        # The factory is called with the parameters of the directive
+        # and may transform the values into whatever should be stored.
+        def factory(self, *values):
+            return list(values)
+
+        # This validator makes sure that the directive can only take
+        # a list of classes an argument
+        def validate(self, *values):
+            for value in values:
+                if not isinstance(value, type):
+                    raise GrokError("%r is not a class!" % value)
+
 * We moved to newer versions of zope packages, using the KGS list for
   Zope 3.4c1.  This means your code can now get some new deprecation
   warnings for imports that have been moved. Please check your code

Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/setup.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -35,8 +35,8 @@
     include_package_data = True,
     zip_safe=False,
     install_requires=['setuptools',
-                      'martian >= 0.9.4',
-                      'grokcore.component >= 1.2',
+                      'martian >= 0.9.6',
+                      'grokcore.component >= 1.3',
                       'simplejson',
                       'pytz',
                       'ZODB3',

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/components.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -437,7 +437,7 @@
         if subob is not None:
             return util.safely_locate_maybe(subob, self.context, name)
 
-        traversable_dict = grok.traversable.get(self.context)
+        traversable_dict = grok.traversable.bind().get(self.context)
         if traversable_dict:
             if name in traversable_dict:
                 subob = getattr(self.context, traversable_dict[name])
@@ -666,8 +666,7 @@
 
     def __init__(self, context, request, view):
         super(ViewletManager, self).__init__(context, request, view)
-        self.__name__ = util.get_name_classname(self.__class__)
-
+        self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
             interface.Interface,
@@ -718,10 +717,7 @@
 
     def __init__(self, context, request, view, manager):
         super(Viewlet, self).__init__(context, request, view, manager)
-        # would be nice to move this to the ViewletGrokker but
-        # new objects don't have __name__ of their class
-        self.__name__ = util.get_name_classname(self.__class__)
-
+        self.__name__ = self.__view_name__
         self.static = component.queryAdapter(
             self.request,
             interface.Interface,

Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/directive.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -24,6 +24,7 @@
 from martian import util
 from martian.error import GrokImportError, GrokError
 from martian.directive import StoreMultipleTimes
+from grokcore.component.scan import UnambiguousComponentScope
 from grok import components
 
 # Define grok directives
@@ -48,7 +49,7 @@
                                   "provides argument of %s." % self.name)
 
         if provides is None:
-            provides = grok.provides.get(factory)
+            provides = grok.provides.bind().get(factory)
 
         if provides is None:
             if util.check_subclass(factory, grok.LocalUtility):
@@ -134,7 +135,7 @@
 
     def factory(self, value):
         if util.check_subclass(value, components.Permission):
-            return grok.name.get(value)
+            return grok.name.bind().get(value)
         return value
 
     def __call__(self, func):
@@ -170,7 +171,7 @@
     pass
 
 class viewletmanager(OneInterfaceOrClassOnClassOrModule):
-    pass
+    scope = UnambiguousComponentScope('viewletmanager')
 
 class view(OneInterfaceOrClassOnClassOrModule):
     default = IBrowserView

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/meta.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -51,14 +51,30 @@
 from grok import components, formlib, templatereg
 from grok.util import check_permission, make_checker
 from grok.util import public_methods_from_class
-from grok.util import get_name_classname
 from grok.rest import RestPublisher
 from grok.interfaces import IRESTSkinType
 from grok.interfaces import IViewletManager as IGrokViewletManager
 
 from grokcore.component.scan import determine_module_component
-from grokcore.component.scan import check_module_component
 
+
+def default_view_name(factory, module=None, **data):
+    return factory.__name__.lower()
+
+def default_fallback_to_name(factory, module, name, **data):
+    return name
+
+def default_annotation_provides(factory, module, **data):
+    base_interfaces = interface.implementedBy(grok.Annotation)
+    factory_interfaces = interface.implementedBy(factory)
+    real_interfaces = list(factory_interfaces - base_interfaces)
+    util.check_implements_one_from_list(real_interfaces, factory)
+    return real_interfaces[0]
+
+def default_annotation_name(factory, module, **data):
+    return factory.__module__ + '.' + factory.__name__
+
+
 class ViewletManagerContextGrokker(martian.GlobalGrokker):
 
     priority = 1001
@@ -70,22 +86,24 @@
         grok.viewletmanager.set(module, viewletmanager)
         return True
 
+
 class XMLRPCGrokker(martian.ClassGrokker):
     component_class = grok.XMLRPC
+    directives = [
+        grok.context.bind(),
+        grok.require.bind(name='class_permission'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        view_context = grok.context.get(factory, module_info.getModule())
-
+    def execute(self, factory, config, class_permission, context, **kw):
         methods = public_methods_from_class(factory)
-        default_permission = grok.require.get(factory)
 
         # make sure we issue an action to check whether this permission
         # exists. That's the only thing that action does
-        if default_permission is not None:
+        if class_permission is not None:
             config.action(
                 discriminator=None,
                 callable=check_permission,
-                args=(factory, default_permission)
+                args=(factory, class_permission)
                 )
 
         for method in methods:
@@ -98,7 +116,7 @@
                 {'__call__': method}
                 )
 
-            adapts = (view_context, IXMLRPCRequest)
+            adapts = (context, IXMLRPCRequest)
             config.action(
                 discriminator=('adapter', adapts, interface.Interface, name),
                 callable=component.provideAdapter,
@@ -108,9 +126,9 @@
             # Protect method_view with either the permission that was
             # set on the method, the default permission from the class
             # level or zope.Public.
-            permission = grok.require.get(method)
+            permission = grok.require.bind().get(method)
             if permission is None:
-                permission = default_permission
+                permission = class_permission
 
             config.action(
                 discriminator=('protectName', method_view, '__call__'),
@@ -119,28 +137,26 @@
                 )
         return True
 
+
 class RESTGrokker(martian.ClassGrokker):
     component_class = grok.REST
+    directives = [
+        grok.context.bind(),
+        grok.layer.bind(default=grok.IRESTLayer),
+        grok.require.bind(name='class_permission'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        view_context = grok.context.get(factory, module_info.getModule())
-
+    def execute(self, factory, config, class_permission, context, layer, **kw):
         methods = public_methods_from_class(factory)
-        default_permission = grok.require.get(factory)
         # make sure we issue an action to check whether this permission
         # exists. That's the only thing that action does
-        if default_permission is not None:
+        if class_permission is not None:
             config.action(
                 discriminator=None,
                 callable=check_permission,
-                args=(factory, default_permission)
+                args=(factory, class_permission)
                 )
 
-        # grab layer from class or module
-        view_layer = grok.layer.get(factory, module_info.getModule())
-        if view_layer is None:
-            view_layer = grok.IRESTLayer
-
         for method in methods:
             name = method.__name__
 
@@ -151,7 +167,7 @@
                 {'__call__': method }
                 )
 
-            adapts = (view_context, view_layer)
+            adapts = (context, layer)
             config.action(
                 discriminator=('adapter', adapts, interface.Interface, name),
                 callable=component.provideAdapter,
@@ -161,9 +177,9 @@
             # Protect method_view with either the permission that was
             # set on the method, the default permission from the class
             # level or zope.Public.
-            permission = grok.require.get(method)
+            permission = grok.require.bind().get(method)
             if permission is None:
-                permission = default_permission
+                permission = class_permission
 
             config.action(
                 discriminator=('protectName', method_view, '__call__'),
@@ -175,16 +191,24 @@
 
 class ViewGrokker(martian.ClassGrokker):
     component_class = grok.View
+    directives = [
+        grok.context.bind(),
+        grok.layer.bind(default=IDefaultBrowserLayer),
+        grok.name.bind(get_default=default_view_name),
+        grok.require.bind(name='permission'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        view_context = grok.context.get(factory, module_info.getModule())
-
+    def grok(self, name, factory, module_info, **kw):
+        # Need to store the module info object on the view class so that it
+        # can look up the 'static' resource directory.
         factory.module_info = module_info
+        return super(ViewGrokker, self).grok(name, factory, module_info, **kw)
 
+    def execute(self, factory, config, context, layer, name, permission, **kw):
         if util.check_subclass(factory, components.GrokForm):
             # setup form_fields from context class if we've encountered a form
             if getattr(factory, 'form_fields', None) is None:
-                factory.form_fields = formlib.get_auto_fields(view_context)
+                factory.form_fields = formlib.get_auto_fields(context)
 
             if not getattr(factory.render, 'base_method', False):
                 raise GrokError(
@@ -194,41 +218,34 @@
                     factory)
 
         # find templates
-        templates = module_info.getAnnotation('grok.templates', None)
+        templates = factory.module_info.getAnnotation('grok.templates', None)
         if templates is not None:
             config.action(
                 discriminator=None,
                 callable=self.checkTemplates,
-                args=(templates, module_info, factory)
-            )
+                args=(templates, factory.module_info, factory)
+                )
 
         # safety belt: make sure that the programmer didn't use
         # @grok.require on any of the view's methods.
         methods = util.methods_from_class(factory)
         for method in methods:
-            if grok.require.get(method) is not None:
+            if grok.require.bind().get(method) is not None:
                 raise GrokError('The @grok.require decorator is used for '
                                 'method %r in view %r. It may only be used '
                                 'for XML-RPC methods.'
                                 % (method.__name__, factory), factory)
 
-        # grab layer from class or module
-        view_layer = grok.layer.get(factory, module_info.getModule())
-        if view_layer is None:
-            view_layer = IDefaultBrowserLayer
-
-        view_name = get_name_classname(factory)
         # __view_name__ is needed to support IAbsoluteURL on views
-        factory.__view_name__ = view_name
-        adapts = (view_context, view_layer)
+        factory.__view_name__ = name
+        adapts = (context, layer)
 
         config.action(
-            discriminator=('adapter', adapts, interface.Interface, view_name),
+            discriminator=('adapter', adapts, interface.Interface, name),
             callable=component.provideAdapter,
-            args=(factory, adapts, interface.Interface, view_name),
+            args=(factory, adapts, interface.Interface, name),
             )
 
-        permission = grok.require.get(factory)
         config.action(
             discriminator=('protectName', factory, '__call__'),
             callable=make_checker,
@@ -249,19 +266,22 @@
 
 class JSONGrokker(martian.ClassGrokker):
     component_class = grok.JSON
+    directives = [
+        grok.context.bind(),
+        grok.require.bind(name='class_permission'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        view_context = grok.context.get(factory, module_info.getModule())
+    # TODO: this grokker doesn't support layers yet
 
+    def execute(self, factory, config, context, class_permission, **kw):
         methods = public_methods_from_class(factory)
-        default_permission = grok.require.get(factory)
         # make sure we issue an action to check whether this permission
         # exists. That's the only thing that action does
-        if default_permission is not None:
+        if class_permission is not None:
             config.action(
                 discriminator=None,
                 callable=check_permission,
-                args=(factory, default_permission)
+                args=(factory, class_permission)
                 )
 
         for method in methods:
@@ -278,7 +298,7 @@
                 factory.__name__, (factory,),
                 {'__view_name__': method.__name__}
                 )
-            adapts = (view_context, IDefaultBrowserLayer)
+            adapts = (context, IDefaultBrowserLayer)
             name = method.__name__
 
             config.action(
@@ -291,9 +311,9 @@
             # set on the method, the default permission from the class
             # level or zope.Public.
 
-            permission = grok.require.get(method)
+            permission = grok.require.bind().get(method)
             if permission is None:
-                permission = default_permission
+                permission = class_permission
 
             config.action(
                 discriminator=('protectName', method_view, '__call__'),
@@ -305,11 +325,12 @@
 
 class TraverserGrokker(martian.ClassGrokker):
     component_class = grok.Traverser
+    directives = [
+        grok.context.bind()
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        factory_context = grok.context.get(factory, module_info.getModule())
-        adapts = (factory_context, IHTTPRequest)
-
+    def execute(self, factory, config, context, **kw):
+        adapts = (context, IHTTPRequest)
         config.action(
             discriminator=('adapter', adapts, IBrowserPublisher, ''),
             callable=component.provideAdapter,
@@ -343,12 +364,12 @@
             discriminator=None,
             callable=templates.register,
             args=(name, instance)
-        )
+            )
         config.action(
             discriminator=None,
             callable=instance._annotateGrokInfo,
             args=(name, module_info.dotted_name)
-        )
+            )
         return True
 
 
@@ -366,7 +387,7 @@
             discriminator=None,
             callable=templates.findFilesystem,
             args=(module_info,)
-        )
+            )
         return True
 
 
@@ -382,7 +403,7 @@
             discriminator=None,
             callable=templates.checkUnassociated,
             args=(module_info,)
-        )
+            )
         return True
 
 
@@ -425,9 +446,11 @@
 class SiteGrokker(martian.ClassGrokker):
     component_class = grok.Site
     priority = 500
+    directives = [
+        grok.local_utility.bind(name='infos'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        infos = grok.local_utility.get(factory)
+    def execute(self, factory, config, infos, **kw):
         if not infos:
             return False
 
@@ -506,99 +529,94 @@
     site_manager.registerUtility(utility, provided=provides,
                                  name=name)
 
+
 class PermissionGrokker(martian.ClassGrokker):
     component_class = grok.Permission
     priority = 1500
+    directives = [
+        grok.name.bind(),
+        grok.title.bind(get_default=default_fallback_to_name),
+        grok.description.bind(),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        id = grok.name.get(factory)
-        if not id:
+    def execute(self, factory, config, name, title, description, **kw):
+        if not name:
             raise GrokError(
                 "A permission needs to have a dotted name for its id. Use "
                 "grok.name to specify one.", factory)
         # We can safely convert to unicode, since the directives make sure
         # it is either unicode already or ASCII.
-        id = unicode(id)
-        title = grok.title.get(factory)
-        if not title:
-            title = id
-        permission = factory(id, unicode(title),
-                             unicode(grok.description.get(factory)))
+        permission = factory(unicode(name), unicode(title),
+                             unicode(description))
 
         config.action(
-            discriminator=('utility', IPermission, id),
+            discriminator=('utility', IPermission, name),
             callable=component.provideUtility,
-            args=(permission, IPermission, id),
+            args=(permission, IPermission, name),
             order=-1 # need to do this early in the process
             )
         return True
 
+
 class RoleGrokker(martian.ClassGrokker):
     component_class = grok.Role
     priority = PermissionGrokker.priority - 1
+    directives = [
+        grok.name.bind(),
+        grok.title.bind(get_default=default_fallback_to_name),
+        grok.description.bind(),
+        grok.permissions.bind(),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        id = grok.name.get(factory)
-        if not id:
+    def execute(self, factory, config, name, title, description,
+                permissions, **kw):
+        if not name:
             raise GrokError(
                 "A role needs to have a dotted name for its id. Use "
                 "grok.name to specify one.", factory)
         # We can safely convert to unicode, since the directives makes sure
         # it is either unicode already or ASCII.
-        id = unicode(id)
-        title = grok.title.get(factory)
-        if not title:
-            title = id
-        role = factory(id, unicode(title),
-                       unicode(grok.description.get(factory)))
+        role = factory(unicode(name), unicode(title), unicode(description))
 
         config.action(
-            discriminator=('utility', IRole, id),
+            discriminator=('utility', IRole, name),
             callable=component.provideUtility,
-            args=(role, IRole, id),
+            args=(role, IRole, name),
             )
 
-        permissions = grok.permissions.get(factory)
         for permission in permissions:
             config.action(
-                discriminator=('grantPermissionToRole', permission, id),
+                discriminator=('grantPermissionToRole', permission, name),
                 callable=rolePermissionManager.grantPermissionToRole,
-                args=(permission, id),
+                args=(permission, name),
                 )
         return True
 
+
 class AnnotationGrokker(martian.ClassGrokker):
     component_class = grok.Annotation
+    directives = [
+        grok.context.bind(name='adapter_context'),
+        grok.provides.bind(get_default=default_annotation_provides),
+        grok.name.bind(get_default=default_annotation_name),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        adapter_context = grok.context.get(factory, module_info.getModule())
-        provides = grok.provides.get(factory)
-        if provides is None:
-            base_interfaces = interface.implementedBy(grok.Annotation)
-            factory_interfaces = interface.implementedBy(factory)
-            real_interfaces = list(factory_interfaces - base_interfaces)
-            util.check_implements_one_from_list(real_interfaces, factory)
-            provides = real_interfaces[0]
-
-        key = grok.name.get(factory)
-        if not key:
-            key = factory.__module__ + '.' + factory.__name__
-
+    def execute(self, factory, config, adapter_context, provides, name, **kw):
         @component.adapter(adapter_context)
         @interface.implementer(provides)
         def getAnnotation(context):
             annotations = IAnnotations(context)
             try:
-                result = annotations[key]
+                result = annotations[name]
             except KeyError:
                 result = factory()
-                annotations[key] = result
+                annotations[name] = result
 
             # Containment has to be set up late to allow containment
             # proxies to be applied, if needed. This does not trigger
             # an event and is idempotent if containment is set up
             # already.
-            contained_result = contained(result, context, key)
+            contained_result = contained(result, context, name)
             return contained_result
 
         config.action(
@@ -629,17 +647,19 @@
     component_class = components.IndexesClass
 
     def grok(self, name, factory, module_info, config, **kw):
-        site = grok.site.get(factory)
+        site = grok.site.bind().get(factory)
+        context = grok.context.bind().get(factory, module_info.getModule())
+        catalog_name = grok.name.bind().get(factory)
+
         if site is None:
             raise GrokError("No site specified for grok.Indexes "
                             "subclass in module %r. "
-                            "Use grok.site() to specify." % module_info.getModule(),
+                            "Use grok.site() to specify."
+                            % module_info.getModule(),
                             factory)
         indexes = getattr(factory, '__grok_indexes__', None)
         if indexes is None:
             return False
-        context = grok.context.get(factory, module_info.getModule())
-        catalog_name = grok.name.get(factory)
 
         subscriber = IndexesSetupSubscriber(catalog_name, indexes,
                                             context, module_info)
@@ -705,13 +725,12 @@
 
 class SkinGrokker(martian.ClassGrokker):
     component_class = grok.Skin
+    directives = [
+        grok.layer.bind(default=IBrowserRequest),
+        grok.name.bind(get_default=default_view_name),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        layer = grok.layer.get(factory, module_info.getModule())
-        if layer is None:
-            layer = IBrowserRequest
-
-        name = get_name_classname(factory)
+    def execute(self, factory, config, name, layer, **kw):
         config.action(
             discriminator=('skin', name),
             callable=zope.component.interface.provideInterface,
@@ -721,13 +740,12 @@
 
 class RESTProtocolGrokker(martian.ClassGrokker):
     component_class = grok.RESTProtocol
+    directives = [
+        grok.layer.bind(default=IBrowserRequest),
+        grok.name.bind(get_default=default_view_name),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        layer = grok.layer.get(factory, module_info.getModule())
-        if layer is None:
-            layer = IBrowserRequest
-
-        name = get_name_classname(factory)
+    def execute(self, factory, config, name, layer, **kw):
         config.action(
             discriminator=('restprotocol', name),
             callable=zope.component.interface.provideInterface,
@@ -737,35 +755,38 @@
 
 class ViewletManagerGrokker(martian.ClassGrokker):
     component_class = grok.ViewletManager
+    directives = [
+        grok.context.bind(),
+        grok.layer.bind(default=IDefaultBrowserLayer),
+        grok.view.bind(),
+        grok.name.bind(),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
+    def grok(self, name, factory, module_info, **kw):
+        # Need to store the module info object on the view class so that it
+        # can look up the 'static' resource directory.
         factory.module_info = module_info
+        return super(ViewletManagerGrokker, self).grok(
+            name, factory, module_info, **kw)
 
+    def execute(self, factory, config, context, layer, view, name, **kw):
+        # This will be used to support __name__ on the viewlet manager
+        factory.__view_name__ = name
+
         # find templates
-        templates = module_info.getAnnotation('grok.templates', None)
+        templates = factory.module_info.getAnnotation('grok.templates', None)
         if templates is not None:
             config.action(
                 discriminator=None,
                 callable=self.checkTemplates,
-                args=(templates, module_info, factory)
+                args=(templates, factory.module_info, factory)
                 )
 
-        name = grok.name.get(factory)
-        view_context = grok.context.get(factory, module_info.getModule())
-        view = grok.view.get(factory, module_info.getModule())
-
-        viewlet_layer = grok.layer.get(factory, module_info.getModule())
-        if viewlet_layer is None:
-            viewlet_layer = IDefaultBrowserLayer
-
         config.action(
-            discriminator = ('viewletManager', view_context, viewlet_layer,
-                             view, name),
+            discriminator = ('viewletManager', context, layer, view, name),
             callable = component.provideAdapter,
-            args = (factory, (view_context, viewlet_layer, view),
-                    IViewletManager, name)
+            args = (factory, (context, layer, view), IViewletManager, name)
             )
-
         return True
 
     def checkTemplates(self, templates, module_info, factory):
@@ -779,41 +800,44 @@
 
 class ViewletGrokker(martian.ClassGrokker):
     component_class = grok.Viewlet
+    directives = [
+        grok.context.bind(),
+        grok.layer.bind(default=IDefaultBrowserLayer),
+        grok.view.bind(),
+        grok.viewletmanager.bind(),
+        grok.name.bind(get_default=default_view_name),
+        grok.require.bind(name='permission'),
+        ]
 
-    def grok(self, name, factory, module_info, config, **kw):
-        viewlet_name = get_name_classname(factory)
-        viewlet_context = grok.context.get(factory, module_info.getModule())
+    def grok(self, name, factory, module_info, **kw):
+        # Need to store the module info object on the view class so that it
+        # can look up the 'static' resource directory.
+        factory.module_info = module_info
+        return super(ViewletGrokker, self).grok(
+            name, factory, module_info, **kw)
 
-        factory.module_info = module_info # to make /static available
+    def execute(self, factory, config,
+                context, layer, view, viewletmanager, name, permission, **kw):
+        # This will be used to support __name__ on the viewlet
+        factory.__view_name__ = name
 
         # find templates
-        templates = module_info.getAnnotation('grok.templates', None)
+        templates = factory.module_info.getAnnotation('grok.templates', None)
         if templates is not None:
             config.action(
                 discriminator=None,
                 callable=self.checkTemplates,
-                args=(templates, module_info, factory)
+                args=(templates, factory.module_info, factory)
                 )
 
-        view = grok.view.get(factory, module_info.getModule())
-        viewlet_layer = grok.layer.get(factory, module_info.getModule())
-        if viewlet_layer is None:
-            viewlet_layer = IDefaultBrowserLayer
-
-        viewletmanager = grok.viewletmanager.get(factory,
-                                                 module_info.getModule())
-        check_module_component(
-            factory, viewletmanager, 'viewletmanager', grok.viewletmanager)
-
         config.action(
-            discriminator = ('viewlet', viewlet_context, viewlet_layer,
-                             view, viewletmanager, viewlet_name),
+            discriminator = ('viewlet', context, layer,
+                             view, viewletmanager, name),
             callable = component.provideAdapter,
-            args = (factory, (viewlet_context, viewlet_layer, view,
-                    viewletmanager), IViewlet, viewlet_name)
+            args = (factory, (context, layer, view, viewletmanager),
+                    IViewlet, name)
             )
 
-        permission = grok.require.get(factory)
         config.action(
             discriminator=('protectName', factory, '__call__'),
             callable=make_checker,

Modified: grok/trunk/src/grok/templatereg.py
===================================================================
--- grok/trunk/src/grok/templatereg.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/templatereg.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -24,7 +24,8 @@
         return entry['template']
 
     def findFilesystem(self, module_info):
-        template_dir_name = grok.templatedir.get(module_info.getModule())
+        template_dir_name = grok.templatedir.bind().get(
+            module=module_info.getModule())
         if template_dir_name is None:
             template_dir_name = module_info.name + '_templates'
 
@@ -88,7 +89,7 @@
     def checkTemplates(self, module_info, factory, component_name,
                        has_render, has_no_render):
         factory_name = factory.__name__.lower()
-        template_name = grok.template.get(factory)
+        template_name = grok.template.bind().get(factory)
         if template_name is None:
             template_name = factory_name
 

Modified: grok/trunk/src/grok/tests/directive/multipleasdict.py
===================================================================
--- grok/trunk/src/grok/tests/directive/multipleasdict.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/tests/directive/multipleasdict.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -4,7 +4,7 @@
 
   >>> from martian import scan
   >>> import grok
-  >>> g = grok.traversable.get(Club)
+  >>> g = grok.traversable.bind().get(Club)
   >>> isinstance(g, dict)
   True
   >>> g['demo']

Modified: grok/trunk/src/grok/tests/directive/multipletimes.py
===================================================================
--- grok/trunk/src/grok/tests/directive/multipletimes.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/tests/directive/multipletimes.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -3,21 +3,26 @@
 GlobalUtilityInfo objects annotated on the module.
 
   >>> from grok.tests.directive import multipletimes
-  >>> guis = grok.global_utility.get(multipletimes)
-  >>> guis
-  [<grokcore.component.directive.GlobalUtilityInfo object at 0x...>,
-   <grokcore.component.directive.GlobalUtilityInfo object at 0x...>]
-  >>> guis[0].factory
+  >>> guis = grok.global_utility.bind().get(module=multipletimes)
+
+  >>> guis = grok.global_utility.bind().get(module=multipletimes)
+  >>> len(guis)
+  2
+
+  >>> factory, provides, name, direct = guis[0]
+  >>> factory
   <class 'grok.tests.directive.multipletimes.Club'>
-  >>> guis[0].provides
+  >>> provides
   <InterfaceClass grok.tests.directive.multipletimes.IClub>
-  >>> guis[0].name
+  >>> name
   'foo'
-  >>> guis[1].factory
+
+  >>> factory, provides, name, direct = guis[1]
+  >>> factory
   <class 'grok.tests.directive.multipletimes.Cave'>
-  >>> guis[1].provides is None
+  >>> provides is None
   True
-  >>> guis[1].name
+  >>> name
   u''
   
 """

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/src/grok/util.py	2008-05-14 16:29:11 UTC (rev 86746)
@@ -29,12 +29,6 @@
 from martian.error import GrokError
 from martian.util import methods_from_class
 
-def get_name_classname(factory):
-    name = grok.name.get(factory)
-    if not name:
-        name = factory.__name__.lower()
-    return name
-
 def public_methods_from_class(factory):
     return [m for m in methods_from_class(factory) if \
             not m.__name__.startswith('_')]
@@ -103,7 +97,7 @@
     interface.directlyProvides(request, *ifaces)
 
 def _sort_key(component):
-    explicit_order, implicit_order = grok.order.get(component)
+    explicit_order, implicit_order = grok.order.bind().get(component)
     return (explicit_order,
             component.__module__,
             implicit_order,

Modified: grok/trunk/versions.cfg
===================================================================
--- grok/trunk/versions.cfg	2008-05-14 16:24:09 UTC (rev 86745)
+++ grok/trunk/versions.cfg	2008-05-14 16:29:11 UTC (rev 86746)
@@ -5,8 +5,8 @@
 ZConfig = 2.5.1
 ZODB3 = 3.8
 docutils = 0.4
-martian = 0.9.5
-grokcore.component = 1.2.1
+martian = 0.9.6
+grokcore.component = 1.3
 mechanize = 0.1.7b
 pytz = 2007k
 simplejson = 1.7.1



More information about the Checkins mailing list