[Checkins] SVN: grok/trunk/ Merge jw-simpler-skin-registration branch.

Philipp von Weitershausen philikon at philikon.de
Sat Aug 2 07:50:27 EDT 2008


Log message for revision 89198:
  Merge jw-simpler-skin-registration branch.
  

Changed:
  U   grok/trunk/CHANGES.txt
  U   grok/trunk/doc/upgrade.txt
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/components.py
  U   grok/trunk/src/grok/directive.py
  D   grok/trunk/src/grok/ftests/view/layers.py
  A   grok/trunk/src/grok/ftests/view/skindirective.py
  U   grok/trunk/src/grok/ftests/viewlet/viewlet_security.py
  U   grok/trunk/src/grok/interfaces.py
  U   grok/trunk/src/grok/meta.py
  D   grok/trunk/src/grok/tests/conflict/skin.py
  A   grok/trunk/src/grok/tests/skin/
  U   grok/trunk/src/grok/tests/test_grok.py

-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/CHANGES.txt	2008-08-02 11:50:27 UTC (rev 89198)
@@ -12,6 +12,11 @@
   your environment, add ``grokui.admin`` to the required packages in
   the ``setup.py`` of your package.
 
+* Removed ``grok.Skin`` baseclass in favour of a ``grok.skin(name)``
+  directive that can be used on layer interfaces.  Also removed the
+  ``IGrokLayer`` interface in favour of exposing ``IBrowserRequest``
+  from the grok package.
+
 Bug fixes
 ---------
 

Modified: grok/trunk/doc/upgrade.txt
===================================================================
--- grok/trunk/doc/upgrade.txt	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/doc/upgrade.txt	2008-08-02 11:50:27 UTC (rev 89198)
@@ -6,6 +6,28 @@
 describes changes involving incompatibilities or deprecations, not new
 features (please refer to ``CHANGES.txt`` for those).
 
+Upgrading to 0.14
+-----------------
+
+* The ``grok.Skin`` class has been removed in favour of a
+  ``grok.skin()`` directive for interfaces.  For instance, if you
+  previously registered a browser layer as a skin like so::
+
+    class IMyLayer(grok.IGrokLayer):
+        pass
+
+    class MySkin(grok.Skin):
+        grok.layer(IMyLayer)
+
+  you can now simply write::
+
+    class IMyLayer(grok.IBrowserRequest):
+        grok.skin('myskin')
+
+  As you can see, ``IGrokLayer`` has also been removed, in favour of
+  the exposure of ``IBrowserRequest``.
+
+
 Upgrading to 0.13
 -----------------
 

Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/__init__.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -23,6 +23,9 @@
     IObjectModifiedEvent, ObjectModifiedEvent,
     IObjectCopiedEvent, ObjectCopiedEvent)
 
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+
 from zope.app.container.contained import (
     IObjectAddedEvent, ObjectAddedEvent,
     IObjectMovedEvent, ObjectMovedEvent,
@@ -39,7 +42,6 @@
 from grok.components import Application, Form, AddForm, EditForm, DisplayForm
 from grok.components import Indexes
 from grok.components import Permission, Role, Public
-from grok.components import Skin, IGrokLayer
 from grok.components import RESTProtocol, IRESTLayer
 from grok.interfaces import IRESTSkinType
 from grok.components import ViewletManager, Viewlet
@@ -49,7 +51,7 @@
     context, name, title, description, provides, global_utility, direct)
 from grok.directive import (
     template, templatedir, local_utility, permissions, require, site,
-    layer, viewletmanager, view, traversable, order)
+    layer, viewletmanager, view, traversable, order, skin)
 from grokcore.component.decorators import subscribe, adapter, implementer
 from martian.error import GrokError, GrokImportError
 

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/components.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -29,6 +29,7 @@
 from zope.securitypolicy.role import Role
 from zope.publisher.browser import BrowserPage
 from zope.publisher.interfaces import NotFound
+from zope.publisher.interfaces.browser import IBrowserRequest
 from zope.publisher.interfaces.browser import IBrowserPublisher
 from zope.publisher.interfaces.http import IHTTPRequest
 from zope.publisher.publish import mapply
@@ -651,15 +652,9 @@
 class Role(Role):
     pass
 
-class IGrokLayer(interface.Interface):
+class IRESTLayer(IBrowserRequest):
     pass
 
-class IRESTLayer(interface.Interface):
-    pass
-
-class Skin(object):
-    pass
-
 class RESTProtocol(object):
     pass
 

Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/directive.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -18,12 +18,14 @@
 import grok
 from zope import interface
 from zope.interface.interfaces import IInterface
+from zope.interface.interface import TAGGED_DATA
+
 from zope.publisher.interfaces.browser import IBrowserView
 
 import martian
 from martian import util
 from martian.error import GrokImportError, GrokError
