[Repoze-dev] Repoze CVS: publisher.py
Tres Seaver
tseaver at agendaless.com
Wed Sep 12 20:20:27 UTC 2007
Update of /home/repoze/cvs/repoze.obob/repoze/obob
In directory laguna.palladion.com:/tmp/cvs-serv16762/repoze/obob
Modified Files:
publisher.py
Log Message:
- Break multiple plugpoints out into a separate helper class, configured
through new 'helper_factory' plugpoing on ObobPublisher.
- Remove use of 'request' anywhere (the helper is responsible for all that).
- Move old default plugpoint implementations out into DefaultHelper class.
Index: publisher.py
===================================================================
RCS file: /home/repoze/cvs/repoze.obob/repoze/obob/publisher.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- publisher.py 12 Sep 2007 18:23:35 -0000 1.5
+++ publisher.py 12 Sep 2007 20:20:25 -0000 1.6
@@ -1,136 +1,105 @@
-PLUGPOINTS = ('request_factory',
- 'get_root',
- 'before_traverse',
- 'traverse',
- 'before_invoke',
- 'invoke',
- 'map_result',
- )
+""" repoze.obob publisher: perform policy-driven graph traversal.
+"""
-class ObobPublisher:
+class DefaultHelper:
+ """ Default traversal policy helper.
- def __init__(self,
- get_root=None,
- request_factory=None,
- before_traverse=None,
- traverse=None,
- before_invoke=None,
- invoke=None,
- map_result=None,
- dispatchable=None,
- extras=None,
- ):
+ Simple applications may just use this class directly. More complex
+ apps can either subclass it, or else supply a different 'helper_factory'
+ to the ObobPublisher constructor, implementing all the same methods
+ on the returned object.
+ """
+ def __init__(self, environ):
+ self.environ = environ
- if dispatchable is None:
- dispatchable = {}
+ def path_elements(self):
+ return [x for x in self.environ['PATH_INFO'].split('/') if x.strip()]
- if extras is None:
- extras = {}
+ def before_traverse(self, current, name):
+ pass
- self._default_root = _DefaultRoot(dispatchable)
- self.extras = extras
+ def traverse(self, current, name):
+ return current[name]
- if get_root is not None:
- if not callable(get_root):
- raise ValueError("'get_root' not callable!")
+ def before_invoke(self, published):
+ pass
- self.get_root = get_root
+ def invoke(self, published):
+ return published()
- if request_factory is not None:
- if not callable(request_factory):
- raise ValueError("'request_factory' not callable!")
- self.request_factory = request_factory
+ def map_result(self, result):
+ if isinstance(result, basestring):
+ result = [result]
+ return '200 OK', {}, result
- if before_traverse is not None:
- if not callable(before_traverse):
- raise ValueError("'before_traverse' not callable!")
- self.before_traverse = before_traverse
- if traverse is not None:
- if not callable(traverse):
- raise ValueError("'traverse' not callable!")
- self.traverse = traverse
+class ObobPublisher:
+ """
+ """
+ def __init__(self,
+ get_root=None,
+ helper_factory=None,
+ dispatchable=None,
+ extras=None,
+ ):
- if before_invoke is not None:
- if not callable(before_invoke):
- raise ValueError("'before_invoke' not callable!")
- self.before_invoke = before_invoke
+ if get_root is not None:
+ self.get_root = get_root
+ else:
+ if dispatchable is None:
+ dispatchable = {}
+ self._default_root = _DefaultRoot(dispatchable)
- if invoke is not None:
- if not callable(invoke):
- raise ValueError("'invoke' not callable!")
- self.invoke = invoke
+ if helper_factory is not None:
+ self.helper_factory = helper_factory
- if map_result is not None:
- if not callable(map_result):
- raise ValueError("'map_result' not callable!")
- self.map_result = map_result
+ if extras is None:
+ extras = {}
+
+ self.extras = extras
def __call__(self, environ, start_response):
""" Application dispatch via graph traversal.
-
- 1. Convert WSGI environ into a request object.
- 2. Get traversal root via self.get_root().
+ 1. Get traversal root via self.get_root().
- 3. Iterate over items in request's path:
+ 2. Iterate over items in request's path:
a. Notify 'self.before_traverse' if not None.
b. Get next object via 'self.traverse'.
- 4. Notify 'self.before_invoke', if not None.
+ 3. Notify 'self.before_invoke', if not None.
- 5. Call the terminal ("published") object, applying request
+ 4. Call the terminal ("published") object, applying request
parameters.
- 6. Map result + request onto WSGI 'start_response' + iteration.
+ 5. Map result onto WSGI 'start_response' + iteration.
"""
- request = self.request_factory(environ)
- root = current = self.get_root(request)
+ helper = self.helper_factory(environ)
+ root = current = self.get_root(environ)
- elements = request['PATH_INFO'].split('/') # XXX, contract?
- for name in elements:
- if name.strip() == '':
- continue
- self.before_traverse(current, name, request)
- current = self.traverse(current, name)
+ for name in helper.path_elements():
+ helper.before_traverse(current, name)
+ current = helper.traverse(current, name)
- published = request['PUBLISHED'] = current # XXX, contract?
+ published = current
- self.before_invoke(published, request)
- result = self.invoke(published, request)
+ helper.before_invoke(published)
+ result = helper.invoke(published)
- status, headers, body_iter = self.map_result(request, result)
+ status, headers, body_iter = helper.map_result(result)
start_response(status, headers)
for chunk in body_iter:
yield chunk
- # Default implementations for plug points.
- def request_factory(self, environ):
- return environ
-
- def get_root(self, request):
+ def get_root(self, environ):
return self._default_root
- def before_traverse(self, current, name, request):
- pass
-
- def traverse(self, current, name):
- return current[name]
-
- def before_invoke(self, published, request):
- pass
-
- def invoke(self, published, request):
- return published()
-
- def map_result(self, request, result):
- if isinstance(result, basestring):
- result = [result]
- return '200 OK', {}, result
+ def helper_factory(self, environ):
+ return DefaultHelper(environ)
class _DefaultRoot:
@@ -158,6 +127,11 @@
])
return lines
+
+_PLUGPOINTS = ('get_root',
+ 'helper_factory',
+ )
+
def _resolve(dotted_or_ep):
from pkg_resources import EntryPoint
return EntryPoint.parse('x=%s' % dotted_or_ep).load(False)
@@ -171,7 +145,7 @@
if k.startswith(PREFIX):
trimmed = k[len(PREFIX):]
callable = _resolve(v)
- if trimmed in PLUGPOINTS:
+ if trimmed in _PLUGPOINTS:
new_kw[trimmed] = callable
else:
dispatchable[trimmed] = callable
_______________________________________________
Repoze-dev mailing list
Repoze-dev at lists.repoze.org
http://lists.repoze.org/mailman/listinfo/repoze-dev
More information about the Repoze-dev
mailing list