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
=== modified file 'src/lazr/restful/NEWS.txt'
--- src/lazr/restful/NEWS.txt 2009-11-12 16:30:50 +0000
+++ src/lazr/restful/NEWS.txt 2009-11-16 15:00:27 +0000
@@ -5,6 +5,10 @@
5Development5Development
6===========6===========
77
8Special note: this version contains backwards-incompatible
9changes. You *must* change your configuration object to get your code
10to work in this version! See "active_versions" below.
11
8Added the precursor of a versioning system for web services. Clients12Added the precursor of a versioning system for web services. Clients
9can now request the "trunk" of a web service as well as one published13can now request the "trunk" of a web service as well as one published
10version. Apart from the URIs served, the two web services are exactly14version. Apart from the URIs served, the two web services are exactly
@@ -16,6 +20,12 @@
16BaseWebServiceConfiguration or one of its subclasses, you'll need to20BaseWebServiceConfiguration or one of its subclasses, you'll need to
17set a value for this.21set a value for this.
1822
23This release _replaces_ one of the fields in
24IWebServiceConfiguration. The string service_version_uri_prefix has
25become the list active_versions. The simplest way to deal with this is
26to just put your service_version_uri_prefix into a list and call it
27active_versions.
28
190.9.17 (2009-11-10)290.9.17 (2009-11-10)
20===================30===================
2131
2232
=== modified file 'src/lazr/restful/docs/absoluteurl.txt'
--- src/lazr/restful/docs/absoluteurl.txt 2009-11-12 17:03:06 +0000
+++ src/lazr/restful/docs/absoluteurl.txt 2009-11-16 15:00:27 +0000
@@ -29,7 +29,7 @@
29 ... implements(IWebServiceConfiguration)29 ... implements(IWebServiceConfiguration)
30 ... hostname = "hostname"30 ... hostname = "hostname"
31 ... service_root_uri_prefix = "root_uri_prefix/"31 ... service_root_uri_prefix = "root_uri_prefix/"
32 ... service_version_uri_prefix = "service_version_uri_prefix"32 ... active_versions = ['active_version']
33 ... latest_version_uri_prefix = "latest_version_uri_prefix"33 ... latest_version_uri_prefix = "latest_version_uri_prefix"
34 ... port = 100034 ... port = 1000
35 ... use_https = True35 ... use_https = True
@@ -50,20 +50,20 @@
50 >>> resource = RootResource()50 >>> resource = RootResource()
51 >>> request = Request("", {})51 >>> request = Request("", {})
52 >>> request.annotations[request.VERSION_ANNOTATION] = (52 >>> request.annotations[request.VERSION_ANNOTATION] = (
53 ... 'service_version_uri_prefix')53 ... 'active_version')
54 >>> adapter = getMultiAdapter((resource, request), IAbsoluteURL)54 >>> adapter = getMultiAdapter((resource, request), IAbsoluteURL)
5555
56Calling the RootResourceAbsoluteURL will give the service root's56Calling the RootResourceAbsoluteURL will give the service root's
57absolute URL.57absolute URL.
5858
59 >>> print adapter()59 >>> print adapter()
60 https://hostname:1000/root_uri_prefix/service_version_uri_prefix/60 https://hostname:1000/root_uri_prefix/active_version/
6161
62Converting the adapter to a string will give the same result, but62Converting the adapter to a string will give the same result, but
63without the trailing slash.63without the trailing slash.
6464
65 >>> print str(adapter)65 >>> print str(adapter)
66 https://hostname:1000/root_uri_prefix/service_version_uri_prefix66 https://hostname:1000/root_uri_prefix/active_version
6767
68(This is useful for the recursive case. When finding the URL to a68(This is useful for the recursive case. When finding the URL to a
69subordinate resource, Zope's AbsoluteURL implementation calls str() on69subordinate resource, Zope's AbsoluteURL implementation calls str() on
@@ -75,11 +75,11 @@
7575
76 >>> configuration.use_https = False76 >>> configuration.use_https = False
77 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()77 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
78 http://hostname:1000/root_uri_prefix/service_version_uri_prefix/78 http://hostname:1000/root_uri_prefix/active_version/
7979
80 >>> configuration.port = None80 >>> configuration.port = None
81 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()81 >>> print getMultiAdapter((resource, request), IAbsoluteURL)()
82 http://hostname/root_uri_prefix/service_version_uri_prefix/82 http://hostname/root_uri_prefix/active_version/
8383
84The URL generated includes a version identifier taken from the84The URL generated includes a version identifier taken from the
85value of the 'lazr.restful.version' annotation.85value of the 'lazr.restful.version' annotation.
@@ -106,7 +106,7 @@
106Cleanup.106Cleanup.
107107
108 >>> request.annotations[request.VERSION_ANNOTATION] = (108 >>> request.annotations[request.VERSION_ANNOTATION] = (
109 ... 'service_version_uri_prefix')109 ... 'active_version')
110110
111111
112MultiplePathPartAbsoluteURL112MultiplePathPartAbsoluteURL
113113
=== modified file 'src/lazr/restful/docs/django.txt'
--- src/lazr/restful/docs/django.txt 2009-09-08 13:33:01 +0000
+++ src/lazr/restful/docs/django.txt 2009-11-16 15:00:27 +0000
@@ -110,8 +110,8 @@
110Attributes that don't have values in settings.py are given their110Attributes that don't have values in settings.py are given their
111default value.111default value.
112112
113 >>> utility.service_version_uri_prefix113 >>> utility.active_versions
114 u''114 []
115 >>> utility.use_https115 >>> utility.use_https
116 True116 True
117117
118118
=== modified file 'src/lazr/restful/docs/webservice-declarations.txt'
--- src/lazr/restful/docs/webservice-declarations.txt 2009-06-08 20:03:55 +0000
+++ src/lazr/restful/docs/webservice-declarations.txt 2009-11-16 15:00:27 +0000
@@ -953,7 +953,7 @@
953 >>> class MyWebServiceConfiguration:953 >>> class MyWebServiceConfiguration:
954 ... implements(IWebServiceConfiguration)954 ... implements(IWebServiceConfiguration)
955 ... view_permission = "lazr.View"955 ... view_permission = "lazr.View"
956 ... service_version_uri_prefix = "beta"956 ... active_versions = ["beta"]
957 ... code_revision = "1.0b"957 ... code_revision = "1.0b"
958 ... default_batch_size = 50958 ... default_batch_size = 50
959 ...959 ...
960960
=== modified file 'src/lazr/restful/docs/webservice-request.txt'
--- src/lazr/restful/docs/webservice-request.txt 2009-08-11 18:36:20 +0000
+++ src/lazr/restful/docs/webservice-request.txt 2009-11-16 15:00:27 +0000
@@ -22,7 +22,7 @@
22 >>> class SimpleWebServiceConfiguration:22 >>> class SimpleWebServiceConfiguration:
23 ... implements(IWebServiceConfiguration)23 ... implements(IWebServiceConfiguration)
24 ... path_override = 'api'24 ... path_override = 'api'
25 ... service_version_uri_prefix = 'beta'25 ... active_versions = ['beta']
26 ...26 ...
27 ... def createRequest(self, body_stream, environ):27 ... def createRequest(self, body_stream, environ):
28 ... request = Request(body_stream, environ)28 ... request = Request(body_stream, environ)
2929
=== modified file 'src/lazr/restful/docs/webservice.txt'
--- src/lazr/restful/docs/webservice.txt 2009-11-12 16:30:50 +0000
+++ src/lazr/restful/docs/webservice.txt 2009-11-16 15:00:27 +0000
@@ -517,7 +517,7 @@
517517
518 >>> class WebServiceConfiguration(BaseWebServiceConfiguration):518 >>> class WebServiceConfiguration(BaseWebServiceConfiguration):
519 ... use_https = False519 ... use_https = False
520 ... service_version_uri_prefix = 'beta'520 ... active_versions = ['beta']
521 ... latest_version_uri_prefix = 'devel'521 ... latest_version_uri_prefix = 'devel'
522 ... code_revision = 'test'522 ... code_revision = 'test'
523 ... max_batch_size = 100523 ... max_batch_size = 100
524524
=== modified file 'src/lazr/restful/example/base/root.py'
--- src/lazr/restful/example/base/root.py 2009-11-12 16:43:57 +0000
+++ src/lazr/restful/example/base/root.py 2009-11-16 15:00:27 +0000
@@ -387,7 +387,7 @@
387 default_batch_size=5387 default_batch_size=5
388 hostname='cookbooks.dev'388 hostname='cookbooks.dev'
389 match_batch_size=50389 match_batch_size=50
390 service_version_uri_prefix='1.0'390 active_versions=['1.0']
391 use_https=False391 use_https=False
392 view_permission='lazr.restful.example.base.View'392 view_permission='lazr.restful.example.base.View'
393393
394394
=== modified file 'src/lazr/restful/example/base/tests/service.txt'
--- src/lazr/restful/example/base/tests/service.txt 2009-11-12 16:35:38 +0000
+++ src/lazr/restful/example/base/tests/service.txt 2009-11-16 15:00:27 +0000
@@ -10,37 +10,18 @@
10Versioning10Versioning
11==========11==========
1212
13In addition to the published version of the web service, lazr.restful13lazr.restful allows you to publish multiple named versions of a web
14publishes a "development" version which may contain backwards14service, as well as a "development" version which includes changes you
15incompatible changes. The default name of the development version is15have yet to batch together into a named version. The default name of
16"devel".16the development version is "devel".
1717
18 >>> body = webservice.get('/', api_version="devel").jsonBody()18 >>> top_level_response = webservice.get(
1919 ... "/", api_version="devel").jsonBody()
20The development version serves URLs that reflect its version name.20 >>> print top_level_response['resource_type_link']
2121 http://cookbooks.dev/devel/#service-root
22 >>> print body['recipes_collection_link']22
23 http://cookbooks.dev/devel/recipes23The web service in examples/multiversion is devoted solely to testing
24 >>> print body['resource_type_link']24the versioning code.
25 http://cookbooks.dev/devel/#service-root
26
27Currently there is no way to publish multiple versions of the web
28service, so apart from the URLs, the development version is exactly
29the same as the only published version.
30
31All versions of the web service can be accessed through Ajax.
32
33 >>> from lazr.restful.testing.webservice import WebServiceAjaxCaller
34 >>> ajax = WebServiceAjaxCaller(domain='cookbooks.dev')
35 >>> body = ajax.get('/', api_version="devel").jsonBody()
36 >>> print body['resource_type_link']
37 http://cookbooks.dev/devel/#service-root
38
39An attempt to access a nonexistent version yields a 404 error.
40
41 >>> print webservice.get('/', api_version="no_such_version")
42 HTTP/1.1 404 Not Found
43 ...
4425
45Nonexistent resources26Nonexistent resources
46=====================27=====================
4728
=== added directory 'src/lazr/restful/example/multiversion'
=== added file 'src/lazr/restful/example/multiversion/README.txt'
--- src/lazr/restful/example/multiversion/README.txt 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/README.txt 2009-11-16 15:00:27 +0000
@@ -0,0 +1,6 @@
1Multiversion web service
2************************
3
4This web service demonstrates lazr.restful's ability to serve multiple
5backwards-incompatible versions of a web service from the same
6underlying code.
07
=== added file 'src/lazr/restful/example/multiversion/__init__.py'
=== added file 'src/lazr/restful/example/multiversion/resources.py'
--- src/lazr/restful/example/multiversion/resources.py 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/resources.py 2009-11-16 15:00:27 +0000
@@ -0,0 +1,35 @@
1__metaclass__ = type
2
3__all__ = ['IKeyValuePair',
4 'IPairSet',
5 'KeyValuePair',
6 'PairSet']
7
8from zope.schema import Text
9from zope.location.interfaces import ILocation
10
11from lazr.restful.declarations import (
12 collection_default_content, export_as_webservice_collection,
13 export_as_webservice_entry, exported)
14
15# We don't need separate implementations of these classes, so borrow
16# the implementations from the WSGI example.
17from lazr.restful.example.wsgi.resources import PairSet, KeyValuePair
18
19# Our interfaces _will_ diverge from the WSGI example interfaces, so
20# define them separately.
21class IKeyValuePair(ILocation):
22 export_as_webservice_entry()
23 key = exported(Text(title=u"The key"))
24 value = exported(Text(title=u"The value"))
25
26
27class IPairSet(ILocation):
28 export_as_webservice_collection(IKeyValuePair)
29
30 @collection_default_content()
31 def getPairs():
32 """Return the key-value pairs."""
33
34 def get(request, name):
35 """Retrieve a key-value pair by its key."""
036
=== added file 'src/lazr/restful/example/multiversion/root.py'
--- src/lazr/restful/example/multiversion/root.py 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/root.py 2009-11-16 15:00:27 +0000
@@ -0,0 +1,53 @@
1"""The RESTful service root."""
2
3__metaclass__ = type
4__all__ = [
5 'BelowRootAbsoluteURL',
6 'RootAbsoluteURL',
7 'WebServiceConfiguration',
8 'MultiversionWebServiceRootResource',
9 ]
10
11from zope.traversing.browser import AbsoluteURL
12
13from lazr.restful.wsgi import BaseWSGIWebServiceConfiguration
14from lazr.restful.simple import RootResource, RootResourceAbsoluteURL
15from lazr.restful.example.multiversion.resources import (
16 IKeyValuePair, PairSet, KeyValuePair)
17
18
19class RootAbsoluteURL(RootResourceAbsoluteURL):
20 """A technique for generating the service's root URL.
21
22 This class contains no code of its own. It's defined so that
23 grok will pick it up.
24 """
25
26
27class BelowRootAbsoluteURL(AbsoluteURL):
28 """A technique for generating a root URL given an ILocation.
29
30 This class contains no code of its own. It's defined so that
31 grok will pick it up.
32 """
33
34
35class WebServiceConfiguration(BaseWSGIWebServiceConfiguration):
36 code_revision = '1'
37 active_versions = ['beta', '1.0', '2.0']
38 latest_version_uri_prefix = 'trunk'
39 use_https = False
40 view_permission = 'zope.Public'
41
42
43class MultiversionWebServiceRootResource(RootResource):
44 """The root resource for the WSGI example web service."""
45 def _build_top_level_objects(self):
46 pairset = PairSet()
47 pairset.pairs = [
48 KeyValuePair(self, "foo", "bar"),
49 KeyValuePair(self, "1", "2")
50 ]
51 collections = dict(pairs=(IKeyValuePair, pairset))
52 return collections, {}
53
054
=== added file 'src/lazr/restful/example/multiversion/site.zcml'
--- src/lazr/restful/example/multiversion/site.zcml 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/site.zcml 2009-11-16 15:00:27 +0000
@@ -0,0 +1,13 @@
1<configure
2 xmlns="http://namespaces.zope.org/zope"
3 xmlns:webservice="http://namespaces.canonical.com/webservice"
4 xmlns:grok="http://namespaces.zope.org/grok">
5
6 <include package="lazr.restful" file="basic-site.zcml" />
7 <webservice:register
8 module="lazr.restful.example.multiversion.resources" />
9 <grok:grok package="lazr.restful.example.multiversion" />
10
11 <securityPolicy
12 component="zope.security.simplepolicies.PermissiveSecurityPolicy" />
13</configure>
014
=== added directory 'src/lazr/restful/example/multiversion/tests'
=== added file 'src/lazr/restful/example/multiversion/tests/__init__.py'
=== added file 'src/lazr/restful/example/multiversion/tests/introduction.txt'
--- src/lazr/restful/example/multiversion/tests/introduction.txt 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/tests/introduction.txt 2009-11-16 15:00:27 +0000
@@ -0,0 +1,64 @@
1Multi-version web services
2**************************
3
4lazr.restful lets you publish two or more mutually incompatible
5web services from the same underlying code. This lets you improve your
6web service to take advantage of new features of lazr.restful, without
7sacrificing backwards compatibility.
8
9The web service in example/multiversion illustrates the multiversion
10features of lazr.restful.
11
12 >>> from lazr.restful.testing.webservice import WebServiceCaller
13 >>> webservice = WebServiceCaller(domain='multiversion.dev')
14
15The multiversion web service serves three named versions of the same
16web service: "beta", "1.0", and "2.0". Once you make a request to the
17service root of a particular version, the web service only serves you
18links within that version.
19
20 >>> top_level_response = webservice.get(
21 ... "/", api_version="beta").jsonBody()
22 >>> print top_level_response['key_value_pairs_collection_link']
23 http://multiversion.dev/beta/pairs
24
25 >>> top_level_response = webservice.get(
26 ... "/", api_version="1.0").jsonBody()
27 >>> print top_level_response['key_value_pairs_collection_link']
28 http://multiversion.dev/1.0/pairs
29
30 >>> top_level_response = webservice.get(
31 ... "/", api_version="2.0").jsonBody()
32 >>> print top_level_response['key_value_pairs_collection_link']
33 http://multiversion.dev/2.0/pairs
34
35Like all web services, the multiversion service also serves a
36development version which tracks the current state of the web service,
37including all changes that have not yet been folded into a named
38version. The default name for the development version is "devel" (see
39example/base/tests/service.txt), but in this web service it's called
40"trunk".
41
42 >>> top_level_response = webservice.get(
43 ... "/", api_version="trunk").jsonBody()
44 >>> print top_level_response['key_value_pairs_collection_link']
45 http://multiversion.dev/trunk/pairs
46
47All versions of the web service can be accessed through Ajax.
48
49 >>> from lazr.restful.testing.webservice import WebServiceAjaxCaller
50 >>> ajax = WebServiceAjaxCaller(domain='multiversion.dev')
51
52 >>> body = ajax.get('/', api_version="1.0").jsonBody()
53 >>> print body['resource_type_link']
54 http://multiversion.dev/1.0/#service-root
55
56 >>> body = ajax.get('/', api_version="trunk").jsonBody()
57 >>> print body['resource_type_link']
58 http://multiversion.dev/trunk/#service-root
59
60An attempt to access a nonexistent version yields a 404 error.
61
62 >>> print webservice.get('/', api_version="no_such_version")
63 HTTP/1.1 404 Not Found
64 ...
065
=== added file 'src/lazr/restful/example/multiversion/tests/test_integration.py'
--- src/lazr/restful/example/multiversion/tests/test_integration.py 1970-01-01 00:00:00 +0000
+++ src/lazr/restful/example/multiversion/tests/test_integration.py 2009-11-16 15:00:27 +0000
@@ -0,0 +1,53 @@
1# Copyright 2008 Canonical Ltd. All rights reserved.
2
3"""Test harness for doctests for lazr.restful multiversion example service."""
4
5__metaclass__ = type
6__all__ = []
7
8import os
9import doctest
10from pkg_resources import resource_filename
11
12from zope.component import getUtility
13from van.testing.layer import zcml_layer, wsgi_intercept_layer
14
15from lazr.restful.example.multiversion.root import (
16 MultiversionWebServiceRootResource)
17from lazr.restful.interfaces import IWebServiceConfiguration
18from lazr.restful.simple import Publication
19from lazr.restful.testing.webservice import WebServiceApplication
20
21
22DOCTEST_FLAGS = (
23 doctest.ELLIPSIS |
24 doctest.NORMALIZE_WHITESPACE |
25 doctest.REPORT_NDIFF)
26
27
28class FunctionalLayer:
29 zcml = os.path.abspath(resource_filename(
30 'lazr.restful.example.multiversion', 'site.zcml'))
31zcml_layer(FunctionalLayer)
32
33
34class WSGILayer(FunctionalLayer):
35
36 @classmethod
37 def make_application(self):
38 getUtility(IWebServiceConfiguration).hostname = "multiversion.dev"
39 getUtility(IWebServiceConfiguration).port = None
40 root = MultiversionWebServiceRootResource()
41 return WebServiceApplication(root, Publication)
42wsgi_intercept_layer(WSGILayer)
43
44
45def additional_tests():
46 """See `zope.testing.testrunner`."""
47 tests = sorted(
48 [name
49 for name in os.listdir(os.path.dirname(__file__))
50 if name.endswith('.txt')])
51 suite = doctest.DocFileSuite(optionflags=DOCTEST_FLAGS, *tests)
52 suite.layer = WSGILayer
53 return suite
054
=== modified file 'src/lazr/restful/example/wsgi/root.py'
--- src/lazr/restful/example/wsgi/root.py 2009-11-12 16:43:57 +0000
+++ src/lazr/restful/example/wsgi/root.py 2009-11-16 15:00:27 +0000
@@ -34,7 +34,7 @@
3434
35class WebServiceConfiguration(BaseWSGIWebServiceConfiguration):35class WebServiceConfiguration(BaseWSGIWebServiceConfiguration):
36 code_revision = '1'36 code_revision = '1'
37 service_version_uri_prefix = '1.0'37 active_versions = ['1.0']
38 use_https = False38 use_https = False
39 view_permission = 'zope.Public'39 view_permission = 'zope.Public'
4040
4141
=== modified file 'src/lazr/restful/interfaces/_rest.py'
--- src/lazr/restful/interfaces/_rest.py 2009-11-12 16:43:57 +0000
+++ src/lazr/restful/interfaces/_rest.py 2009-11-16 15:00:27 +0000
@@ -51,7 +51,7 @@
51 'IWebServiceLayer',51 'IWebServiceLayer',
52 ]52 ]
5353
54from zope.schema import Bool, Int, TextLine54from zope.schema import Bool, Int, List, TextLine
55from zope.interface import Attribute, Interface55from zope.interface import Attribute, Interface
56# These two should really be imported from zope.interface, but56# These two should really be imported from zope.interface, but
57# the import fascist complains because they are not in __all__ there.57# the import fascist complains because they are not in __all__ there.
@@ -417,15 +417,19 @@
417 "put the URL prefix here. (In the example case, the URL prefix "417 "put the URL prefix here. (In the example case, the URL prefix "
418 "is 'web-service/').")418 "is 'web-service/').")
419419
420 service_version_uri_prefix = TextLine(420 active_versions = List(
421 default=u"",421 value_type=TextLine(),
422 description=u"""The versioning string, if any, to use as the422 default = [],
423 URI prefix for web service URIs. A popular string is 'beta',423 title=u"The active versions of the web service.",
424 but you could also use a version number or the date the API424 description = u"""A list of names of active versions of this
425 was finalized.425 web service. They might be version numbers, names such as
426426 "beta", or the date a particular version was finalized.
427 The service version URI prefix shows up in URIs *after* any427
428 value for service_root_uri_prefix.""")428 Newer versions should show up later in the list than earlier
429 versions. The most recent active version should be at the end
430 of the list.
431
432 Currently this list must contain at least one version name.""")
429433
430 latest_version_uri_prefix = TextLine(434 latest_version_uri_prefix = TextLine(
431 default=u"devel",435 default=u"devel",
432436
=== modified file 'src/lazr/restful/publisher.py'
--- src/lazr/restful/publisher.py 2009-11-12 17:03:06 +0000
+++ src/lazr/restful/publisher.py 2009-11-16 15:00:27 +0000
@@ -231,11 +231,11 @@
231 alsoProvides(self, IWebBrowserInitiatedRequest)231 alsoProvides(self, IWebBrowserInitiatedRequest)
232232
233 # Only accept versioned URLs. Either the233 # Only accept versioned URLs. Either the
234 # service_version_uri_prefix or the234 # latest_version_uri_prefix or one of the active_versions is
235 # latest_version_uri_prefix is acceptable.235 # acceptable.
236 version = None236 version = None
237 for version_string in [config.service_version_uri_prefix,237 for version_string in (
238 config.latest_version_uri_prefix]:238 config.active_versions + [config.latest_version_uri_prefix]):
239 if version_string is not None:239 if version_string is not None:
240 version = self._popTraversal(version_string)240 version = self._popTraversal(version_string)
241 if version is not None:241 if version is not None:
@@ -265,13 +265,17 @@
265265
266@implementer(IWebServiceClientRequest)266@implementer(IWebServiceClientRequest)
267@adapter(IBrowserRequest)267@adapter(IBrowserRequest)
268def browser_request_to_web_service_request(website_request):268def browser_request_to_web_service_request(
269 website_request, web_service_version=None):
269 """An adapter from a browser request to a web service request.270 """An adapter from a browser request to a web service request.
270271
271 Used to instantiate Resource objects when handling normal web272 Used to instantiate Resource objects when handling normal web
272 browser requests.273 browser requests.
273 """274 """
274 config = getUtility(IWebServiceConfiguration)275 config = getUtility(IWebServiceConfiguration)
276 if web_service_version is None:
277 web_service_version = config.active_versions[-1]
278
275 body = website_request.bodyStream.getCacheStream().read()279 body = website_request.bodyStream.getCacheStream().read()
276 environ = dict(website_request.environment)280 environ = dict(website_request.environment)
277 # Zope picks up on SERVER_URL when setting the _app_server attribute281 # Zope picks up on SERVER_URL when setting the _app_server attribute
@@ -279,6 +283,8 @@
279 environ['SERVER_URL'] = website_request.getApplicationURL()283 environ['SERVER_URL'] = website_request.getApplicationURL()
280 web_service_request = config.createRequest(body, environ)284 web_service_request = config.createRequest(body, environ)
281 web_service_request.setVirtualHostRoot(285 web_service_request.setVirtualHostRoot(
282 names=[config.path_override, config.service_version_uri_prefix])286 names=[config.path_override, web_service_version])
287 web_service_request.annotations[web_service_request.VERSION_ANNOTATION] = (
288 web_service_request)
283 web_service_request._vh_root = website_request.getVirtualHostRoot()289 web_service_request._vh_root = website_request.getVirtualHostRoot()
284 return web_service_request290 return web_service_request
285291
=== modified file 'src/lazr/restful/testing/webservice.py'
--- src/lazr/restful/testing/webservice.py 2009-11-12 16:30:50 +0000
+++ src/lazr/restful/testing/webservice.py 2009-11-16 15:00:27 +0000
@@ -163,7 +163,7 @@
163 @property163 @property
164 def default_api_version(self):164 def default_api_version(self):
165 return getUtility(165 return getUtility(
166 IWebServiceConfiguration).service_version_uri_prefix166 IWebServiceConfiguration).active_versions[-1]
167167
168 def getAbsoluteUrl(self, resource_path, api_version=None):168 def getAbsoluteUrl(self, resource_path, api_version=None):
169 """Convenience method for creating a url in tests.169 """Convenience method for creating a url in tests.

Subscribers

People subscribed via source and target branches