Merge lp:~leonardr/lazr.restful/generate-multiversion-collections into lp:lazr.restful
| Status: | Merged |
|---|---|
| Approved by: | Edwin Grubbs on 2010-01-27 |
| Approved revision: | not available |
| Merged at revision: | not available |
| Proposed branch: | lp:~leonardr/lazr.restful/generate-multiversion-collections |
| Merge into: | lp:lazr.restful |
| Diff against target: |
450 lines (+210/-63) 6 files modified
src/lazr/restful/declarations.py (+41/-15) src/lazr/restful/docs/webservice-declarations.txt (+99/-12) src/lazr/restful/example/multiversion/resources.py (+10/-1) src/lazr/restful/example/multiversion/root.py (+2/-1) src/lazr/restful/example/multiversion/tests/introduction.txt (+27/-7) src/lazr/restful/metazcml.py (+31/-27) |
| To merge this branch: | bzr merge lp:~leonardr/lazr.restful/generate-multiversion-collections |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Edwin Grubbs (community) | code | 2010-01-27 | Approve on 2010-01-27 |
|
Review via email:
|
|||
| Leonard Richardson (leonardr) wrote : | # |
| Edwin Grubbs (edwin-grubbs) wrote : | # |
Hi Leonard,
This is a nice refactoring and improvement. I only have minor comments below.
merge-conditional
-Edwin
>=== modified file 'src/lazr/
>--- src/lazr/
>+++ src/lazr/
>@@ -202,7 +202,7 @@
> collection, or if used more than once in the same interface.
> """
>
>- def __init__(self, **params):
>+ def __init__(self, version=None, **params):
> """Create the decorator marking the default collection method.
>
> :param params: Optional parameter values to use when calling the
The docstring should explain how the version parameter should be used.
>@@ -891,20 +898,26 @@
> return method(**params)
>
>
>-def generate_
>+def generate_
> """Create a class adapting from interface to ICollection."""
> _check_
>
> tag = interface.
>- method_name = tag['collection
>+ default_
>+ assert (version in default_
>+ "'%s' isn't tagged for export to web service "
>+ "version '%s'." % (interface.
>+ method_name, params = default_
> entry_schema = tag['collection
> class_dict = {
> 'entry_schema' : CollectionEntry
>- 'method_name': tag['collection
>- 'params': tag['collection
>+ 'method_name': method_name,
>+ 'params': params,
> '__doc__': interface.__doc__,
> }
>- classname = "%sCollectionAd
>+ classname =_versioned_
s/=_/= _/
>+ "%sCollectionAd
>+ version)
> factory = type(classname, (BaseCollection
>
> protect_
>@@ -1016,8 +1029,9 @@
> if return_type is None:
> return_type = None
>
>- name = '%s_%s_%s_%s' % (prefix, method.
>- version)
>+ name = _versioned_
>+ '%s_%s_%s' % (prefix, method.
>+ version)
> class_dict = {'params' : tuple(tag[
> 'return_type' : return_type,
> '_export_info': tag,
>@@ -1026,8 +1040,20 @@
>
> if tag['type'] == 'write_operation':
> class_dict[
>- factory = type(make_
>+ factory = type(name, bases, class_dict)
> classImplements
> protect_
>
> return factory
>+
>+
>+def _versioned_
>+ """Create a class name incorporating the given version string."""
>+ if version is None:
>+ # We need to incorporate the version into a Python class name,
>+ # but we won't find out t...

This branch makes the @collection_ default_ content annotation
version-aware. For different versions of the web service you can
specify different methods to be used as the collection's find()
implementation, and different values for that method's keyword
arguments.
I was able to refactor some code because this is the second branch adapter_ for_version. Previously if the ntRequest. This prevents ntRequest needed to be changed to ClientRequest.
that makes our code generation version-aware. I also simplified the
implementation of register_
version in question was None (indicating the earliest version), I
looked up which version was the earliest and then looked up its
version-specific marker interface. Now I simply use the generic web
service request interface, IWebServiceClie
test failures where all that changed is that a lookup that failed with
IWebServiceClie
IWebServiceBeta
Here are some questions I asked myself during development. They all had to do
with whether version differences were better solved with annotations
or left to navigation code.
Q: Do I need an analogue to @operation_ removed_ in_version? default_ content for that version won't solve anything.
A: No. If a collection disappears in a certain version, it needs to
disappear from the navigation. Hiding the
collection_
The reason we need @operation_ removed_ in_version is that lookup of
named operation happens after the navigation is done. The
navigation takes you to an entry or collection, and then the named
operation lookup needs to succeed or fail depending on the version.
If it turns out to be too much trouble to change the navigation, we removed_ in_version and make the
could create a @collection_
lazr.restful behavior to raise a 404 instead of calling find(), but
for now I say YAGNI.
Q: What happens if a collection changes its name between versions?
A: That, too is a navigation issue. And again, we had to deal with it
specially for named operations because operation lookup is not
navigation.
Q: What happens if a collection doesn't have a default_ content for the earliest version? Don't I
@collection_
need to prevent that?
A: That corresponds to a case where the collection didn't exist in the
earliest version and was added later. This is a legitimate case,
and it will work fine if accompanied by appropriate navigation
code.