-from martian.directive import StoreMultipleTimes
+from martian.directive import StoreOnce, StoreMultipleTimes
 from grokcore.component.scan import UnambiguousComponentScope
 from grok import components
 
@@ -195,3 +197,33 @@
     def factory(self, value=0):
         order._order += 1
         return value, order._order
+
+class TaggedValueStoreOnce(StoreOnce):
+    """Stores the directive value in a interface tagged value.
+    """
+
+    def get(self, directive, component, default):
+        return component.queryTaggedValue(directive.dotted_name(), default)
+
+    def set(self, locals_, directive, value):
+        if directive.dotted_name() in locals_:
+            raise GrokImportError(
+                "The '%s' directive can only be called once per %s." %
+                (directive.name, directive.scope.description))
+        # Make use of the implementation details of interface tagged
+        # values.  Instead of being able to call "setTaggedValue()"
+        # on an interface object, we only have access to the "locals"
+        # of the interface object.  We inject whatever setTaggedValue()
+        # would've injected.
+        taggeddata = locals_.setdefault(TAGGED_DATA, {})
+        taggeddata[directive.dotted_name()] = value
+
+    def setattr(self, context, directive, value):
+        context.setTaggedValue(directive.dotted_name(), value)
+
+class skin(martian.Directive):
+    # We cannot do any better than to check for a class scope. Ideally we
+    # would've checked whether the context is indeed an Interface class.
+    scope = martian.CLASS
+    store = TaggedValueStoreOnce()
+    validate = martian.validateText

Deleted: grok/trunk/src/grok/ftests/view/layers.py
===================================================================
--- grok/trunk/src/grok/ftests/view/layers.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/ftests/view/layers.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -1,63 +0,0 @@
-"""
-  >>> getRootFolder()["manfred"] = Mammoth()
- 
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-  >>> browser.open("http://localhost/++skin++Basic/manfred/@@cavedrawings")
-  >>> print browser.contents
-  <html>
-  <body>
-  <h1>Hello, world!</h1>
-  </body>
-  </html>
-  
-  >>> browser.open("http://localhost/++skin++Rotterdam/manfred/@@moredrawings")
-  >>> print browser.contents
-  Pretty
-
-  >>> browser.open("http://localhost/++skin++myskin/manfred/@@evenmoredrawings")
-  >>> print browser.contents
-  Awesome
-
-"""
-import grok
-from zope.app.basicskin import IBasicSkin
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.rotterdam import rotterdam
-from zope import interface
-
-grok.layer(IBasicSkin)
-
-class MySkinLayer(grok.IGrokLayer):
-    pass
-
-class MySkin(grok.Skin):
-    grok.layer(MySkinLayer)
-
-class Mammoth(grok.Model):
-    pass
-
-class CaveDrawings(grok.View):
-    pass
-
-cavedrawings = grok.PageTemplate("""\
-<html>
-<body>
-<h1>Hello, world!</h1>
-</body>
-</html>
-""")
-
-class MoreDrawings(grok.View):
-    grok.layer(rotterdam)
-
-    def render(self):
-        return "Pretty"
-
-
-class EvenMoreDrawings(grok.View):
-    grok.layer(MySkinLayer)
-
-    def render(self):
-        return "Awesome"

Copied: grok/trunk/src/grok/ftests/view/skindirective.py (from rev 89197, grok/branches/jw-simpler-skin-registration/src/grok/ftests/view/skindirective.py)
===================================================================
--- grok/trunk/src/grok/ftests/view/skindirective.py	                        (rev 0)
+++ grok/trunk/src/grok/ftests/view/skindirective.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -0,0 +1,61 @@
+"""
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/++skin++Basic/manfred/@@cavedrawings")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, world!</h1>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/++skin++Rotterdam/manfred/@@moredrawings")
+  >>> print browser.contents
+  Pretty
+
+  >>> browser.open("http://localhost/++skin++myskin/manfred/@@evenmoredrawings")
+  >>> print browser.contents
+  Awesome
+
+"""
+import grok
+from zope.app.basicskin import IBasicSkin
+from zope.app.rotterdam import rotterdam
+
+grok.layer(IBasicSkin)
+
+class MySkinLayer(grok.IBrowserRequest):
+    pass
+
+class MySkin(MySkinLayer):
+    grok.skin('myskin')
+
+class Mammoth(grok.Model):
+    pass
+
+class CaveDrawings(grok.View):
+    pass
+
+cavedrawings = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, world!</h1>
+</body>
+</html>
+""")
+
+class MoreDrawings(grok.View):
+    grok.layer(rotterdam)
+
+    def render(self):
+        return "Pretty"
+
+
+class EvenMoreDrawings(grok.View):
+    grok.layer(MySkinLayer)
+
+    def render(self):
+        return "Awesome"

Modified: grok/trunk/src/grok/ftests/viewlet/viewlet_security.py
===================================================================
--- grok/trunk/src/grok/ftests/viewlet/viewlet_security.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/ftests/viewlet/viewlet_security.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -154,8 +154,8 @@
     def render(self):
         return 'Gold Bone'
 
-class IBoneLayer(grok.IGrokLayer, IDefaultBrowserLayer):
-    pass
+class IBoneLayer(IDefaultBrowserLayer):
+    grok.skin('boneskin')
 
 class LayeredBone(grok.Viewlet):
     grok.context(Interface)
@@ -180,9 +180,6 @@
     def render(self):
         return 'Lady Viewlet'
 
-class BoneSkin(grok.Skin):
-    grok.layer(IBoneLayer)
-
 class NamedViewletManager(grok.ViewletManager):
     grok.context(Interface)
     grok.name('managerwithname')

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/interfaces.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -238,6 +238,8 @@
         """
 
     IRESTSkinType = interface.Attribute('The REST skin type')
