Code review comment for lp:~leonardr/lazr.restful/multiversion-mutators

Revision history for this message
Leonard Richardson (leonardr) wrote :

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)
    @export_write_operation()
    @operation_for_version('baz')
    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'),
 ('bar', dict(exported_as='barfield')]

Where does 'baz' go? There is *no way* to know. The decision has to be deferred until generate_entry_interfaces, 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_interfaces 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.

« Back to merge proposal