Source code for swagger_spec_compatibility.walkers.additional_properties

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import typing
from enum import Enum
from itertools import chain

from bravado_core.spec import Spec

from swagger_spec_compatibility.spec_utils import get_properties
from swagger_spec_compatibility.util import EntityMapping
from swagger_spec_compatibility.walkers import NoValue
from swagger_spec_compatibility.walkers import PathType
from swagger_spec_compatibility.walkers import SchemaWalker


[docs]class DiffType(Enum): PROPERTIES = 0 VALUE = 1
[docs]class AdditionalPropertiesDiff(typing.NamedTuple( 'AdditionalPropertiesDiff', ( ('path', PathType), ('diff_type', DiffType), ('additionalProperties', typing.Optional[EntityMapping[typing.Union[bool, typing.Mapping[typing.Text, typing.Any]]]]), ('properties', typing.Optional[EntityMapping[typing.Set[typing.Text]]]), ), )):
[docs] def fix_parameter_path(self, path, original_path): # type: (PathType, PathType) -> 'AdditionalPropertiesDiff' return AdditionalPropertiesDiff( path=tuple(chain(original_path, self.path[len(original_path):])), diff_type=self.diff_type, additionalProperties=self.additionalProperties, properties=self.properties, )
def _evaluate_additional_properties_diffs( path, # type: PathType left_spec, # type: Spec right_spec, # type: Spec left_schema, # type: typing.Optional[typing.Mapping[typing.Text, typing.Any]] right_schema, # type: typing.Optional[typing.Mapping[typing.Text, typing.Any]] ): # type: (...) -> typing.List[AdditionalPropertiesDiff] result = [] # type: typing.List[AdditionalPropertiesDiff] left_additional_properties = None if left_schema is None else left_schema.get('additionalProperties', True) right_additional_properties = None if right_schema is None else right_schema.get('additionalProperties', True) left_properties = get_properties(left_spec, left_schema) or set() right_properties = get_properties(right_spec, right_schema) or set() properties_appear_once = left_properties.symmetric_difference(right_properties) if left_additional_properties == {}: # Normalize additional properties left_additional_properties = True if right_additional_properties == {}: # Normalize additional properties right_additional_properties = True if left_additional_properties != right_additional_properties: result.append(AdditionalPropertiesDiff( path=path, diff_type=DiffType.VALUE, additionalProperties=EntityMapping( # casting here is safe as swagger specs are assumed to be valid and bool or dict are the only possible types old=typing.cast(typing.Union[bool, typing.Mapping[typing.Text, typing.Any]], left_additional_properties), new=typing.cast(typing.Union[bool, typing.Mapping[typing.Text, typing.Any]], right_additional_properties), ), properties=None, )) if (left_additional_properties is False or right_additional_properties is False) and properties_appear_once: result.append(AdditionalPropertiesDiff( path=path, diff_type=DiffType.PROPERTIES, additionalProperties=None, properties=EntityMapping( old=properties_appear_once.intersection(left_properties), new=properties_appear_once.intersection(right_properties), ), )) return result
[docs]class AdditionalPropertiesDifferWalker(SchemaWalker[AdditionalPropertiesDiff]): left_spec = None # type: Spec right_spec = None # type: Spec additionalPropertiesValue = None # type: typing.Union[bool, typing.Mapping[typing.Text, typing.Any]] diffs = None # type: typing.List[AdditionalPropertiesDiff]
[docs] def dict_check( self, path, # type: PathType left_dict, # type: typing.Union[NoValue, typing.Mapping[typing.Text, typing.Any]] right_dict, # type: typing.Union[NoValue, typing.Mapping[typing.Text, typing.Any]] ): # type: (...) -> typing.Iterable[AdditionalPropertiesDiff] return _evaluate_additional_properties_diffs( path=path, left_spec=self.left_spec, right_spec=self.right_spec, left_schema=None if isinstance(left_dict, NoValue) else left_dict, right_schema=None if isinstance(right_dict, NoValue) else right_dict, )
[docs] def list_check( self, path, # type: PathType left_list, # type: typing.Union[NoValue, typing.Sequence[typing.Any]] right_list, # type: typing.Union[NoValue, typing.Sequence[typing.Any]] ): # type: (...) -> typing.Iterable[AdditionalPropertiesDiff] return ()
[docs] def value_check( self, path, # type: PathType left_value, # type: typing.Any right_value, # type: typing.Any ): # type: (...) -> typing.Iterable[AdditionalPropertiesDiff] return ()