[Checkins] SVN: grok/branches/0.11/ Backport fix for not registering methods with names that

Jan-Wijbrand Kolman janwijbrand at gmail.com
Mon Jan 7 10:27:06 EST 2008


Log message for revision 82731:
  Backport fix for not registering methods with names that 
  start with an '_' as views on REST, XMLRPC and JSON components.

Changed:
  U   grok/branches/0.11/CHANGES.txt
  U   grok/branches/0.11/src/grok/meta.py
  U   grok/branches/0.11/src/grok/tests/json/view_lookup.py
  A   grok/branches/0.11/src/grok/tests/util/public_methods_from_class.py
  U   grok/branches/0.11/src/grok/util.py

-=-
Modified: grok/branches/0.11/CHANGES.txt
===================================================================
--- grok/branches/0.11/CHANGES.txt	2008-01-07 15:20:52 UTC (rev 82730)
+++ grok/branches/0.11/CHANGES.txt	2008-01-07 15:27:05 UTC (rev 82731)
@@ -7,6 +7,12 @@
 Bug fixes
 ---------
 
+* Do not register the publishTraverse and browserDefault methods of the
+  JSON component as views.
+
+* Methods with names that start with an '_' are not registered as views
+  for XMLRPC, REST and JSON components.
+
 * Use a configuration action for the registration of the static directory.
 
 * Fix https://bugs.launchpad.net/grok/+bug/161948: grok.testing.grok()

Modified: grok/branches/0.11/src/grok/meta.py
===================================================================
--- grok/branches/0.11/src/grok/meta.py	2008-01-07 15:20:52 UTC (rev 82730)
+++ grok/branches/0.11/src/grok/meta.py	2008-01-07 15:27:05 UTC (rev 82731)
@@ -47,7 +47,7 @@
 import grok
 from grok import components, formlib, templatereg
 from grok.util import check_adapts, get_default_permission, make_checker
-from grok.util import determine_class_directive
+from grok.util import determine_class_directive, public_methods_from_class
 from grok.rest import RestPublisher
 from grok.interfaces import IRESTSkinType
 
@@ -130,10 +130,9 @@
     def grok(self, name, factory, module_info, config, **kw):
         context = module_info.getAnnotation('grok.context', None)
         view_context = util.determine_class_context(factory, context)
-        # XXX We should really not make __FOO__ methods available to
-        # the outside -- need to discuss how to restrict such things.
-        methods = util.methods_from_class(factory)
 
+        methods = public_methods_from_class(factory)
+
         default_permission = get_default_permission(factory)
 
         for method in methods:
@@ -174,10 +173,9 @@
     def grok(self, name, factory, module_info, config, **kw):
         context = module_info.getAnnotation('grok.context', None)
         view_context = util.determine_class_context(factory, context)
-        # XXX We should really not make __FOO__ methods available to
-        # the outside -- need to discuss how to restrict such things.
-        methods = util.methods_from_class(factory)
 
+        methods = public_methods_from_class(factory)
+
         default_permission = get_default_permission(factory)
 
         # grab layer from class or module
@@ -294,11 +292,19 @@
     def grok(self, name, factory, module_info, config, **kw):
         context = module_info.getAnnotation('grok.context', None)
         view_context = util.determine_class_context(factory, context)
-        methods = util.methods_from_class(factory)
 
+        methods = public_methods_from_class(factory)
+
         default_permission = get_default_permission(factory)
 
         for method in methods:
+            # The grok.JSON component inherits methods from its baseclass
+            # (being zope.publisher.browser.BrowserPage) with names that
+            # do not start with an underscore, but should still not
+            # be registered as views. Ignore these methods:
+            if method.__name__ in ['browserDefault', 'publishTraverse']:
+                continue
+
             # Create a new class with a __view_name__ attribute so the
             # JSON class knows what method to call.
             method_view = type(

Modified: grok/branches/0.11/src/grok/tests/json/view_lookup.py
===================================================================
--- grok/branches/0.11/src/grok/tests/json/view_lookup.py	2008-01-07 15:20:52 UTC (rev 82730)
+++ grok/branches/0.11/src/grok/tests/json/view_lookup.py	2008-01-07 15:27:05 UTC (rev 82731)
@@ -20,7 +20,44 @@
   >>> view = getMultiAdapter((mammoth, request), name='another')
   >>> view()
   '{"another": "grok"}'
-  
+
+Although principally all methods of the JSON class are registered as views,
+methods with names that start with an underscore are not::
+
+  >>> view = getMultiAdapter((mammoth, request), name='_private')
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<grok.tests.json.view_lookup.Mammoth object at ...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass zope.interface.Interface>, '_private')
+
+Even more important, special methods like __call__ are not registered as viewws
+too. This test is here to make sure a previous bug has been fixed::
+
+  >>> view = getMultiAdapter((mammoth, request), name='__call__')
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<grok.tests.json.view_lookup.Mammoth object at ...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass zope.interface.Interface>, '__call__')
+
+For JSON views we also need to confirm some methods that are defined on the
+baseclass (BrowserPage) are not registered as views::
+
+  >>> view = getMultiAdapter((mammoth, request), name='browserDefault')
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<grok.tests.json.view_lookup.Mammoth object at ...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass zope.interface.Interface>, 'browserDefault')
+
+  >>> view = getMultiAdapter((mammoth, request), name='publishTraverse')
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<grok.tests.json.view_lookup.Mammoth object at ...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass zope.interface.Interface>, 'publishTraverse')
+
 """
 import grok
 
@@ -35,4 +72,9 @@
 
     def another(self):
         return { 'another': 'grok'}
-    
+
+class SecondMammothView(grok.JSON):
+    grok.context(Mammoth)
+
+    def _private(self):
+        return {'should': 'not be registered'}

Added: grok/branches/0.11/src/grok/tests/util/public_methods_from_class.py
===================================================================
--- grok/branches/0.11/src/grok/tests/util/public_methods_from_class.py	                        (rev 0)
+++ grok/branches/0.11/src/grok/tests/util/public_methods_from_class.py	2008-01-07 15:27:05 UTC (rev 82731)
@@ -0,0 +1,28 @@
+"""
+  >>> methods = grok.util.public_methods_from_class(A)
+  >>> sorted([m.__name__ for m in methods])
+  ['should_also_be_public', 'should_be_public']
+
+"""
+import grok
+import grok.util
+
+class A(object):
+
+    def __init__(self):
+        pass # this method is ignored
+
+    def __call__(self):
+        pass # this method is ignored
+
+    def __double_underscored(self):
+        pass # this method is ignored
+
+    def _single_underscored(self):
+        pass # this method is ignored
+
+    def should_be_public(self):
+        pass # this method is found
+
+    def should_also_be_public(self):
+        pass # this method is found

Modified: grok/branches/0.11/src/grok/util.py
===================================================================
--- grok/branches/0.11/src/grok/util.py	2008-01-07 15:20:52 UTC (rev 82730)
+++ grok/branches/0.11/src/grok/util.py	2008-01-07 15:27:05 UTC (rev 82731)
@@ -25,7 +25,7 @@
 from zope.security.interfaces import IPermission
 
 from martian.error import GrokError, GrokImportError
-from martian.util import class_annotation
+from martian.util import class_annotation, methods_from_class
 
 def check_adapts(class_):
     if component.adaptedBy(class_) is None:
@@ -105,3 +105,7 @@
     if directive is not None:
         return directive
     return default
+
+def public_methods_from_class(factory):
+    return [m for m in methods_from_class(factory) if \
+            not m.__name__.startswith('_')]



More information about the Checkins mailing list