Merge lp:~leonardr/lazr.restful/version-specific-request-interface into lp:lazr.restful
| Status: | Work in progress |
|---|---|
| Proposed branch: | lp:~leonardr/lazr.restful/version-specific-request-interface |
| Merge into: | lp:lazr.restful |
| Diff against target: |
395 lines (+180/-76) 3 files modified
src/lazr/restful/docs/multiversion.txt (+146/-73) src/lazr/restful/interfaces/_rest.py (+17/-1) src/lazr/restful/publisher.py (+17/-2) |
| To merge this branch: | bzr merge lp:~leonardr/lazr.restful/version-specific-request-interface |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Francis J. Lacoste (community) | code | 2009-11-23 | Approve on 2010-01-06 |
|
Review via email:
|
|||
| Leonard Richardson (leonardr) wrote : | # |
| Leonard Richardson (leonardr) wrote : | # |
Because this branch is complicated and I'm not yet certain it will pay off, I don't plan to land it immediately. Instead, I'll be merging other branches into it and landing the whole thing once I have something useful.
| Francis J. Lacoste (flacoste) wrote : | # |
Hi Leonard,
Nice to see this coming along.
This is good to go once you fix the conflit marker and handle my few other
comments.
Cheers
> === modified file 'src/lazr/
> --- src/lazr/
> +++ src/lazr/
> @@ -5,10 +5,99 @@
> services. Typically these different services represent successive
> versions of a single web service, improved over time.
>
> +Setup
> +=====
> +
> +First, let's set up the web service infrastructure. Doing this first
> +will let us create HTTP requests for different versions of the web
> +service. The first step is to make all component lookups use the
> +global site manager.
> +
> + >>> from zope.component import getSiteManager
> + >>> sm = getSiteManager()
> +
> + >>> from zope.component import adapter
> + >>> from zope.component.
> + >>> from zope.interface import implementer, Interface
> + >>> @implementer(
> + ... @adapter(Interface)
> + ... def everything_
> + ... return sm
> + >>> sm.registerAdap
Like discussed on IRC, the waving of this dead chicken isn't needed :-)
> +
> +Defining the request interfaces
> +------
> +
> +Every version must have a corresponding subclass of
> +IWebServiceCli
> +keep track of which version of the web service a particular client
> +wants to use. In a real application, these interfaces will be
> +generated and registered automatically.
> +
> + >>> from lazr.restful.
> + ... IVersionedClien
> + >>> class IWebServiceRequ
> + ... pass
> +
> + >>> class IWebServiceRequ
> + ... pass
> +
> + >>> class IWebServiceRequ
> + ... pass
> +
> + >>> request_classes = [IWebServiceReq
> + ... IWebServiceRequ
> +
> + >>> from zope.interface import alsoProvides
> + >>> for cls, version in ((IWebServiceRe
> + ... (IWebServiceReq
> + ... (IWebServiceReq
> + ... alsoProvides(cls, IVersionedClien
> + ... sm.registerUtil
> + ... name=version)
> +
Can you explain the use of IVersionedClien
explained on IRC that it to make it easy to retrieve the interface related to
a version string.
Would IVersionedWebCl
> +<<<<<<< TREE
> >>> for version in ['beta', 'dev', '1.0']:
> ... sm.registerAdapter(
> ... ContactCollection, provided=
> @@ -397,3 +495,105 @@
> >>> print absoluteURL(
> http://
- 95. By Leonard Richardson on 2010-01-06
-
Merged from original branch to get rid of conflict markers.
| Leonard Richardson (leonardr) wrote : | # |
I removed the rubber chicken and changed the text in the section on named utilities to make it more clear. I did this in the second branch because this branch has a lot of test failures (which the job of the second branch is to fix). The second branch already included a doctest of request.version, in the "Request lifecycle" section of multiversion.txt.
Unmerged revisions
- 95. By Leonard Richardson on 2010-01-06
-
Merged from original branch to get rid of conflict markers.

This branch changes the way an incoming web service request is associated with a specific version of the web service. Previously, the version number was stuffed into a Zope annotation on the request object. Versioned lookups were done as named lookups using the version number as the name.
Now, the web service is expected to define a marker interface for every version it publishes, eg. IWebServiceRequ estBeta. Once the traversal code knows which version of the web service the client is requesting, it calls alsoProvides on the request object to mark it with the appropriate marker interface.
The idea here is to get rid of named lookups. Instead of this:
getAdapter( data_model_ object, IEntry, name="1.0")
We can now do this:
getMultiAdapter ([data_ model_object, request], IEntry)
Unfortunately, the benefits of this are mostly in the future. The two named lookups we do right now cannot be turned into multiadapter lookups. The first is the lookup that gets us the version-specific request interface in the first place. The second is a utility lookup:
root = getUtility( IWebServiceRoot Resource, name="1.0")
There's no such thing as a multi-value utility lookup. However, I'm considering writing a wrapper class that lets the utility lookup look like a simple adaptation:
root = IWebServiceRoot Resource( request)
But I'm not sure if that's valuable to the programmer.
To avoid a million test failures, I preserved the behavior of the unversioned code (where the incoming request does not have any special interface applied to it). I'll almost certainly remove this code once I make the service generation code support multi-versioning, but that's a way in the future.