Merge lp:~leonardr/lazr.restful/multiversion-mutators into lp:lazr.restful
Proposed by
Leonard Richardson
on 2010-02-05
| Status: | Merged |
|---|---|
| Merged at revision: | not available |
| Proposed branch: | lp:~leonardr/lazr.restful/multiversion-mutators |
| Merge into: | lp:lazr.restful |
| Diff against target: |
303 lines (+192/-20) 2 files modified
src/lazr/restful/declarations.py (+70/-11) src/lazr/restful/docs/webservice-declarations.txt (+122/-9) |
| To merge this branch: | bzr merge lp:~leonardr/lazr.restful/multiversion-mutators |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Paul Hummer (community) | code | 2010-02-05 | Approve on 2010-02-05 |
|
Review via email:
|
|||
To post a comment you must log in.
| Leonard Richardson (leonardr) wrote : | # |
| Paul Hummer (rockstar) wrote : | # |
Leonard, thanks for making the pagetests so detailed. It makes reviewing easier, since I hop back and forth between test and code when I have questions. I'm also glad to see the tests that were XXX missing from a previous branch are in this one.
review:
Approve
(code)

This diff makes mutators version-aware. It lets you define different mutators for different versions, and it prevents you from defining more than one mutator for any particular version.
The complication here is that the @mutator_for annotation is attached to the mutator method, but it modifies a field. Before multi-version, @mutator_for just grabbed the field's annotation dictionary and modified it. But now, "modifying the field's annotation dictionary" means modifying the way the field is published *in the most recent version*. We need to modify the way the field is published in a *specific* version. But we have no guarantee that the field already has an existing set of annotations for that version, and if it's not in the stack already we have no idea whether that version comes before or after other versions.
Here's an example. (I don't have a test like this because it doesn't add any code coverage, and I don't think it's necessary to write a test to explain the internal implementation of something, but it's the best way to explain the problem.) Let's say I publish an entry like this:
field = exported( TextLine( ), ('foo', dict(exported_ as='foofield' ),
(' bar', dict(exported_ as='barfield' ))
@mutator_ for(field) write_operation () for_version( 'baz')
@export_
@operation_
def mutator(value):
...
When I process the 'mutator' method I need to modify the annotations on the 'field' field. That field's LAZR_WEBSERVICE _EXPORTED annotation stack looks the same as it did in the exported() call:
[('foo', dict(exported_ as='foofield' ), as='barfield' )]
('bar', dict(exported_
Where does 'baz' go? There is *no way* to know. The decision has to be deferred until generate_ entry_interface s, when we have an ordered list of the versions. So this 'baz' thing can't go into LAZR_WEBSERVICE _EXPORTED at all. That's why I created a separate annotation dictionary just for mutators, LAZR_WEBSERVICE _MUTATORS. This is a regular dictionary (not a VersionedDict) that maps versions to (mutator, mutator_ annotations) 2-tuples. When we encounter @mutator_for, the stuff that was going to go into LAZR_WEBSERVICE _EXPORTED gets put into here instead. Later on, in generate_ entry_interface s and generate_ entry_adapters, when we need to do per-version error checking or generate a per-version Property, we pull the version-indexed value out of LAZR_WEBSERVICE _MUTATORS.