+    IBrowserRequest = interface.Attribute('Browser request interface')
+    IDefaultBrowserLayer = interface.Attribute('Default layer for browser views.')
 
 class IGrokView(IBrowserPage, IBrowserView):
     """Grok views all provide this interface."""

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/meta.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -17,6 +17,7 @@
 
 import zope.component.interface
 from zope import interface, component
+from zope.interface.interface import InterfaceClass
 from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
                                                IBrowserRequest,
                                                IBrowserPublisher,
@@ -274,7 +275,7 @@
     # this needs to happen before any other grokkers execute that actually
     # use the templates
     martian.priority(1000)
-    
+
     def grok(self, name, instance, module_info, config, **kw):
         templates = module_info.getAnnotation('grok.templates', None)
         if templates is None:
@@ -634,19 +635,35 @@
         return intids
 
 
-class SkinGrokker(martian.ClassGrokker):
-    martian.component(grok.Skin)
-    martian.directive(grok.layer, default=IBrowserRequest)
-    martian.directive(grok.name, get_default=default_view_name)
+_skin_not_used = object()
 
-    def execute(self, factory, config, name, layer, **kw):
+class SkinInterfaceDirectiveGrokker(martian.InstanceGrokker):
+    martian.component(InterfaceClass)
+
+    def grok(self, name, interface, module_info, config, **kw):
+        skin = grok.skin.bind(default=_skin_not_used).get(interface)
+        if skin is _skin_not_used:
+            # The skin directive is not actually used on the found interface.
+            return False
+
+        if not interface.extends(IBrowserRequest):
+            # For layers it is required to extend IBrowserRequest.
+            raise GrokError(
+                "The grok.skin() directive is used on interface %r. "
+                "However, %r does not extend IBrowserRequest which is "
+                "required for interfaces that are used as layers and are to "
+                "be registered as a skin."
+                % (interface.__identifier__, interface.__identifier__),
+                interface
+                )
         config.action(
-            discriminator=('skin', name),
+            discriminator=('utility', IBrowserSkinType, skin),
             callable=zope.component.interface.provideInterface,
-            args=(name, layer, IBrowserSkinType)
+            args=(skin, interface, IBrowserSkinType)
             )
         return True
 
+
 class RESTProtocolGrokker(martian.ClassGrokker):
     martian.component(grok.RESTProtocol)
     martian.directive(grok.layer, default=IBrowserRequest)

Deleted: grok/trunk/src/grok/tests/conflict/skin.py
===================================================================
--- grok/trunk/src/grok/tests/conflict/skin.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/tests/conflict/skin.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -1,17 +0,0 @@
-"""
-We cannot register two skins under the same name::
-
-  >>> grok.testing.grok(__name__)
-  Traceback (most recent call last):
-    ...
-  ConfigurationConflictError: Conflicting configuration actions
-    For: ('skin', 'foo')
-"""
-
-import grok
-
-class Skin1(grok.Skin):
-    grok.name('foo')
-
-class Skin2(grok.Skin):
-    grok.name('foo')

Copied: grok/trunk/src/grok/tests/skin (from rev 89197, grok/branches/jw-simpler-skin-registration/src/grok/tests/skin)

Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py	2008-08-02 11:38:21 UTC (rev 89197)
+++ grok/trunk/src/grok/tests/test_grok.py	2008-08-02 11:50:27 UTC (rev 89198)
@@ -44,7 +44,7 @@
     suite = unittest.TestSuite()
     for name in ['adapter', 'error', 'view', 'event', 'security', 'catalog',
                  'zcml', 'static', 'utility', 'xmlrpc', 'json', 'container',
-                 'traversal', 'form', 'grokker', 'directive',
+                 'traversal', 'form', 'grokker', 'directive', 'skin',
                  'baseclass', 'annotation', 'application', 'template',
                  'viewlet', 'testsetup', 'conflict', 'order']:
         suite.addTest(suiteFromPackage(name))



More information about the Checkins mailing list