summaryrefslogtreecommitdiff
path: root/repoze/bfg/zcml.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-10-21 21:48:19 +0000
committerChris McDonough <chrism@agendaless.com>2009-10-21 21:48:19 +0000
commitb2f9291bfb55f9305f59b8ba0e3fe04ff6f31cc6 (patch)
tree5afe13809e933cc16ea5e2cca7908a0b6c0caab2 /repoze/bfg/zcml.py
parentb06b260b83bfc2f40105c6e730f5e7e8eccd61d9 (diff)
downloadpyramid-b2f9291bfb55f9305f59b8ba0e3fe04ff6f31cc6.tar.gz
pyramid-b2f9291bfb55f9305f59b8ba0e3fe04ff6f31cc6.tar.bz2
pyramid-b2f9291bfb55f9305f59b8ba0e3fe04ff6f31cc6.zip
- Change how ``bfg_view`` decorator works when used as a class method
decorator. In 1.1a7, it actually tried to grope every class in scanned package at startup time looking for methods, which led to some strange symptoms (e.g. ``AttributeError: object has no attribute __provides__``). Now, instead of groping methods at startup time, we just cause the ``bfg_view`` decorator itself to populate its class' __dict__ when its used inside a class as a method decorator. This is essentially a reversion back to 1.1a6 "grokking" behavior plus some special magic for using the ``bfg_view`` decorator as method decorator inside the ``bfg_view`` class itself.
Diffstat (limited to 'repoze/bfg/zcml.py')
-rw-r--r--repoze/bfg/zcml.py59
1 files changed, 4 insertions, 55 deletions
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 6bf180b3a..84b1243d1 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -1,8 +1,6 @@
-import inspect
import re
import sys
-from zope.interface import implements
from zope.component import getSiteManager
from zope.component import getUtility
from zope.component import queryUtility
@@ -19,7 +17,6 @@ from zope.schema import Int
from zope.schema import TextLine
import martian
-import martian.interfaces # pyflakes whines, but don't delete it
from repoze.bfg.interfaces import IAuthenticationPolicy
from repoze.bfg.interfaces import IAuthorizationPolicy
@@ -678,56 +675,23 @@ def scan(_context, package, martian=martian):
# martian overrideable only for unit tests
multi_grokker = BFGMultiGrokker()
multi_grokker.register(BFGViewGrokker())
- multi_grokker.register(BFGClassGrokker())
module_grokker = martian.ModuleGrokker(grokker=multi_grokker)
martian.grok_dotted_name(package.__name__, grokker=module_grokker,
context=_context, exclude_filter=exclude)
################# utility stuff ####################
-class Class(object):
- pass
-
-class AnythingButAClass(object):
+class BFGViewMarker(object):
pass
class BFGMultiGrokker(martian.core.MultiInstanceOrClassGrokkerBase):
def get_bases(self, obj):
- if inspect.isclass(obj):
- return [Class]
- elif hasattr(obj, '__bfg_view_settings__'):
- return [AnythingButAClass]
+ if hasattr(obj, '__bfg_view_settings__'):
+ return [BFGViewMarker]
return []
-class BFGClassGrokker(object):
- implements(martian.interfaces.IGrokker)
- martian.component(Class)
- def grok(self, name, class_, module_info=None, **kw):
- # The class itself may be decorated, so we feed it to BFGViewGrokker
- found = BFGViewGrokker().grok(name, class_, **kw)
-
- # grok any decorations attached to the class' method (direct
- # methods only, not methods of any base class); we can't use
- # inspect.getmembers here because it doesn't deal with a
- # corner case where objects that inherit from Persistent
- # advertises a '__provides__' as per dir(ob) but getattr(ob,
- # '__provides__') raises an AttributeError. Unknown why this
- # happens, but it doesn't matter: need to deal with it.
- methods = getmembers(class_, inspect.ismethod)
- classmethods = class_.__dict__.keys()
- for method_name, method in methods:
- if method_name in classmethods:
- # it's not an inherited method
- config = getattr(method, '__bfg_view_settings__', [])
- for settings in config:
- settings = dict(settings)
- settings['attr'] = settings['attr'] or method_name
- view(kw['context'], view=class_, **settings)
- found = True
- return found
-
class BFGViewGrokker(martian.InstanceGrokker):
- martian.component(AnythingButAClass)
+ martian.component(BFGViewMarker)
def grok(self, name, obj, **kw):
config = getattr(obj, '__bfg_view_settings__', [])
for settings in config:
@@ -745,18 +709,3 @@ class Uncacheable(object):
file_configure = zcml_configure # backwards compat (>0.8.1)
-def getmembers(object, predicate=None):
- """Return all members of an object as (name, value) pairs sorted
- by name. Optionally, only return members that satisfy a given
- predicate. Differs from inspect.getmembers inasmuch as it ignores
- AttributeErrors."""
- results = []
- for key in dir(object):
- try:
- value = getattr(object, key)
- except AttributeError:
- continue
- if not predicate or predicate(value):
- results.append((key, value))
- results.sort()
- return results