~leonardr/lazr.restful/multiversion-pagetest

« back to all changes in this revision

Viewing changes to src/lazr/restful/declarations.py

  • Committer: Leonard Richardson
  • Date: 2010-02-04 22:23:54 UTC
  • mfrom: (101.3.2 multiversion-mutators)
  • Revision ID: leonard.richardson@canonical.com-20100204222354-2aa8qa9kauw0px2r
[r=rockstar] Make sure that a published destructor method never has any unfixed arguments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
285
285
            'collection_default_content', {})
286
286
 
287
287
        if version in default_content_methods:
288
 
            if version is None:
289
 
                version = "(earliest version)"
290
288
            raise TypeError(
291
289
                "Only one method can be marked with "
292
 
                "@collection_default_content for version '%s'." % version)
 
290
                "@collection_default_content for version '%s'." % (
 
291
                    _version_name(version)))
293
292
        self.version = version
294
293
        self.params = params
295
294
 
424
423
        # Make sure that each version of the web service defines
425
424
        # a self-consistent view of this method.
426
425
        for version, annotations in annotation_stack.stack:
427
 
            if version is None:
428
 
                # Create a human-readable name for the earliest version
429
 
                # without trying to look it up.
430
 
                version = "(earliest version)"
431
 
 
432
426
            if annotations['type'] == REMOVED_OPERATION_TYPE:
433
427
                # The method is published in other versions of the web
434
428
                # service, but not in this one. Don't try to validate this
456
450
                raise TypeError(
457
451
                    'method "%s" doesn\'t have the following exported '
458
452
                    'parameters in version "%s": %s.' % (
459
 
                        method.__name__, version,
 
453
                        method.__name__, _version_name(version),
460
454
                        ", ".join(sorted(undefined_params))))
461
455
            missing_params = set(
462
456
                info['required']).difference(exported_params)
463
457
            if missing_params:
464
458
                raise TypeError(
465
 
                    'method "%s" is missing exported parameter definitions '
466
 
                    'in version "%s": %s' % (
467
 
                        method.__name__, version,
 
459
                    'method "%s" is missing definitions for parameter(s) '
 
460
                    'exported in version "%s": %s' % (
 
461
                        method.__name__, _version_name(version),
468
462
                        ", ".join(sorted(missing_params))))
469
463
 
470
464
            _update_default_and_required_params(annotations['params'], info)
784
778
    """
785
779
    type = "destructor"
786
780
 
787
 
    def annotate_method(self, method, annotations):
 
781
    def annotate_method(self, method, annotation_stack):
788
782
        """See `_method_annotator`.
789
783
 
790
784
        Store information about the mutator method with the method.
 
785
 
 
786
        Every version must have a self-consistent set of annotations.
791
787
        """
 
788
        super(export_destructor_operation, self).annotate_method(
 
789
              method, annotation_stack)
792
790
        # The mutator method must take no arguments, not counting
793
791
        # arguments with values fixed by call_with().
794
792
        signature = fromFunction(method).getSignatureInfo()
795
 
        free_params = _free_parameters(method, annotations)
796
 
        if len(free_params) != 0:
797
 
            raise TypeError("A destructor method must take no "
798
 
                            "non-fixed arguments; %s takes %d." %
799
 
                            (method.__name__, len(free_params)))
800
 
        super(export_destructor_operation, self).annotate_method(
801
 
            method, annotations)
 
793
        for version, annotations in annotation_stack.stack:
 
794
            if annotations['type'] == REMOVED_OPERATION_TYPE:
 
795
                continue
 
796
            free_params = _free_parameters(method, annotations)
 
797
            if len(free_params) != 0:
 
798
                raise TypeError(
 
799
                    "A destructor method must take no non-fixed arguments. "
 
800
                    'In version %s, the "%s" method takes %d: "%s".' % (
 
801
                        _version_name(version), method.__name__,
 
802
                        len(free_params), '", "'.join(free_params))
 
803
                        )
802
804
 
803
805
 
804
806
def _check_tagged_interface(interface, type):
845
847
            if annotations.get('type') == export_destructor_operation.type:
846
848
                destructor = destructor_for_version.get(version)
847
849
                if destructor is not None:
848
 
                    if version is None:
849
 
                        version = "(earliest)"
850
850
                    raise TypeError(
851
851
                        'An entry can only have one destructor method for '
852
852
                        'version %s; %s and %s make two.' % (
853
 
                            version, method.__name__, destructor.__name__))
 
853
                            _version_name(version), method.__name__,
 
854
                            destructor.__name__))
854
855
                destructor_for_version[version] = method
855
856
 
856
857
    # Next, we'll normalize each published field. A normalized field
1267
1268
    versioned_dict.stack = new_stack
1268
1269
    return field
1269
1270
 
 
1271
 
 
1272
def _version_name(version):
 
1273
    """Return a human-readable version name.
 
1274
 
 
1275
    If `version` is None (indicating the as-yet-unknown earliest
 
1276
    version), returns "(earliest version)". Otherwise returns the version
 
1277
    name.
 
1278
    """
 
1279
    if version is None:
 
1280
        return "(earliest version)"
 
1281
    return version
 
1282
 
 
1283
 
1270
1284
def _versioned_class_name(base_name, version):
1271
1285
    """Create a class name incorporating the given version string."""
1272
1286
    if version is None: