Merge lp:~leonardr/lazr.restful/active-versions into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Approved by: Aaron Bentley
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~leonardr/lazr.restful/active-versions
Merge into: lp:lazr.restful
Diff against target: 583 lines (+287/-62)
18 files modified
src/lazr/restful/NEWS.txt (+10/-0)
src/lazr/restful/docs/absoluteurl.txt (+7/-7)
src/lazr/restful/docs/django.txt (+2/-2)
src/lazr/restful/docs/webservice-declarations.txt (+1/-1)
src/lazr/restful/docs/webservice-request.txt (+1/-1)
src/lazr/restful/docs/webservice.txt (+1/-1)
src/lazr/restful/example/base/root.py (+1/-1)
src/lazr/restful/example/base/tests/service.txt (+12/-31)
src/lazr/restful/example/multiversion/README.txt (+6/-0)
src/lazr/restful/example/multiversion/resources.py (+35/-0)
src/lazr/restful/example/multiversion/root.py (+53/-0)
src/lazr/restful/example/multiversion/site.zcml (+13/-0)
src/lazr/restful/example/multiversion/tests/introduction.txt (+64/-0)
src/lazr/restful/example/multiversion/tests/test_integration.py (+53/-0)
src/lazr/restful/example/wsgi/root.py (+1/-1)
src/lazr/restful/interfaces/_rest.py (+14/-10)
src/lazr/restful/publisher.py (+12/-6)
src/lazr/restful/testing/webservice.py (+1/-1)
To merge this branch: bzr merge lp:~leonardr/lazr.restful/active-versions
Reviewer Review Type Date Requested Status
Aaron Bentley (community) code Approve
Review via email: mp+14912@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

This branch makes two major changes:

1. It introduces a new web service specifically for testing the multiversion code. This is pretty much a full copy of the WSGI test service, though I was able to import a few classes from the WSGI test service rather than re-defining them. (Many classes, even empty ones, had to be re-defined so that grok would handle them properly.)

Most of the multiversion tests in examples/base/tests/service.txt have been moved to examples/multiversion/tests/introduction.txt

2. It replaces the string service_version_uri_prefix (this is "beta" in the Launchpad web service) with a list of active_versions (this would be ["beta"] in the Launchpad web service). A request to any of the versions in active_versions will succeed, and although all versions still serve the exact same resources, the URLs to those resources will change depending on the version number.

Revision history for this message
Aaron Bentley (abentley) wrote :

Looks fine.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/lazr/restful/NEWS.txt'
2--- src/lazr/restful/NEWS.txt 2009-11-12 16:30:50 +0000
3+++ src/lazr/restful/NEWS.txt 2009-11-16 15:00:27 +0000
4@@ -5,6 +5,10 @@
5 Development
6 ===========
7
8+Special note: this version contains backwards-incompatible
9+changes. You *must* change your configuration object to get your code
10+to work in this version! See "active_versions" below.
11+
12 Added the precursor of a versioning system for web services. Clients
13 can now request the "trunk" of a web service as well as one published
14 version. Apart from the URIs served, the two web services are exactly
15@@ -16,6 +20,12 @@
16 BaseWebServiceConfiguration or one of its subclasses, you'll need to
17 set a value for this.
18
19+This release _replaces_ one of the fields in
20+IWebServiceConfiguration. The string service_version_uri_prefix has
21+become the list active_versions. The simplest way to deal with this is
22+to just put your service_version_uri_prefix into a list and call it
23+active_versions.
24+
25 0.9.17 (2009-11-10)
26 ===================
27
28
29=== modified file 'src/lazr/restful/docs/absoluteurl.txt'
30--- src/lazr/restful/docs/absoluteurl.txt 2009-11-12 17:03:06 +0000
31+++ src/lazr/restful/docs/absoluteurl.txt 2009-11-16 15:00:27 +0000
32@@ -29,7 +29,7 @@
33 ... implements(IWebServiceConfiguration)
34 ... hostname = "hostname"
35 ... service_root_uri_prefix = "root_uri_prefix/"
36- ... service_version_uri_prefix = "service_version_uri_prefix"
37+ ... active_versions = ['active_version']
38 ... latest_version_uri_prefix = "latest_version_uri_prefix"
39 ... port = 1000
40 ... use_https = True
41@@ -50,20 +50,20 @@
42 >>> resource = RootResource()
43 >>> request = Request("", {})
44 >>> request.annotations[request.VERSION_ANNOTATION] = (
45- ... 'service_version_uri_prefix')
46+ ... 'active_version')
47 >>> adapter = getMultiAdapter((resource, request), IAbsoluteURL)
48
49 Calling the RootResourceAbsoluteURL will give the service root's
50 absolute URL.
51
52 >>> print adapter()
53- https://hostname:1000/root_uri_prefix/service_version_uri_prefix/
54+ https://hostname:1000/root_uri_prefix/active_version/
55
56 Converting the adapter to a string will give the same result, but
57 without the trailing slash.
58
59 >>> print str(adapter)
60- https://hostname:1000/root_uri_prefix/service_version_uri_prefix
61+ https://hostname:1000/root_uri_prefix/active_version
62
63 (This is useful for the recursive case. When finding the URL to a
64 subordinate resource, Zope's AbsoluteURL implementation calls str() on
65@@ -75,11 +75,11 @@
66
67 >>> configuration.use_https = False
68 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
69- http://hostname:1000/root_uri_prefix/service_version_uri_prefix/
70+ http://hostname:1000/root_uri_prefix/active_version/
71
72 >>> configuration.port = None
73 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
74- http://hostname/root_uri_prefix/service_version_uri_prefix/
75+ http://hostname/root_uri_prefix/active_version/
76
77 The URL generated includes a version identifier taken from the
78 value of the 'lazr.restful.version' annotation.
79@@ -106,7 +106,7 @@
80 Cleanup.
81
82 >>> request.annotations[request.VERSION_ANNOTATION] = (
83- ... 'service_version_uri_prefix')
84+ ... 'active_version')
85
86
87 MultiplePathPartAbsoluteURL
88
89=== modified file 'src/lazr/restful/docs/django.txt'
90--- src/lazr/restful/docs/django.txt 2009-09-08 13:33:01 +0000
91+++ src/lazr/restful/docs/django.txt 2009-11-16 15:00:27 +0000
92@@ -110,8 +110,8 @@
93 Attributes that don't have values in settings.py are given their
94 default value.
95
96- >>> utility.service_version_uri_prefix
97- u''
98+ >>> utility.active_versions
99+ []
100 >>> utility.use_https
101 True
102
103
104=== modified file 'src/lazr/restful/docs/webservice-declarations.txt'
105--- src/lazr/restful/docs/webservice-declarations.txt 2009-06-08 20:03:55 +0000
106+++ src/lazr/restful/docs/webservice-declarations.txt 2009-11-16 15:00:27 +0000
107@@ -953,7 +953,7 @@
108 >>> class MyWebServiceConfiguration:
109 ... implements(IWebServiceConfiguration)
110 ... view_permission = "lazr.View"
111- ... service_version_uri_prefix = "beta"
112+ ... active_versions = ["beta"]
113 ... code_revision = "1.0b"
114 ... default_batch_size = 50
115 ...
116
117=== modified file 'src/lazr/restful/docs/webservice-request.txt'
118--- src/lazr/restful/docs/webservice-request.txt 2009-08-11 18:36:20 +0000
119+++ src/lazr/restful/docs/webservice-request.txt 2009-11-16 15:00:27 +0000
120@@ -22,7 +22,7 @@
121 >>> class SimpleWebServiceConfiguration:
122 ... implements(IWebServiceConfiguration)
123 ... path_override = 'api'
124- ... service_version_uri_prefix = 'beta'
125+ ... active_versions = ['beta']
126 ...
127 ... def createRequest(self, body_stream, environ):
128 ... request = Request(body_stream, environ)
129
130=== modified file 'src/lazr/restful/docs/webservice.txt'
131--- src/lazr/restful/docs/webservice.txt 2009-11-12 16:30:50 +0000
132+++ src/lazr/restful/docs/webservice.txt 2009-11-16 15:00:27 +0000
133@@ -517,7 +517,7 @@
134
135 >>> class WebServiceConfiguration(BaseWebServiceConfiguration):
136 ... use_https = False
137- ... service_version_uri_prefix = 'beta'
138+ ... active_versions = ['beta']
139 ... latest_version_uri_prefix = 'devel'
140 ... code_revision = 'test'
141 ... max_batch_size = 100
142
143=== modified file 'src/lazr/restful/example/base/root.py'
144--- src/lazr/restful/example/base/root.py 2009-11-12 16:43:57 +0000
145+++ src/lazr/restful/example/base/root.py 2009-11-16 15:00:27 +0000
146@@ -387,7 +387,7 @@
147 default_batch_size=5
148 hostname='cookbooks.dev'
149 match_batch_size=50
150- service_version_uri_prefix='1.0'
151+ active_versions=['1.0']
152 use_https=False
153 view_permission='lazr.restful.example.base.View'
154
155
156=== modified file 'src/lazr/restful/example/base/tests/service.txt'
157--- src/lazr/restful/example/base/tests/service.txt 2009-11-12 16:35:38 +0000
158+++ src/lazr/restful/example/base/tests/service.txt 2009-11-16 15:00:27 +0000
159@@ -10,37 +10,18 @@
160 Versioning
161 ==========
162
163-In addition to the published version of the web service, lazr.restful
164-publishes a "development" version which may contain backwards
165-incompatible changes. The default name of the development version is
166-"devel".
167-
168- >>> body = webservice.get('/', api_version="devel").jsonBody()
169-
170-The development version serves URLs that reflect its version name.
171-
172- >>> print body['recipes_collection_link']
173- http://cookbooks.dev/devel/recipes
174- >>> print body['resource_type_link']
175- http://cookbooks.dev/devel/#service-root
176-
177-Currently there is no way to publish multiple versions of the web
178-service, so apart from the URLs, the development version is exactly
179-the same as the only published version.
180-
181-All versions of the web service can be accessed through Ajax.
182-
183- >>> from lazr.restful.testing.webservice import WebServiceAjaxCaller
184- >>> ajax = WebServiceAjaxCaller(domain='cookbooks.dev')
185- >>> body = ajax.get('/', api_version="devel").jsonBody()
186- >>> print body['resource_type_link']
187- http://cookbooks.dev/devel/#service-root
188-
189-An attempt to access a nonexistent version yields a 404 error.
190-
191- >>> print webservice.get('/', api_version="no_such_version")
192- HTTP/1.1 404 Not Found
193- ...
194+lazr.restful allows you to publish multiple named versions of a web
195+service, as well as a "development" version which includes changes you
196+have yet to batch together into a named version. The default name of
197+the development version is "devel".
198+
199+ >>> top_level_response = webservice.get(
200+ ... "/", api_version="devel").jsonBody()
201+ >>> print top_level_response['resource_type_link']
202+ http://cookbooks.dev/devel/#service-root
203+
204+The web service in examples/multiversion is devoted solely to testing
205+the versioning code.
206
207 Nonexistent resources
208 =====================
209
210=== added directory 'src/lazr/restful/example/multiversion'
211=== added file 'src/lazr/restful/example/multiversion/README.txt'
212--- src/lazr/restful/example/multiversion/README.txt 1970-01-01 00:00:00 +0000
213+++ src/lazr/restful/example/multiversion/README.txt 2009-11-16 15:00:27 +0000
214@@ -0,0 +1,6 @@
215+Multiversion web service
216+************************
217+
218+This web service demonstrates lazr.restful's ability to serve multiple
219+backwards-incompatible versions of a web service from the same
220+underlying code.
221
222=== added file 'src/lazr/restful/example/multiversion/__init__.py'
223=== added file 'src/lazr/restful/example/multiversion/resources.py'
224--- src/lazr/restful/example/multiversion/resources.py 1970-01-01 00:00:00 +0000
225+++ src/lazr/restful/example/multiversion/resources.py 2009-11-16 15:00:27 +0000
226@@ -0,0 +1,35 @@
227+__metaclass__ = type
228+
229+__all__ = ['IKeyValuePair',
230+ 'IPairSet',
231+ 'KeyValuePair',
232+ 'PairSet']
233+
234+from zope.schema import Text
235+from zope.location.interfaces import ILocation
236+
237+from lazr.restful.declarations import (
238+ collection_default_content, export_as_webservice_collection,
239+ export_as_webservice_entry, exported)
240+
241+# We don't need separate implementations of these classes, so borrow
242+# the implementations from the WSGI example.
243+from lazr.restful.example.wsgi.resources import PairSet, KeyValuePair
244+
245+# Our interfaces _will_ diverge from the WSGI example interfaces, so
246+# define them separately.
247+class IKeyValuePair(ILocation):
248+ export_as_webservice_entry()
249+ key = exported(Text(title=u"The key"))
250+ value = exported(Text(title=u"The value"))
251+
252+
253+class IPairSet(ILocation):
254+ export_as_webservice_collection(IKeyValuePair)
255+
256+ @collection_default_content()
257+ def getPairs():
258+ """Return the key-value pairs."""
259+
260+ def get(request, name):
261+ """Retrieve a key-value pair by its key."""
262
263=== added file 'src/lazr/restful/example/multiversion/root.py'
264--- src/lazr/restful/example/multiversion/root.py 1970-01-01 00:00:00 +0000
265+++ src/lazr/restful/example/multiversion/root.py 2009-11-16 15:00:27 +0000
266@@ -0,0 +1,53 @@
267+"""The RESTful service root."""
268+
269+__metaclass__ = type
270+__all__ = [
271+ 'BelowRootAbsoluteURL',
272+ 'RootAbsoluteURL',
273+ 'WebServiceConfiguration',
274+ 'MultiversionWebServiceRootResource',
275+ ]
276+
277+from zope.traversing.browser import AbsoluteURL
278+
279+from lazr.restful.wsgi import BaseWSGIWebServiceConfiguration
280+from lazr.restful.simple import RootResource, RootResourceAbsoluteURL
281+from lazr.restful.example.multiversion.resources import (
282+ IKeyValuePair, PairSet, KeyValuePair)
283+
284+
285+class RootAbsoluteURL(RootResourceAbsoluteURL):
286+ """A technique for generating the service's root URL.
287+
288+ This class contains no code of its own. It's defined so that
289+ grok will pick it up.
290+ """
291+
292+
293+class BelowRootAbsoluteURL(AbsoluteURL):
294+ """A technique for generating a root URL given an ILocation.
295+
296+ This class contains no code of its own. It's defined so that
297+ grok will pick it up.
298+ """
299+
300+
301+class WebServiceConfiguration(BaseWSGIWebServiceConfiguration):
302+ code_revision = '1'
303+ active_versions = ['beta', '1.0', '2.0']
304+ latest_version_uri_prefix = 'trunk'
305+ use_https = False
306+ view_permission = 'zope.Public'
307+
308+
309+class MultiversionWebServiceRootResource(RootResource):
310+ """The root resource for the WSGI example web service."""
311+ def _build_top_level_objects(self):
312+ pairset = PairSet()
313+ pairset.pairs = [
314+ KeyValuePair(self, "foo", "bar"),
315+ KeyValuePair(self, "1", "2")
316+ ]
317+ collections = dict(pairs=(IKeyValuePair, pairset))
318+ return collections, {}
319+
320
321=== added file 'src/lazr/restful/example/multiversion/site.zcml'
322--- src/lazr/restful/example/multiversion/site.zcml 1970-01-01 00:00:00 +0000
323+++ src/lazr/restful/example/multiversion/site.zcml 2009-11-16 15:00:27 +0000
324@@ -0,0 +1,13 @@
325+<configure
326+ xmlns="http://namespaces.zope.org/zope"
327+ xmlns:webservice="http://namespaces.canonical.com/webservice"
328+ xmlns:grok="http://namespaces.zope.org/grok">
329+
330+ <include package="lazr.restful" file="basic-site.zcml" />
331+ <webservice:register
332+ module="lazr.restful.example.multiversion.resources" />
333+ <grok:grok package="lazr.restful.example.multiversion" />
334+
335+ <securityPolicy
336+ component="zope.security.simplepolicies.PermissiveSecurityPolicy" />
337+</configure>
338
339=== added directory 'src/lazr/restful/example/multiversion/tests'
340=== added file 'src/lazr/restful/example/multiversion/tests/__init__.py'
341=== added file 'src/lazr/restful/example/multiversion/tests/introduction.txt'
342--- src/lazr/restful/example/multiversion/tests/introduction.txt 1970-01-01 00:00:00 +0000
343+++ src/lazr/restful/example/multiversion/tests/introduction.txt 2009-11-16 15:00:27 +0000
344@@ -0,0 +1,64 @@
345+Multi-version web services
346+**************************
347+
348+lazr.restful lets you publish two or more mutually incompatible
349+web services from the same underlying code. This lets you improve your
350+web service to take advantage of new features of lazr.restful, without
351+sacrificing backwards compatibility.
352+
353+The web service in example/multiversion illustrates the multiversion
354+features of lazr.restful.
355+
356+ >>> from lazr.restful.testing.webservice import WebServiceCaller
357+ >>> webservice = WebServiceCaller(domain='multiversion.dev')
358+
359+The multiversion web service serves three named versions of the same
360+web service: "beta", "1.0", and "2.0". Once you make a request to the
361+service root of a particular version, the web service only serves you
362+links within that version.
363+
364+ >>> top_level_response = webservice.get(
365+ ... "/", api_version="beta").jsonBody()
366+ >>> print top_level_response['key_value_pairs_collection_link']
367+ http://multiversion.dev/beta/pairs
368+
369+ >>> top_level_response = webservice.get(
370+ ... "/", api_version="1.0").jsonBody()
371+ >>> print top_level_response['key_value_pairs_collection_link']
372+ http://multiversion.dev/1.0/pairs
373+
374+ >>> top_level_response = webservice.get(
375+ ... "/", api_version="2.0").jsonBody()
376+ >>> print top_level_response['key_value_pairs_collection_link']
377+ http://multiversion.dev/2.0/pairs
378+
379+Like all web services, the multiversion service also serves a
380+development version which tracks the current state of the web service,
381+including all changes that have not yet been folded into a named
382+version. The default name for the development version is "devel" (see
383+example/base/tests/service.txt), but in this web service it's called
384+"trunk".
385+
386+ >>> top_level_response = webservice.get(
387+ ... "/", api_version="trunk").jsonBody()
388+ >>> print top_level_response['key_value_pairs_collection_link']
389+ http://multiversion.dev/trunk/pairs
390+
391+All versions of the web service can be accessed through Ajax.
392+
393+ >>> from lazr.restful.testing.webservice import WebServiceAjaxCaller
394+ >>> ajax = WebServiceAjaxCaller(domain='multiversion.dev')
395+
396+ >>> body = ajax.get('/', api_version="1.0").jsonBody()
397+ >>> print body['resource_type_link']
398+ http://multiversion.dev/1.0/#service-root
399+
400+ >>> body = ajax.get('/', api_version="trunk").jsonBody()
401+ >>> print body['resource_type_link']
402+ http://multiversion.dev/trunk/#service-root
403+
404+An attempt to access a nonexistent version yields a 404 error.
405+
406+ >>> print webservice.get('/', api_version="no_such_version")
407+ HTTP/1.1 404 Not Found
408+ ...
409
410=== added file 'src/lazr/restful/example/multiversion/tests/test_integration.py'
411--- src/lazr/restful/example/multiversion/tests/test_integration.py 1970-01-01 00:00:00 +0000
412+++ src/lazr/restful/example/multiversion/tests/test_integration.py 2009-11-16 15:00:27 +0000
413@@ -0,0 +1,53 @@
414+# Copyright 2008 Canonical Ltd. All rights reserved.
415+
416+"""Test harness for doctests for lazr.restful multiversion example service."""
417+
418+__metaclass__ = type
419+__all__ = []
420+
421+import os
422+import doctest
423+from pkg_resources import resource_filename
424+
425+from zope.component import getUtility
426+from van.testing.layer import zcml_layer, wsgi_intercept_layer
427+
428+from lazr.restful.example.multiversion.root import (
429+ MultiversionWebServiceRootResource)
430+from lazr.restful.interfaces import IWebServiceConfiguration
431+from lazr.restful.simple import Publication
432+from lazr.restful.testing.webservice import WebServiceApplication
433+
434+
435+DOCTEST_FLAGS = (
436+ doctest.ELLIPSIS |
437+ doctest.NORMALIZE_WHITESPACE |
438+ doctest.REPORT_NDIFF)
439+
440+
441+class FunctionalLayer:
442+ zcml = os.path.abspath(resource_filename(
443+ 'lazr.restful.example.multiversion', 'site.zcml'))
444+zcml_layer(FunctionalLayer)
445+
446+
447+class WSGILayer(FunctionalLayer):
448+
449+ @classmethod
450+ def make_application(self):
451+ getUtility(IWebServiceConfiguration).hostname = "multiversion.dev"
452+ getUtility(IWebServiceConfiguration).port = None
453+ root = MultiversionWebServiceRootResource()
454+ return WebServiceApplication(root, Publication)
455+wsgi_intercept_layer(WSGILayer)
456+
457+
458+def additional_tests():
459+ """See `zope.testing.testrunner`."""
460+ tests = sorted(
461+ [name
462+ for name in os.listdir(os.path.dirname(__file__))
463+ if name.endswith('.txt')])
464+ suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *tests)
465+ suite.layer = WSGILayer
466+ return suite
467
468=== modified file 'src/lazr/restful/example/wsgi/root.py'
469--- src/lazr/restful/example/wsgi/root.py 2009-11-12 16:43:57 +0000
470+++ src/lazr/restful/example/wsgi/root.py 2009-11-16 15:00:27 +0000
471@@ -34,7 +34,7 @@
472
473 class WebServiceConfiguration(BaseWSGIWebServiceConfiguration):
474 code_revision = '1'
475- service_version_uri_prefix = '1.0'
476+ active_versions = ['1.0']
477 use_https = False
478 view_permission = 'zope.Public'
479
480
481=== modified file 'src/lazr/restful/interfaces/_rest.py'
482--- src/lazr/restful/interfaces/_rest.py 2009-11-12 16:43:57 +0000
483+++ src/lazr/restful/interfaces/_rest.py 2009-11-16 15:00:27 +0000
484@@ -51,7 +51,7 @@
485 'IWebServiceLayer',
486 ]
487
488-from zope.schema import Bool, Int, TextLine
489+from zope.schema import Bool, Int, List, TextLine
490 from zope.interface import Attribute, Interface
491 # These two should really be imported from zope.interface, but
492 # the import fascist complains because they are not in __all__ there.
493@@ -417,15 +417,19 @@
494 "put the URL prefix here. (In the example case, the URL prefix "
495 "is 'web-service/').")
496
497- service_version_uri_prefix = TextLine(
498- default=u"",
499- description=u"""The versioning string, if any, to use as the
500- URI prefix for web service URIs. A popular string is 'beta',
501- but you could also use a version number or the date the API
502- was finalized.
503-
504- The service version URI prefix shows up in URIs *after* any
505- value for service_root_uri_prefix.""")
506+ active_versions = List(
507+ value_type=TextLine(),
508+ default = [],
509+ title=u"The active versions of the web service.",
510+ description = u"""A list of names of active versions of this
511+ web service. They might be version numbers, names such as
512+ "beta", or the date a particular version was finalized.
513+
514+ Newer versions should show up later in the list than earlier
515+ versions. The most recent active version should be at the end
516+ of the list.
517+
518+ Currently this list must contain at least one version name.""")
519
520 latest_version_uri_prefix = TextLine(
521 default=u"devel",
522
523=== modified file 'src/lazr/restful/publisher.py'
524--- src/lazr/restful/publisher.py 2009-11-12 17:03:06 +0000
525+++ src/lazr/restful/publisher.py 2009-11-16 15:00:27 +0000
526@@ -231,11 +231,11 @@
527 alsoProvides(self, IWebBrowserInitiatedRequest)
528
529 # Only accept versioned URLs. Either the
530- # service_version_uri_prefix or the
531- # latest_version_uri_prefix is acceptable.
532+ # latest_version_uri_prefix or one of the active_versions is
533+ # acceptable.
534 version = None
535- for version_string in [config.service_version_uri_prefix,
536- config.latest_version_uri_prefix]:
537+ for version_string in (
538+ config.active_versions + [config.latest_version_uri_prefix]):
539 if version_string is not None:
540 version = self._popTraversal(version_string)
541 if version is not None:
542@@ -265,13 +265,17 @@
543
544 @implementer(IWebServiceClientRequest)
545 @adapter(IBrowserRequest)
546-def browser_request_to_web_service_request(website_request):
547+def browser_request_to_web_service_request(
548+ website_request, web_service_version=None):
549 """An adapter from a browser request to a web service request.
550
551 Used to instantiate Resource objects when handling normal web
552 browser requests.
553 """
554 config = getUtility(IWebServiceConfiguration)
555+ if web_service_version is None:
556+ web_service_version = config.active_versions[-1]
557+
558 body = website_request.bodyStream.getCacheStream().read()
559 environ = dict(website_request.environment)
560 # Zope picks up on SERVER_URL when setting the _app_server attribute
561@@ -279,6 +283,8 @@
562 environ['SERVER_URL'] = website_request.getApplicationURL()
563 web_service_request = config.createRequest(body, environ)
564 web_service_request.setVirtualHostRoot(
565- names=[config.path_override, config.service_version_uri_prefix])
566+ names=[config.path_override, web_service_version])
567+ web_service_request.annotations[web_service_request.VERSION_ANNOTATION] = (
568+ web_service_request)
569 web_service_request._vh_root = website_request.getVirtualHostRoot()
570 return web_service_request
571
572=== modified file 'src/lazr/restful/testing/webservice.py'
573--- src/lazr/restful/testing/webservice.py 2009-11-12 16:30:50 +0000
574+++ src/lazr/restful/testing/webservice.py 2009-11-16 15:00:27 +0000
575@@ -163,7 +163,7 @@
576 @property
577 def default_api_version(self):
578 return getUtility(
579- IWebServiceConfiguration).service_version_uri_prefix
580+ IWebServiceConfiguration).active_versions[-1]
581
582 def getAbsoluteUrl(self, resource_path, api_version=None):
583 """Convenience method for creating a url in tests.

Subscribers

People subscribed via source and target branches