Merge lp:~cjwatson/lazr.restful/mutator-replacement into lp:lazr.restful

Proposed by Colin Watson
Status: Merged
Merged at revision: 226
Proposed branch: lp:~cjwatson/lazr.restful/mutator-replacement
Merge into: lp:lazr.restful
Diff against target: 156 lines (+40/-29)
3 files modified
src/lazr/restful/NEWS.txt (+9/-0)
src/lazr/restful/docs/webservice-declarations.txt (+14/-21)
src/lazr/restful/metazcml.py (+17/-8)
To merge this branch: bzr merge lp:~cjwatson/lazr.restful/mutator-replacement
Reviewer Review Type Date Requested Status
Ioana Lasc (community) Approve
LAZR Developers Pending
Review via email: mp+355845@code.launchpad.net

Commit message

Remove limitation on immediately reinstating a mutator as a named operation.

Description of the change

This previously only worked if the registration code happened to encounter the replacing named operation before it encountered the replaced mutator, which ultimately depended on dict iteration order. I considered making it enforce the limitation consistently, but it was just as easy to remove the limitation.

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) :
review: Approve

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 2018-02-21 15:18:34 +0000
+++ src/lazr/restful/NEWS.txt 2018-09-28 14:44:56 +0000
@@ -2,6 +2,15 @@
2NEWS for lazr.restful2NEWS for lazr.restful
3=====================3=====================
44
50.20.2
6======
7
8Remove limitation on immediately reinstating a named operation with the same
9name as a mutator in the webservice version that gets rid of named
10operations for mutator methods. (This was previously only unreliably
11enforced in any case, as it depended on the order of methods returned by
12zope.interface.Interface.namesAndDescriptions.)
13
50.20.1 (2018-02-21)140.20.1 (2018-02-21)
6===================15===================
716
817
=== modified file 'src/lazr/restful/docs/webservice-declarations.txt'
--- src/lazr/restful/docs/webservice-declarations.txt 2016-02-17 01:07:21 +0000
+++ src/lazr/restful/docs/webservice-declarations.txt 2018-09-28 14:44:56 +0000
@@ -2901,14 +2901,13 @@
2901 >>> print entry.field2901 >>> print entry.field
2902 !foo!2902 !foo!
29032903
2904You can't immediately reinstate a mutator operation as a named operation2904You can immediately reinstate a mutator operation as a named operation
2905^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^2905^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29062906
2907Here's one that shows a limitation of the software. This method2907This method defines a mutator 'set_value' for version 1.0, which will be
2908defines a mutator 'set_value' for version 1.0, which will be removed2908removed in version 2.0. It *also* defines a named operation to be published
2909in version 2.0. It *also* defines a named operation to be published2909as 'set_value' in version 2.0, and a third operation to be published as
2910as 'set_value' in version 2.0, and a third operation to be published2910'set_value' in version 3.0.
2911as 'set_value' in version 3.0.
29122911
2913 >>> class IMutatorPlusNamedOperationEntry(Interface):2912 >>> class IMutatorPlusNamedOperationEntry(Interface):
2914 ... export_as_webservice_entry()2913 ... export_as_webservice_entry()
@@ -2950,23 +2949,17 @@
2950 >>> print operation_for(context, '1.0', 'set_value').__class__.__name__2949 >>> print operation_for(context, '1.0', 'set_value').__class__.__name__
2951 POST_IMutatorPlusNamedOperationEntry_set_value_1_02950 POST_IMutatorPlusNamedOperationEntry_set_value_1_0
29522951
2953But the named operation that replaces the mutator in version 1.0 is2952The named operations that replace the mutator in versions 2.0 and 3.0 are
2954not accessible.2953also accessible.
29552954
2956 >>> operation_for(context, '2.0', 'set_value')2955 >>> print operation_for(context, '2.0', 'set_value').__class__.__name__
2957 Traceback (most recent call last):2956 POST_IMutatorPlusNamedOperationEntry_set_value_2_0
2958 ...
2959 ComponentLookupError: ...
2960
2961The named operation of the same name defined in version 3.0 _is_
2962accessible.
2963
2964 >>> print operation_for(context, '3.0', 'set_value').__class__.__name__2957 >>> print operation_for(context, '3.0', 'set_value').__class__.__name__
2965 POST_IMutatorPlusNamedOperationEntry_set_value_3_02958 POST_IMutatorPlusNamedOperationEntry_set_value_3_0
29662959
2967So, in the version that gets rid of named operations for mutator2960So, in the version that gets rid of named operations for mutator methods,
2968methods, you can't define a named operation with the same name as one2961you can immediately define a named operation with the same name as one of
2969of the outgoing mutator methods.2962the outgoing mutator methods.
29702963
2971Removing mutator named operations altogether2964Removing mutator named operations altogether
2972^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^2965^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29732966
=== modified file 'src/lazr/restful/metazcml.py'
--- src/lazr/restful/metazcml.py 2016-11-26 00:54:04 +0000
+++ src/lazr/restful/metazcml.py 2018-09-28 14:44:56 +0000
@@ -476,6 +476,8 @@
476 no_mutator_operations_after+1]476 no_mutator_operations_after+1]
477 else:477 else:
478 block_mutator_operations_as_of_version = None478 block_mutator_operations_as_of_version = None
479 registered_adapters = set()
480 block_mutator_operations = set()
479481
480 methods = interface.namesAndDescriptions(True)482 methods = interface.namesAndDescriptions(True)
481 for iface in REGISTERED_CONTRIBUTORS[interface]:483 for iface in REGISTERED_CONTRIBUTORS[interface]:
@@ -522,7 +524,6 @@
522 # version.524 # version.
523 previous_operation_name = None525 previous_operation_name = None
524 previous_operation_provides = None526 previous_operation_provides = None
525 mutator_operation_needs_to_be_blocked = False
526 for version, tag in tag.stack:527 for version, tag in tag.stack:
527 if version is None:528 if version is None:
528 this_version_index = 0529 this_version_index = 0
@@ -592,7 +593,6 @@
592 # This will save us from having to do another593 # This will save us from having to do another
593 # de-registration later.594 # de-registration later.
594 factory = _mask_adapter_registration595 factory = _mask_adapter_registration
595 mutator_operation_needs_to_be_blocked = False
596 else:596 else:
597 factory = generate_operation_adapter(method, version)597 factory = generate_operation_adapter(method, version)
598598
@@ -607,6 +607,9 @@
607 _mask_adapter_registration, interface, version,607 _mask_adapter_registration, interface, version,
608 previous_operation_provides, previous_operation_name,608 previous_operation_provides, previous_operation_name,
609 context.info)609 context.info)
610 registered_adapters.add(
611 (previous_operation_name, version,
612 previous_operation_provides))
610613
611 # If the operation exists in this version (ie. its name is614 # If the operation exists in this version (ie. its name is
612 # not None), register it using this version's name.615 # not None), register it using this version's name.
@@ -614,6 +617,8 @@
614 register_adapter_for_version(617 register_adapter_for_version(
615 factory, interface, version, operation_provides,618 factory, interface, version, operation_provides,
616 operation_name, context.info)619 operation_name, context.info)
620 registered_adapters.add(
621 (operation_name, version, operation_provides))
617 if (tag.get('is_mutator')622 if (tag.get('is_mutator')
618 and block_mutator_operations_as_of_version != None):623 and block_mutator_operations_as_of_version != None):
619 defined_in = this_version_index624 defined_in = this_version_index
@@ -625,21 +630,25 @@
625 # mutators stop being named operations, and630 # mutators stop being named operations, and
626 # the operation registration for this mutator631 # the operation registration for this mutator
627 # will need to be blocked.632 # will need to be blocked.
628 mutator_operation_needs_to_be_blocked = True633 block_mutator_operations.add(
634 (operation_name,
635 block_mutator_operations_as_of_version,
636 operation_provides))
629 if repository is not None:637 if repository is not None:
630 repository.append(VersionedObject(version, method))638 repository.append(VersionedObject(version, method))
631 previous_operation_name = operation_name639 previous_operation_name = operation_name
632 previous_operation_provides = operation_provides640 previous_operation_provides = operation_provides
633641
634 if mutator_operation_needs_to_be_blocked:642 for operation_key in block_mutator_operations:
643 if operation_key not in registered_adapters:
644 operation_name, version, operation_provides = operation_key
635 # The operation was registered as a mutator, back in the645 # The operation was registered as a mutator, back in the
636 # days when mutator operations were also named operations,646 # days when mutator operations were also named operations,
637 # and it never got de-registered. De-register it now.647 # and it never got de-registered. De-register it now.
638 register_adapter_for_version(648 register_adapter_for_version(
639 _mask_adapter_registration, interface,649 _mask_adapter_registration, interface, version,
640 block_mutator_operations_as_of_version,650 operation_provides, operation_name, context.info)
641 previous_operation_provides, previous_operation_name,651
642 context.info)
643652
644def _mask_adapter_registration(*args):653def _mask_adapter_registration(*args):
645 """A factory function that stops an adapter lookup from succeeding.654 """A factory function that stops an adapter lookup from succeeding.

Subscribers

People subscribed via source and target branches