Merge lp:~leonardr/lazr.restful/integrate-strict-versioning into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Approved by: Данило Шеган
Approved revision: 190
Merged at revision: 185
Proposed branch: lp:~leonardr/lazr.restful/integrate-strict-versioning
Merge into: lp:lazr.restful
Diff against target: 229 lines (+36/-31)
8 files modified
setup.py (+1/-0)
src/lazr/restful/NEWS.txt (+8/-0)
src/lazr/restful/configure.zcml (+3/-0)
src/lazr/restful/declarations.py (+7/-9)
src/lazr/restful/metazcml.py (+14/-20)
src/lazr/restful/utils.py (+1/-1)
src/lazr/restful/version.txt (+1/-1)
versions.cfg (+1/-0)
To merge this branch: bzr merge lp:~leonardr/lazr.restful/integrate-strict-versioning
Reviewer Review Type Date Requested Status
Данило Шеган (community) Approve
Review via email: mp+54530@code.launchpad.net

Description of the change

This branch makes minor changes that were neccessary to integrate lazr.restful's 'strict versioning' feature into Launchpad.

* Instead of being run when register_webservice is called, webservice_sanity_checks() is run when Zope starts up. This was necessary because register_webservice can be called many times over the course of building a webservice, and when that happens the web service will not necessarily be self-consistent any of those times (except the last).

* Fixed a bad entry in utils.py __all__.

Also some minor cleanup:

* Use dict_for_name() in one place instead of reinventing the wheel.

To post a comment you must log in.
190. By Leonard Richardson

Removed another breakpoint.

