Merge lp:~leonardr/lazr.restful/grok-configuration-2 into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Merged at revision: not available
Proposed branch: lp:~leonardr/lazr.restful/grok-configuration-2
Merge into: lp:lazr.restful
Diff against target: None lines
To merge this branch: bzr merge lp:~leonardr/lazr.restful/grok-configuration-2
Reviewer Review Type Date Requested Status
Gary Poster Approve
Review via email: mp+11131@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

This branch defines some new grokkers for registering utilities and adapters. It gets rid of the "manually call grokcore.component methods" technique in favor of the "subclass a class, even if the subclass is empty" technique.

Revision history for this message
Gary Poster (gary) wrote :

Looks good.

Please add the directives to the pertinent module's __all__.

I wonder if the base classes ought to be named clearly as "Abstract" or something else. Then I would have seen

    class RootAbsoluteURL(AbstractRootAbsoluteURL):

and

    class BelowRootAbsoluteURL(AbstractAbsoluteURL):

which I think would have been clearer for me. As I mentioned on IRC, if you disagree, I'll leave it alone. That's my inclination though.

Thank you

Gary

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/lazr/restful/directives/__init__.py'
2--- src/lazr/restful/directives/__init__.py 2009-09-02 19:36:14 +0000
3+++ src/lazr/restful/directives/__init__.py 2009-09-03 14:10:38 +0000
4@@ -9,27 +9,55 @@
5
6 import martian
7 from zope.component import getSiteManager, getUtility
8+from zope.location.interfaces import ILocation
9+from zope.traversing.browser import AbsoluteURL
10+from zope.traversing.browser.interfaces import IAbsoluteURL
11+
12 from lazr.restful.interfaces import (
13- IServiceRootResource, IWebServiceConfiguration)
14+ IServiceRootResource, IWebServiceConfiguration, IWebServiceLayer)
15+from lazr.restful import ServiceRootResource
16 from lazr.restful.simple import (
17- BaseWebServiceConfiguration, Publication, Request)
18+ BaseWebServiceConfiguration, Publication, Request,
19+ RootResourceAbsoluteURL)
20
21
22 class request_class(martian.Directive):
23- """Directive used to specify a service's request class."""
24+ """Directive used to specify a service's request class.
25+
26+ The default is lazr.restful.simple.Request.
27+ """
28 scope = martian.CLASS
29 store = martian.ONCE
30 default = Request
31
32
33 class publication_class(martian.Directive):
34- """Directive used to specify a service's publication class."""
35+ """Directive used to specify a service's publication class.
36+
37+ The default is lazr.restful.simple.Publication.
38+ """
39 scope = martian.CLASS
40 store = martian.ONCE
41 default = Publication
42
43
44 class ConfigurationGrokker(martian.ClassGrokker):
45+ """Subclass BaseWebServiceConfiguration for an easy configuration class.
46+
47+ Subclass BaseWebServiceConfiguration and override any of the
48+ configuration settings specific to your web service.
49+
50+ This grokker creates default implementations of createRequest()
51+ and get_request_user, if those methods are not implemented.
52+
53+ The default implementations use the request and publication
54+ classes you specify with the directives
55+ lazr.restful.directives.request_class() and
56+ lazr.restful.directives.publication_class().
57+
58+ This grokker then registers an instance of your subclass as the
59+ singleton configuration object.
60+ """
61 martian.component(BaseWebServiceConfiguration)
62 martian.directive(request_class)
63 martian.directive(publication_class)
64@@ -54,3 +82,36 @@
65 # Register as utility.
66 getSiteManager().registerUtility(cls(), IWebServiceConfiguration)
67 return True
68+
69+
70+class ServiceRootGrokker(martian.ClassGrokker):
71+ """Registers your service root as a singleton object."""
72+ martian.component(ServiceRootResource)
73+ def execute(self, cls, config, *kw):
74+ getSiteManager().registerUtility(cls(), IServiceRootResource)
75+ return True
76+
77+
78+class RootResourceAbsoluteURLGrokker(martian.ClassGrokker):
79+ """Registers a strategy for generating your service's base URL.
80+
81+ In most cases you can simply create an empty subclass of
82+ RootResourceAbsoluteURL.
83+ """
84+ martian.component(RootResourceAbsoluteURL)
85+ def execute(self, cls, config, *kw):
86+ getSiteManager().registerAdapter(cls)
87+ return True
88+
89+
90+class AbsoluteURLGrokker(martian.ClassGrokker):
91+ """Registers a strategy for generating an object's URL.
92+
93+ In most cases you can simply create an empty subclass of
94+ AbsoluteURL.
95+ """
96+ martian.component(AbsoluteURL)
97+ def execute(self, cls, config, *kw):
98+ getSiteManager().registerAdapter(
99+ cls, (ILocation, IWebServiceLayer), IAbsoluteURL)
100+ return True
101
102=== modified file 'src/lazr/restful/example/base/root.py'
103--- src/lazr/restful/example/base/root.py 2009-09-02 18:54:22 +0000
104+++ src/lazr/restful/example/base/root.py 2009-09-03 12:40:34 +0000
105@@ -350,15 +350,13 @@
106
107
108 # Define classes for the service root.
109-class CookbookServiceRootResource(ServiceRootResource,
110- grokcore.component.GlobalUtility):
111+class CookbookServiceRootResource(ServiceRootResource):
112 """A service root for the cookbook web service.
113
114 Traversal to top-level resources is handled with the get() method.
115 The top-level objects are stored in the top_level_names dict.
116 """
117 implements(IHasGet)
118- grokcore.component.provides(IServiceRootResource)
119
120 @property
121 def top_level_names(self):
122
123=== modified file 'src/lazr/restful/example/base/traversal.py'
124--- src/lazr/restful/example/base/traversal.py 2009-09-01 14:39:06 +0000
125+++ src/lazr/restful/example/base/traversal.py 2009-09-03 14:04:03 +0000
126@@ -4,7 +4,11 @@
127
128 __metaclass__ = type
129 __all__ = [
130- 'TraverseWithGet']
131+ 'BelowRootAbsoluteURL',
132+ 'CookbookSetTraverse',
133+ 'RootAbsoluteURL',
134+ 'TraverseWithGet',
135+ ]
136
137
138 from urllib import unquote
139@@ -13,21 +17,29 @@
140 from zope.publisher.interfaces import IPublishTraverse, NotFound
141 from zope.publisher.interfaces.browser import IDefaultBrowserLayer
142 from zope.traversing.browser import absoluteURL, AbsoluteURL
143-from zope.traversing.browser.interfaces import IAbsoluteURL
144
145 import grokcore.component
146
147 from lazr.restful.example.base.interfaces import ICookbookSet, IHasGet
148 from lazr.restful.example.base.root import CookbookWebServiceObject
149-from lazr.restful.interfaces import IWebServiceLayer
150 from lazr.restful.simple import RootResourceAbsoluteURL
151 from lazr.restful import RedirectResource
152
153
154-# Grok setup of classes defined elsewhere.
155-grokcore.component.global_adapter(RootResourceAbsoluteURL)
156-grokcore.component.global_adapter(
157- AbsoluteURL, (CookbookWebServiceObject, IWebServiceLayer), IAbsoluteURL)
158+class RootAbsoluteURL(RootResourceAbsoluteURL):
159+ """A technique for generating the service's root URL.
160+
161+ This class contains no code of its own. It's defined so that grok
162+ will pick it up.
163+ """
164+
165+
166+class BelowRootAbsoluteURL(AbsoluteURL):
167+ """A technique for generating a root URL given an ILocation.
168+
169+ This class contains no code of its own. It's defined so that
170+ grok will pick it up.
171+ """
172
173
174 class TraverseWithGet(grokcore.component.MultiAdapter):
175
176=== modified file 'src/lazr/restful/example/wsgi/root.py'
177--- src/lazr/restful/example/wsgi/root.py 2009-09-02 18:54:22 +0000
178+++ src/lazr/restful/example/wsgi/root.py 2009-09-03 14:04:03 +0000
179@@ -2,26 +2,34 @@
180
181 __metaclass__ = type
182 __all__ = [
183+ 'BelowRootAbsoluteURL',
184+ 'RootAbsoluteURL',
185 'WebServiceConfiguration',
186 'WSGIExampleWebServiceRootResource',
187 ]
188
189-import grokcore.component
190-from zope.location.interfaces import ILocation
191 from zope.traversing.browser import AbsoluteURL
192-from zope.traversing.browser.interfaces import IAbsoluteURL
193
194-from lazr.restful import directives
195 from lazr.restful.example.wsgi.resources import (
196 IKeyValuePair, PairSet, KeyValuePair)
197-from lazr.restful.interfaces import IWebServiceLayer
198 from lazr.restful.simple import (
199 BaseWebServiceConfiguration, RootResource, RootResourceAbsoluteURL)
200
201-# Grok setup of classes defined elsewhere.
202-grokcore.component.global_adapter(RootResourceAbsoluteURL)
203-grokcore.component.global_adapter(
204- AbsoluteURL, (ILocation, IWebServiceLayer), IAbsoluteURL)
205+
206+class RootAbsoluteURL(RootResourceAbsoluteURL):
207+ """A technique for generating the service's root URL.
208+
209+ This class contains no code of its own. It's defined so that
210+ grok will pick it up.
211+ """
212+
213+
214+class BelowRootAbsoluteURL(AbsoluteURL):
215+ """A technique for generating a root URL given an ILocation.
216+
217+ This class contains no code of its own. It's defined so that
218+ grok will pick it up.
219+ """
220
221
222 class WebServiceConfiguration(BaseWebServiceConfiguration):
223@@ -41,4 +49,4 @@
224 ]
225 collections = dict(pairs=(IKeyValuePair, pairset))
226 return collections, {}
227-grokcore.component.global_utility(WSGIExampleWebServiceRootResource)
228+

Subscribers

People subscribed via source and target branches