Revision history for this message
Данило Шеган (danilo) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'setup.py'
2--- setup.py 2010-10-05 17:55:44 +0000
3+++ setup.py 2011-03-23 14:39:44 +0000
4@@ -74,6 +74,7 @@
5 'zope.event',
6 'zope.interface',
7 'zope.pagetemplate',
8+ 'zope.processlifetime',
9 'zope.proxy',
10 'zope.publisher',
11 'zope.schema',
12
13=== modified file 'src/lazr/restful/NEWS.txt'
14--- src/lazr/restful/NEWS.txt 2011-03-14 23:07:52 +0000
15+++ src/lazr/restful/NEWS.txt 2011-03-23 14:39:44 +0000
16@@ -2,6 +2,14 @@
17 NEWS for lazr.restful
18 =====================
19
20+0.18.0 (Unreleased)
21+===================
22+
23+If the configuration variable `require_explicit_versions` is set,
24+lazr.restful will not load up a web service unless every field, entry,
25+and named operation explicitly states which version of the web service
26+it first appears in.
27+
28 0.17.5 (2011-03-15)
29 ===================
30
31
32=== modified file 'src/lazr/restful/configure.zcml'
33--- src/lazr/restful/configure.zcml 2011-03-15 15:44:46 +0000
34+++ src/lazr/restful/configure.zcml 2011-03-23 14:39:44 +0000
35@@ -19,6 +19,9 @@
36 <allow interface='lazr.restful.interfaces.IJSONPublishable' />
37 </class>
38
39+ <subscriber for="zope.processlifetime.IProcessStarting"
40+ handler="lazr.restful.metazcml.webservice_sanity_checks" />
41+
42 <!--
43 XXX flacoste 2008/05/09 bug=185958:
44 Ideally, we would use webservice_error() to register the view,
45
46=== modified file 'src/lazr/restful/declarations.py'
47--- src/lazr/restful/declarations.py 2011-03-17 14:21:32 +0000
48+++ src/lazr/restful/declarations.py 2011-03-23 14:39:44 +0000
49@@ -1344,12 +1344,10 @@
50 if tag is None:
51 raise TypeError(
52 "'%s' isn't tagged for webservice export." % method.__name__)
53- match = [annotations for version_name, annotations in tag.stack
54- if version_name==version]
55- if len(match) == 0:
56+ match = tag.dict_for_name(version)
57+ if match is None:
58 raise AssertionError("'%s' isn't tagged for export to web service "
59 "version '%s'" % (method.__name__, version))
60- tag = match[0]
61 config = getUtility(IWebServiceConfiguration)
62 if version is None:
63 # This code path is not currently used except in a test, since
64@@ -1365,7 +1363,7 @@
65 'annotation stack.' % (method.__name__, version, version))
66
67 bases = (BaseResourceOperationAdapter, )
68- operation_type = tag['type']
69+ operation_type = match['type']
70 if operation_type == 'read_operation':
71 prefix = 'GET'
72 provides = IResourceGETOperation
73@@ -1380,16 +1378,16 @@
74 else:
75 raise AssertionError('Unknown method export type: %s' % operation_type)
76
77- return_type = tag['return_type']
78+ return_type = match['return_type']
79
80 name = _versioned_class_name(
81- '%s_%s_%s' % (prefix, method.interface.__name__, tag['as']),
82+ '%s_%s_%s' % (prefix, method.interface.__name__, match['as']),
83 version)
84 class_dict = {
85- 'params': tuple(tag['params'].values()),
86+ 'params': tuple(match['params'].values()),
87 'return_type': return_type,
88 '_orig_iface': method.interface,
89- '_export_info': tag,
90+ '_export_info': match,
91 '_method_name': method.__name__,
92 '__doc__': method.__doc__}
93
94
95=== modified file 'src/lazr/restful/metazcml.py'
96--- src/lazr/restful/metazcml.py 2011-03-18 15:31:53 +0000
97+++ src/lazr/restful/metazcml.py 2011-03-23 14:39:44 +0000
98@@ -10,6 +10,7 @@
99 import itertools
100
101 from zope.component import (
102+ adapter,
103 getGlobalSiteManager,
104 getUtility,
105 )
106@@ -17,6 +18,7 @@
107 from zope.configuration.fields import GlobalObject
108 from zope.interface import Interface
109 from zope.interface.interfaces import IInterface
110+from zope.processlifetime import IProcessStarting
111
112 from lazr.restful.declarations import (
113 COLLECTION_TYPE,
114@@ -47,6 +49,12 @@
115 from lazr.restful.utils import VersionedObject
116
117
118+# Keep track of entry and operation registrations so we can
119+# sanity-check them later.
120+REGISTERED_ENTRIES = []
121+REGISTERED_OPERATIONS = []
122+
123+
124 class IRegisterDirective(Interface):
125 """Directive to hook up webservice based on the declarations in a module.
126 """
127@@ -281,11 +289,6 @@
128 module, type(module))
129 interfaces_with_contributors = find_interfaces_and_contributors(module)
130
131- # Keep track of entry and operation registrations so we can
132- # sanity-check them later.
133- registered_entries = []
134- registered_operations = []
135-
136 for interface, contributors in interfaces_with_contributors.items():
137 if issubclass(interface, Exception):
138 register_exception_view(context, interface)
139@@ -297,7 +300,7 @@
140 discriminator=('webservice entry interface', interface),
141 callable=generate_and_register_entry_adapters,
142 args=(interface, context.info, contributors,
143- registered_entries),
144+ REGISTERED_ENTRIES),
145 )
146 elif tag['type'] == COLLECTION_TYPE:
147 for version in tag['collection_default_content'].keys():
148@@ -315,19 +318,11 @@
149 raise AssertionError('Unknown export type: %s' % tag['type'])
150 context.action(
151 discriminator=('webservice versioned operations', interface),
152- args=(context, interface, contributors, registered_operations),
153+ args=(context, interface, contributors, REGISTERED_OPERATIONS),
154 callable=generate_and_register_webservice_operations)
155
156- # Now that all the adapters and operations are registered, run a
157- # sanity check to make sure no version of the web service
158- # references a feature not available in that version
159- context.action(
160- discriminator=('webservice sanity checks'),
161- args=(registered_entries, registered_operations),
162- callable=webservice_sanity_checks)
163-
164-
165-def webservice_sanity_checks(entries, operations):
166+@adapter(IProcessStarting)
167+def webservice_sanity_checks(registration):
168 """Ensure the web service contains no references to unpublished objects.
169
170 We are worried about fields that link to unpublished objects, and
171@@ -336,7 +331,6 @@
172 it may not be published in the same version in which it's
173 referenced.
174 """
175-
176 # Create a mapping of marker interfaces to version names.
177 versions = getUtility(IWebServiceConfiguration).active_versions
178 version_for_marker = { IWebServiceClientRequest: versions[0] }
179@@ -362,7 +356,7 @@
180 # Check every Reference and CollectionField field in every IEntry
181 # interface, making sure that they only reference entries that are
182 # published in that version.
183- for version, interface in entries:
184+ for version, interface in REGISTERED_ENTRIES:
185 for name, field in interface.namesAndDescriptions():
186 referenced_interface, what = _extract_reference_type(field)
187 if referenced_interface is not None:
188@@ -376,7 +370,7 @@
189 # named operation published in that version, making sure that
190 # there are no references to IEntries not published in that
191 # version.
192- for version, method in operations:
193+ for version, method in REGISTERED_OPERATIONS:
194 tags = method.getTaggedValue(LAZR_WEBSERVICE_EXPORTED)
195 return_type = tags.get('return_type')
196 referenced_interface, what = _extract_reference_type(return_type)
197
198=== modified file 'src/lazr/restful/utils.py'
199--- src/lazr/restful/utils.py 2011-03-17 14:21:32 +0000
200+++ src/lazr/restful/utils.py 2011-03-23 14:39:44 +0000
201@@ -15,8 +15,8 @@
202 'smartquote',
203 'simple_popen2',
204 'tag_request_with_version_name',
205- 'VersionedAnnotations',
206 'VersionedDict',
207+ 'VersionedObject',
208 ]
209
210
211
212=== modified file 'src/lazr/restful/version.txt'
213--- src/lazr/restful/version.txt 2011-03-14 23:26:59 +0000
214+++ src/lazr/restful/version.txt 2011-03-23 14:39:44 +0000
215@@ -1,1 +1,1 @@
216-0.17.5
217+0.18.0
218
219=== modified file 'versions.cfg'
220--- versions.cfg 2010-10-05 15:55:18 +0000
221+++ versions.cfg 2011-03-23 14:39:44 +0000
222@@ -58,6 +58,7 @@
223 zope.lifecycleevent = 3.5.2
224 zope.location = 3.7.0
225 zope.pagetemplate = 3.5.0
226+zope.processlifetime = 1.0
227 zope.proxy = 3.5.0
228 zope.publisher = 3.12.0
229 zope.schema = 3.5.4

Subscribers

People subscribed via source and target branches