[python-experimental] simplifies type checking (#13437)

* Better control of when to write MetaOapg

* Makes MetaOapg in Schema a type hint rather than assignmnet

* Samples regenerated

* Adds tuple types

* Removes types info

* Adds _types

* Samples regenerated

* Adds missing mixins, samples regenerated

* SchemaTypeChecker removed

* Samples regnerated
This commit is contained in:
Justin Black 2022-09-15 17:17:39 -07:00 committed by GitHub
parent 3177277b52
commit 048af8eeae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
222 changed files with 888 additions and 639 deletions

View File

@ -25,6 +25,7 @@ def discriminator(cls):
{{/with}} {{/with}}
{{/if}} {{/if}}
{{#if vars}} {{#if vars}}
class properties: class properties:
{{#each vars}} {{#each vars}}
{{#if complexType}} {{#if complexType}}

View File

@ -0,0 +1,11 @@
{{#with items}}
{{#if complexType}}
@classmethod
@property
def {{baseName}}(cls) -> typing.Type['{{complexType}}']:
return {{complexType}}
{{else}}
{{> model_templates/schema }}
{{/if}}
{{/with}}

View File

@ -11,9 +11,6 @@ class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}
schemas.AnyTypeSchema, schemas.AnyTypeSchema,
{{/if}} {{/if}}
{{else}} {{else}}
{{#if getHasMultipleTypes}}
schemas.SchemaTypeCheckerClsFactory(typing.Union[{{#if isNull}}schemas.NoneClass, {{/if}}{{#if isMap}}frozendict.frozendict, {{/if}}{{#if isArray}}tuple, {{/if}}{{#if isString }}str, {{/if}}{{#or isInteger isNumber}}decimal.Decimal, {{/or}}{{#if isBoolean}}schemas.BoolClass, {{/if}}]),
{{/if}}
{{#if composedSchemas}} {{#if composedSchemas}}
schemas.ComposedBase, schemas.ComposedBase,
{{/if}} {{/if}}
@ -41,17 +38,9 @@ class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}
{{#if getFormat}} {{#if getFormat}}
format = '{{getFormat}}' format = '{{getFormat}}'
{{/if}} {{/if}}
{{#with items}} {{#if getItems}}
{{#if complexType}} {{> model_templates/list_partial }}
@classmethod
@property
def {{baseName}}(cls) -> typing.Type['{{complexType}}']:
return {{complexType}}
{{else}}
{{> model_templates/schema }}
{{/if}} {{/if}}
{{/with}}
{{#or additionalProperties getRequiredVarsMap getHasDiscriminatorWithNonEmptyMapping vars}} {{#or additionalProperties getRequiredVarsMap getHasDiscriminatorWithNonEmptyMapping vars}}
{{> model_templates/dict_partial }} {{> model_templates/dict_partial }}
{{/or}} {{/or}}

View File

@ -14,13 +14,22 @@ class {{> model_templates/classname }}(
{{/if}} {{/if}}
""" """
{{/if}} {{/if}}
{{#if isStub}}
{{#or additionalProperties getRequiredVarsMap getHasDiscriminatorWithNonEmptyMapping vars}}
class MetaOapg:
{{> model_templates/dict_partial }}
{{/or}}
{{else}}
{{#or additionalProperties getRequiredVarsMap getHasDiscriminatorWithNonEmptyMapping vars hasValidation}}
class MetaOapg: class MetaOapg:
{{> model_templates/dict_partial }} {{> model_templates/dict_partial }}
{{#unless isStub}}
{{> model_templates/validations }} {{> model_templates/validations }}
{{/unless}} {{/or}}
{{/if}}
{{> model_templates/property_type_hints }} {{> model_templates/property_type_hints }}
{{> model_templates/new }} {{> model_templates/new }}

View File

@ -14,23 +14,24 @@ class {{> model_templates/classname }}(
{{/if}} {{/if}}
""" """
{{/if}} {{/if}}
{{#if isStub}}
{{#if items}}
class MetaOapg: class MetaOapg:
{{#unless isStub}} {{> model_templates/list_partial }}
{{> model_templates/validations }} {{/if}}
{{/unless}} {{else}}
{{#with items}} {{#or getItems hasValidation}}
{{#if complexType}}
@classmethod class MetaOapg:
@property {{#if hasValidation}}
def {{baseName}}(cls) -> typing.Type['{{complexType}}']: {{> model_templates/validations }}
return {{complexType}} {{/if}}
{{else}} {{> model_templates/list_partial }}
{{> model_templates/schema }} {{/or}}
{{/if}} {{/if}}
{{/with}}
{{> model_templates/new }} {{> model_templates/new }}

View File

@ -236,8 +236,60 @@ class Schema:
the base class of all swagger/openapi schemas/models the base class of all swagger/openapi schemas/models
""" """
__inheritable_primitive_types_set = {decimal.Decimal, str, tuple, frozendict.frozendict, FileIO, bytes, BoolClass, NoneClass} __inheritable_primitive_types_set = {decimal.Decimal, str, tuple, frozendict.frozendict, FileIO, bytes, BoolClass, NoneClass}
_types: typing.Set[typing.Type]
MetaOapg = MetaOapgTyped MetaOapg = MetaOapgTyped
@staticmethod
def __get_valid_classes_phrase(input_classes):
"""Returns a string phrase describing what types are allowed"""
all_classes = list(input_classes)
all_classes = sorted(all_classes, key=lambda cls: cls.__name__)
all_class_names = [cls.__name__ for cls in all_classes]
if len(all_class_names) == 1:
return "is {0}".format(all_class_names[0])
return "is one of [{0}]".format(", ".join(all_class_names))
@classmethod
def __type_error_message(
cls, var_value=None, var_name=None, valid_classes=None, key_type=None
):
"""
Keyword Args:
var_value (any): the variable which has the type_error
var_name (str): the name of the variable which has the typ error
valid_classes (tuple): the accepted classes for current_item's
value
key_type (bool): False if our value is a value in a dict
True if it is a key in a dict
False if our item is an item in a tuple
"""
key_or_value = "value"
if key_type:
key_or_value = "key"
valid_classes_phrase = cls.__get_valid_classes_phrase(valid_classes)
msg = "Invalid type. Required {1} type {2} and " "passed type was {3}".format(
var_name,
key_or_value,
valid_classes_phrase,
type(var_value).__name__,
)
return msg
@classmethod
def __get_type_error(cls, var_value, path_to_item, valid_classes, key_type=False):
error_msg = cls.__type_error_message(
var_name=path_to_item[-1],
var_value=var_value,
valid_classes=valid_classes,
key_type=key_type,
)
return ApiTypeError(
error_msg,
path_to_item=path_to_item,
valid_classes=valid_classes,
key_type=key_type,
)
@classmethod @classmethod
def _validate_oapg( def _validate_oapg(
cls, cls,
@ -246,21 +298,8 @@ class Schema:
) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]: ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
""" """
Schema _validate_oapg Schema _validate_oapg
Runs all schema validation logic and All keyword validation except for type checking was done in calling stack frames
returns a dynamic class of different bases depending upon the input If those validations passed, the validated classes are collected in path_to_schemas
This makes it so:
- the returned instance is always a subclass of our defining schema
- this allows us to check type based on whether an instance is a subclass of a schema
- the returned instance is a serializable type (except for None, True, and False) which are enums
Use cases:
1. inheritable type: string/decimal.Decimal/frozendict.frozendict/tuple
2. singletons: bool/None -> uses the base classes BoolClass/NoneClass
Required Steps:
1. verify type of input is valid vs the allowed _types
2. check validations that are applicable for this type of input
3. if enums exist, check that the value exists in the enum
Returns: Returns:
path_to_schemas: a map of path to schemas path_to_schemas: a map of path to schemas
@ -270,6 +309,14 @@ class Schema:
ApiTypeError: when the input type is not in the list of allowed spec types ApiTypeError: when the input type is not in the list of allowed spec types
""" """
base_class = type(arg) base_class = type(arg)
if base_class not in cls._types:
raise cls.__get_type_error(
arg,
validation_metadata.path_to_item,
cls._types,
key_type=False,
)
path_to_schemas = {validation_metadata.path_to_item: set()} path_to_schemas = {validation_metadata.path_to_item: set()}
path_to_schemas[validation_metadata.path_to_item].add(cls) path_to_schemas[validation_metadata.path_to_item].add(cls)
path_to_schemas[validation_metadata.path_to_item].add(base_class) path_to_schemas[validation_metadata.path_to_item].add(base_class)
@ -508,6 +555,8 @@ if typing.TYPE_CHECKING:
StrMixin = str StrMixin = str
DecimalMixin = decimal.Decimal DecimalMixin = decimal.Decimal
BoolMixin = BoolClass BoolMixin = BoolClass
BytesMixin = bytes
FileMixin = FileIO
# qty 2 # qty 2
class BinaryMixin(bytes, FileIO): class BinaryMixin(bytes, FileIO):
pass pass
@ -629,77 +678,151 @@ if typing.TYPE_CHECKING:
# qty 6 # qty 6
class NoneFrozenDictTupleStrDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass): class NoneFrozenDictTupleStrDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass):
pass pass
# qty 8
class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes):
pass
else: else:
# qty 1 # qty 1
NoneMixin = object class NoneMixin:
FrozenDictMixin = object _types = {NoneClass}
TupleMixin = object class FrozenDictMixin:
StrMixin = object _types = {frozendict.frozendict}
DecimalMixin = object class TupleMixin:
BoolMixin = object _types = {tuple}
class StrMixin:
_types = {str}
class DecimalMixin:
_types = {decimal.Decimal}
class BoolMixin:
_types = {BoolClass}
class BytesMixin:
_types = {bytes}
class FileMixin:
_types = {FileIO}
# qty 2 # qty 2
BinaryMixin = object class BinaryMixin:
NoneFrozenDictMixin = object _types = {bytes, FileIO}
NoneTupleMixin = object class NoneFrozenDictMixin:
NoneStrMixin = object _types = {NoneClass, frozendict.frozendict}
NoneDecimalMixin = object class NoneTupleMixin:
NoneBoolMixin = object _types = {NoneClass, tuple}
FrozenDictTupleMixin = object class NoneStrMixin:
FrozenDictStrMixin = object _types = {NoneClass, str}
FrozenDictDecimalMixin = object class NoneDecimalMixin:
FrozenDictBoolMixin = object _types = {NoneClass, decimal.Decimal}
TupleStrMixin = object class NoneBoolMixin:
TupleDecimalMixin = object _types = {NoneClass, BoolClass}
TupleBoolMixin = object class FrozenDictTupleMixin:
StrDecimalMixin = object _types = {frozendict.frozendict, tuple}
StrBoolMixin = object class FrozenDictStrMixin:
DecimalBoolMixin = object _types = {frozendict.frozendict, str}
class FrozenDictDecimalMixin:
_types = {frozendict.frozendict, decimal.Decimal}
class FrozenDictBoolMixin:
_types = {frozendict.frozendict, BoolClass}
class TupleStrMixin:
_types = {tuple, str}
class TupleDecimalMixin:
_types = {tuple, decimal.Decimal}
class TupleBoolMixin:
_types = {tuple, BoolClass}
class StrDecimalMixin:
_types = {str, decimal.Decimal}
class StrBoolMixin:
_types = {str, BoolClass}
class DecimalBoolMixin:
_types = {decimal.Decimal, BoolClass}
# qty 3 # qty 3
NoneFrozenDictTupleMixin = object class NoneFrozenDictTupleMixin:
NoneFrozenDictStrMixin = object _types = {NoneClass, frozendict.frozendict, tuple}
NoneFrozenDictDecimalMixin = object class NoneFrozenDictStrMixin:
NoneFrozenDictBoolMixin = object _types = {NoneClass, frozendict.frozendict, str}
NoneTupleStrMixin = object class NoneFrozenDictDecimalMixin:
NoneTupleDecimalMixin = object _types = {NoneClass, frozendict.frozendict, decimal.Decimal}
NoneTupleBoolMixin = object class NoneFrozenDictBoolMixin:
NoneStrDecimalMixin = object _types = {NoneClass, frozendict.frozendict, BoolClass}
NoneStrBoolMixin = object class NoneTupleStrMixin:
NoneDecimalBoolMixin = object _types = {NoneClass, tuple, str}
FrozenDictTupleStrMixin = object class NoneTupleDecimalMixin:
FrozenDictTupleDecimalMixin = object _types = {NoneClass, tuple, decimal.Decimal}
FrozenDictTupleBoolMixin = object class NoneTupleBoolMixin:
FrozenDictStrDecimalMixin = object _types = {NoneClass, tuple, BoolClass}
FrozenDictStrBoolMixin = object class NoneStrDecimalMixin:
FrozenDictDecimalBoolMixin = object _types = {NoneClass, str, decimal.Decimal}
TupleStrDecimalMixin = object class NoneStrBoolMixin:
TupleStrBoolMixin = object _types = {NoneClass, str, BoolClass}
TupleDecimalBoolMixin = object class NoneDecimalBoolMixin:
StrDecimalBoolMixin = object _types = {NoneClass, decimal.Decimal, BoolClass}
class FrozenDictTupleStrMixin:
_types = {frozendict.frozendict, tuple, str}
class FrozenDictTupleDecimalMixin:
_types = {frozendict.frozendict, tuple, decimal.Decimal}
class FrozenDictTupleBoolMixin:
_types = {frozendict.frozendict, tuple, BoolClass}
class FrozenDictStrDecimalMixin:
_types = {frozendict.frozendict, str, decimal.Decimal}
class FrozenDictStrBoolMixin:
_types = {frozendict.frozendict, str, BoolClass}
class FrozenDictDecimalBoolMixin:
_types = {frozendict.frozendict, decimal.Decimal, BoolClass}
class TupleStrDecimalMixin:
_types = {tuple, str, decimal.Decimal}
class TupleStrBoolMixin:
_types = {tuple, str, BoolClass}
class TupleDecimalBoolMixin:
_types = {tuple, decimal.Decimal, BoolClass}
class StrDecimalBoolMixin:
_types = {str, decimal.Decimal, BoolClass}
# qty 4 # qty 4
NoneFrozenDictTupleStrMixin = object class NoneFrozenDictTupleStrMixin:
NoneFrozenDictTupleDecimalMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str}
NoneFrozenDictTupleBoolMixin = object class NoneFrozenDictTupleDecimalMixin:
NoneFrozenDictStrDecimalMixin = object _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal}
NoneFrozenDictStrBoolMixin = object class NoneFrozenDictTupleBoolMixin:
NoneFrozenDictDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, BoolClass}
NoneTupleStrDecimalMixin = object class NoneFrozenDictStrDecimalMixin:
NoneTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, str, decimal.Decimal}
NoneTupleDecimalBoolMixin = object class NoneFrozenDictStrBoolMixin:
NoneStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, str, BoolClass}
FrozenDictTupleStrDecimalMixin = object class NoneFrozenDictDecimalBoolMixin:
FrozenDictTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, decimal.Decimal, BoolClass}
FrozenDictTupleDecimalBoolMixin = object class NoneTupleStrDecimalMixin:
FrozenDictStrDecimalBoolMixin = object _types = {NoneClass, tuple, str, decimal.Decimal}
TupleStrDecimalBoolMixin = object class NoneTupleStrBoolMixin:
_types = {NoneClass, tuple, str, BoolClass}
class NoneTupleDecimalBoolMixin:
_types = {NoneClass, tuple, decimal.Decimal, BoolClass}
class NoneStrDecimalBoolMixin:
_types = {NoneClass, str, decimal.Decimal, BoolClass}
class FrozenDictTupleStrDecimalMixin:
_types = {frozendict.frozendict, tuple, str, decimal.Decimal}
class FrozenDictTupleStrBoolMixin:
_types = {frozendict.frozendict, tuple, str, BoolClass}
class FrozenDictTupleDecimalBoolMixin:
_types = {frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
class FrozenDictStrDecimalBoolMixin:
_types = {frozendict.frozendict, str, decimal.Decimal, BoolClass}
class TupleStrDecimalBoolMixin:
_types = {tuple, str, decimal.Decimal, BoolClass}
# qty 5 # qty 5
NoneFrozenDictTupleStrDecimalMixin = object class NoneFrozenDictTupleStrDecimalMixin:
NoneFrozenDictTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal}
NoneFrozenDictTupleDecimalBoolMixin = object class NoneFrozenDictTupleStrBoolMixin:
NoneFrozenDictStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str, BoolClass}
NoneTupleStrDecimalBoolMixin = object class NoneFrozenDictTupleDecimalBoolMixin:
FrozenDictTupleStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
class NoneFrozenDictStrDecimalBoolMixin:
_types = {NoneClass, frozendict.frozendict, str, decimal.Decimal, BoolClass}
class NoneTupleStrDecimalBoolMixin:
_types = {NoneClass, tuple, str, decimal.Decimal, BoolClass}
class FrozenDictTupleStrDecimalBoolMixin:
_types = {frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
# qty 6 # qty 6
NoneFrozenDictTupleStrDecimalBoolMixin = object class NoneFrozenDictTupleStrDecimalBoolMixin:
_types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
# qty 8
class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin:
_types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes}
class ValidatorBase: class ValidatorBase:
@ -743,92 +866,6 @@ class Validator(typing.Protocol):
pass pass
def SchemaTypeCheckerClsFactory(union_type_cls: typing.Any) -> Validator:
if typing.get_origin(union_type_cls) is typing.Union:
union_classes = typing.get_args(union_type_cls)
else:
# note: when a union of a single class is passed in, the union disappears
union_classes = tuple([union_type_cls])
"""
I want the type hint... union_type_cls
and to use it as a base class but when I do, I get
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
"""
class SchemaTypeChecker:
@staticmethod
def __get_valid_classes_phrase(input_classes):
"""Returns a string phrase describing what types are allowed"""
all_classes = list(input_classes)
all_classes = sorted(all_classes, key=lambda cls: cls.__name__)
all_class_names = [cls.__name__ for cls in all_classes]
if len(all_class_names) == 1:
return "is {0}".format(all_class_names[0])
return "is one of [{0}]".format(", ".join(all_class_names))
@classmethod
def __type_error_message(
cls, var_value=None, var_name=None, valid_classes=None, key_type=None
):
"""
Keyword Args:
var_value (any): the variable which has the type_error
var_name (str): the name of the variable which has the typ error
valid_classes (tuple): the accepted classes for current_item's
value
key_type (bool): False if our value is a value in a dict
True if it is a key in a dict
False if our item is an item in a tuple
"""
key_or_value = "value"
if key_type:
key_or_value = "key"
valid_classes_phrase = cls.__get_valid_classes_phrase(valid_classes)
msg = "Invalid type. Required {1} type {2} and " "passed type was {3}".format(
var_name,
key_or_value,
valid_classes_phrase,
type(var_value).__name__,
)
return msg
@classmethod
def __get_type_error(cls, var_value, path_to_item, valid_classes, key_type=False):
error_msg = cls.__type_error_message(
var_name=path_to_item[-1],
var_value=var_value,
valid_classes=valid_classes,
key_type=key_type,
)
return ApiTypeError(
error_msg,
path_to_item=path_to_item,
valid_classes=valid_classes,
key_type=key_type,
)
@classmethod
def _validate_oapg(
cls,
arg,
validation_metadata: ValidationMetadata,
) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
"""
SchemaTypeChecker _validate_oapg
Validates arg's type
"""
arg_type = type(arg)
if arg_type in union_classes:
return super()._validate_oapg(arg, validation_metadata=validation_metadata)
raise cls.__get_type_error(
arg,
validation_metadata.path_to_item,
union_classes,
key_type=False,
)
return SchemaTypeChecker
class EnumMakerBase: class EnumMakerBase:
pass pass
@ -1989,7 +2026,6 @@ class ComposedBase(Discriminable):
# DictBase, ListBase, NumberBase, StrBase, BoolBase, NoneBase # DictBase, ListBase, NumberBase, StrBase, BoolBase, NoneBase
class ComposedSchema( class ComposedSchema(
SchemaTypeCheckerClsFactory(typing.Union[NoneClass, str, decimal.Decimal, BoolClass, tuple, frozendict.frozendict]),
ComposedBase, ComposedBase,
DictBase, DictBase,
ListBase, ListBase,
@ -2010,7 +2046,6 @@ class ComposedSchema(
class ListSchema( class ListSchema(
SchemaTypeCheckerClsFactory(tuple),
ListBase, ListBase,
Schema, Schema,
TupleMixin TupleMixin
@ -2025,7 +2060,6 @@ class ListSchema(
class NoneSchema( class NoneSchema(
SchemaTypeCheckerClsFactory(NoneClass),
NoneBase, NoneBase,
Schema, Schema,
NoneMixin NoneMixin
@ -2040,7 +2074,6 @@ class NoneSchema(
class NumberSchema( class NumberSchema(
SchemaTypeCheckerClsFactory(decimal.Decimal),
NumberBase, NumberBase,
Schema, Schema,
DecimalMixin DecimalMixin
@ -2236,7 +2269,6 @@ class Float64Schema(
class StrSchema( class StrSchema(
SchemaTypeCheckerClsFactory(str),
StrBase, StrBase,
Schema, Schema,
StrMixin StrMixin
@ -2289,8 +2321,8 @@ class DecimalSchema(DecimalBase, StrSchema):
class BytesSchema( class BytesSchema(
SchemaTypeCheckerClsFactory(bytes),
Schema, Schema,
BytesMixin
): ):
""" """
this class will subclass bytes and is immutable this class will subclass bytes and is immutable
@ -2300,8 +2332,8 @@ class BytesSchema(
class FileSchema( class FileSchema(
SchemaTypeCheckerClsFactory(FileIO),
Schema, Schema,
FileMixin
): ):
""" """
This class is NOT immutable This class is NOT immutable
@ -2329,7 +2361,6 @@ class BinaryBase:
class BinarySchema( class BinarySchema(
SchemaTypeCheckerClsFactory(typing.Union[bytes, FileIO]),
ComposedBase, ComposedBase,
BinaryBase, BinaryBase,
Schema, Schema,
@ -2346,7 +2377,6 @@ class BinarySchema(
class BoolSchema( class BoolSchema(
SchemaTypeCheckerClsFactory(BoolClass),
BoolBase, BoolBase,
Schema, Schema,
BoolMixin BoolMixin
@ -2361,9 +2391,6 @@ class BoolSchema(
class AnyTypeSchema( class AnyTypeSchema(
SchemaTypeCheckerClsFactory(
typing.Union[frozendict.frozendict, tuple, decimal.Decimal, str, BoolClass, NoneClass, bytes, FileIO]
),
DictBase, DictBase,
ListBase, ListBase,
NumberBase, NumberBase,
@ -2371,7 +2398,7 @@ class AnyTypeSchema(
BoolBase, BoolBase,
NoneBase, NoneBase,
Schema, Schema,
NoneFrozenDictTupleStrDecimalBoolMixin NoneFrozenDictTupleStrDecimalBoolFileBytesMixin
): ):
# Python representation of a schema defined as true or {} # Python representation of a schema defined as true or {}
pass pass
@ -2407,7 +2434,6 @@ class NotAnyTypeSchema(
class DictSchema( class DictSchema(
SchemaTypeCheckerClsFactory(frozendict.frozendict),
DictBase, DictBase,
Schema, Schema,
FrozenDictMixin FrozenDictMixin

View File

@ -33,6 +33,7 @@ class AdditionalpropertiesAllowsASchemaWhichShouldValidate(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -33,6 +33,7 @@ class AdditionalpropertiesAllowsASchemaWhichShouldValidate(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -33,6 +33,7 @@ class AdditionalpropertiesAreAllowedByDefault(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -33,6 +33,7 @@ class AdditionalpropertiesAreAllowedByDefault(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -42,6 +42,7 @@ class AdditionalpropertiesShouldNotLookInApplicators(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -42,6 +42,7 @@ class AdditionalpropertiesShouldNotLookInApplicators(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -44,6 +44,7 @@ class Allof(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class Allof(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -44,6 +44,7 @@ class Allof(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class Allof(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class AllofWithBaseSchema(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -52,6 +53,7 @@ class AllofWithBaseSchema(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {
@ -107,6 +109,7 @@ class AllofWithBaseSchema(
required = { required = {
"baz", "baz",
} }
class properties: class properties:
baz = schemas.NoneSchema baz = schemas.NoneSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class AllofWithBaseSchema(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -52,6 +53,7 @@ class AllofWithBaseSchema(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {
@ -107,6 +109,7 @@ class AllofWithBaseSchema(
required = { required = {
"baz", "baz",
} }
class properties: class properties:
baz = schemas.NoneSchema baz = schemas.NoneSchema
__annotations__ = { __annotations__ = {

View File

@ -44,6 +44,7 @@ class AnyofComplexTypes(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class AnyofComplexTypes(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -44,6 +44,7 @@ class AnyofComplexTypes(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class AnyofComplexTypes(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class EnumsInProperties(
required = { required = {
"bar", "bar",
} }
class properties: class properties:

View File

@ -36,6 +36,7 @@ class EnumsInProperties(
required = { required = {
"bar", "bar",
} }
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ForbiddenProperty(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.NotAnyTypeSchema foo = schemas.NotAnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class ForbiddenProperty(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.NotAnyTypeSchema foo = schemas.NotAnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class InvalidStringValueForDefault(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class InvalidStringValueForDefault(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -41,6 +41,7 @@ class NotMoreComplexSchema(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class NotMoreComplexSchema(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class ObjectPropertiesValidation(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.IntSchema foo = schemas.IntSchema
bar = schemas.StrSchema bar = schemas.StrSchema

View File

@ -33,6 +33,7 @@ class ObjectPropertiesValidation(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.IntSchema foo = schemas.IntSchema
bar = schemas.StrSchema bar = schemas.StrSchema

View File

@ -44,6 +44,7 @@ class OneofComplexTypes(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class OneofComplexTypes(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -44,6 +44,7 @@ class OneofComplexTypes(
required = { required = {
"bar", "bar",
} }
class properties: class properties:
bar = schemas.IntSchema bar = schemas.IntSchema
__annotations__ = { __annotations__ = {
@ -99,6 +100,7 @@ class OneofComplexTypes(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class PropertiesWithEscapedCharacters(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo_nbar = schemas.NumberSchema foo_nbar = schemas.NumberSchema
foo_bar = schemas.NumberSchema foo_bar = schemas.NumberSchema

View File

@ -33,6 +33,7 @@ class PropertiesWithEscapedCharacters(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo_nbar = schemas.NumberSchema foo_nbar = schemas.NumberSchema
foo_bar = schemas.NumberSchema foo_bar = schemas.NumberSchema

View File

@ -33,6 +33,7 @@ class PropertyNamedRefThatIsNotAReference(
class MetaOapg: class MetaOapg:
class properties: class properties:
ref = schemas.StrSchema ref = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class PropertyNamedRefThatIsNotAReference(
class MetaOapg: class MetaOapg:
class properties: class properties:
ref = schemas.StrSchema ref = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class RefInProperty(
class MetaOapg: class MetaOapg:
class properties: class properties:
@classmethod @classmethod

View File

@ -33,6 +33,7 @@ class RefInProperty(
class MetaOapg: class MetaOapg:
class properties: class properties:
@classmethod @classmethod

View File

@ -33,6 +33,7 @@ class RequiredDefaultValidation(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class RequiredDefaultValidation(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class RequiredValidation(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -36,6 +36,7 @@ class RequiredValidation(
required = { required = {
"foo", "foo",
} }
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
bar = schemas.AnyTypeSchema bar = schemas.AnyTypeSchema

View File

@ -33,6 +33,7 @@ class RequiredWithEmptyArray(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class RequiredWithEmptyArray(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.AnyTypeSchema foo = schemas.AnyTypeSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class TheDefaultKeywordDoesNotDoAnythingIfThePropertyIsMissing(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class TheDefaultKeywordDoesNotDoAnythingIfThePropertyIsMissing(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -42,6 +42,7 @@ class SchemaForRequestBodyApplicationJson(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -40,6 +40,7 @@ class SchemaForRequestBodyApplicationJson(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class SchemaFor200ResponseBodyApplicationJson(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -39,6 +39,7 @@ class SchemaFor200ResponseBodyApplicationJson(
class MetaOapg: class MetaOapg:
class properties: class properties:
foo = schemas.StrSchema foo = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -243,8 +243,60 @@ class Schema:
the base class of all swagger/openapi schemas/models the base class of all swagger/openapi schemas/models
""" """
__inheritable_primitive_types_set = {decimal.Decimal, str, tuple, frozendict.frozendict, FileIO, bytes, BoolClass, NoneClass} __inheritable_primitive_types_set = {decimal.Decimal, str, tuple, frozendict.frozendict, FileIO, bytes, BoolClass, NoneClass}
_types: typing.Set[typing.Type]
MetaOapg = MetaOapgTyped MetaOapg = MetaOapgTyped
@staticmethod
def __get_valid_classes_phrase(input_classes):
"""Returns a string phrase describing what types are allowed"""
all_classes = list(input_classes)
all_classes = sorted(all_classes, key=lambda cls: cls.__name__)
all_class_names = [cls.__name__ for cls in all_classes]
if len(all_class_names) == 1:
return "is {0}".format(all_class_names[0])
return "is one of [{0}]".format(", ".join(all_class_names))
@classmethod
def __type_error_message(
cls, var_value=None, var_name=None, valid_classes=None, key_type=None
):
"""
Keyword Args:
var_value (any): the variable which has the type_error
var_name (str): the name of the variable which has the typ error
valid_classes (tuple): the accepted classes for current_item's
value
key_type (bool): False if our value is a value in a dict
True if it is a key in a dict
False if our item is an item in a tuple
"""
key_or_value = "value"
if key_type:
key_or_value = "key"
valid_classes_phrase = cls.__get_valid_classes_phrase(valid_classes)
msg = "Invalid type. Required {1} type {2} and " "passed type was {3}".format(
var_name,
key_or_value,
valid_classes_phrase,
type(var_value).__name__,
)
return msg
@classmethod
def __get_type_error(cls, var_value, path_to_item, valid_classes, key_type=False):
error_msg = cls.__type_error_message(
var_name=path_to_item[-1],
var_value=var_value,
valid_classes=valid_classes,
key_type=key_type,
)
return ApiTypeError(
error_msg,
path_to_item=path_to_item,
valid_classes=valid_classes,
key_type=key_type,
)
@classmethod @classmethod
def _validate_oapg( def _validate_oapg(
cls, cls,
@ -253,21 +305,8 @@ class Schema:
) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]: ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
""" """
Schema _validate_oapg Schema _validate_oapg
Runs all schema validation logic and All keyword validation except for type checking was done in calling stack frames
returns a dynamic class of different bases depending upon the input If those validations passed, the validated classes are collected in path_to_schemas
This makes it so:
- the returned instance is always a subclass of our defining schema
- this allows us to check type based on whether an instance is a subclass of a schema
- the returned instance is a serializable type (except for None, True, and False) which are enums
Use cases:
1. inheritable type: string/decimal.Decimal/frozendict.frozendict/tuple
2. singletons: bool/None -> uses the base classes BoolClass/NoneClass
Required Steps:
1. verify type of input is valid vs the allowed _types
2. check validations that are applicable for this type of input
3. if enums exist, check that the value exists in the enum
Returns: Returns:
path_to_schemas: a map of path to schemas path_to_schemas: a map of path to schemas
@ -277,6 +316,14 @@ class Schema:
ApiTypeError: when the input type is not in the list of allowed spec types ApiTypeError: when the input type is not in the list of allowed spec types
""" """
base_class = type(arg) base_class = type(arg)
if base_class not in cls._types:
raise cls.__get_type_error(
arg,
validation_metadata.path_to_item,
cls._types,
key_type=False,
)
path_to_schemas = {validation_metadata.path_to_item: set()} path_to_schemas = {validation_metadata.path_to_item: set()}
path_to_schemas[validation_metadata.path_to_item].add(cls) path_to_schemas[validation_metadata.path_to_item].add(cls)
path_to_schemas[validation_metadata.path_to_item].add(base_class) path_to_schemas[validation_metadata.path_to_item].add(base_class)
@ -515,6 +562,8 @@ if typing.TYPE_CHECKING:
StrMixin = str StrMixin = str
DecimalMixin = decimal.Decimal DecimalMixin = decimal.Decimal
BoolMixin = BoolClass BoolMixin = BoolClass
BytesMixin = bytes
FileMixin = FileIO
# qty 2 # qty 2
class BinaryMixin(bytes, FileIO): class BinaryMixin(bytes, FileIO):
pass pass
@ -636,77 +685,151 @@ if typing.TYPE_CHECKING:
# qty 6 # qty 6
class NoneFrozenDictTupleStrDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass): class NoneFrozenDictTupleStrDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass):
pass pass
# qty 8
class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes):
pass
else: else:
# qty 1 # qty 1
NoneMixin = object class NoneMixin:
FrozenDictMixin = object _types = {NoneClass}
TupleMixin = object class FrozenDictMixin:
StrMixin = object _types = {frozendict.frozendict}
DecimalMixin = object class TupleMixin:
BoolMixin = object _types = {tuple}
class StrMixin:
_types = {str}
class DecimalMixin:
_types = {decimal.Decimal}
class BoolMixin:
_types = {BoolClass}
class BytesMixin:
_types = {bytes}
class FileMixin:
_types = {FileIO}
# qty 2 # qty 2
BinaryMixin = object class BinaryMixin:
NoneFrozenDictMixin = object _types = {bytes, FileIO}
NoneTupleMixin = object class NoneFrozenDictMixin:
NoneStrMixin = object _types = {NoneClass, frozendict.frozendict}
NoneDecimalMixin = object class NoneTupleMixin:
NoneBoolMixin = object _types = {NoneClass, tuple}
FrozenDictTupleMixin = object class NoneStrMixin:
FrozenDictStrMixin = object _types = {NoneClass, str}
FrozenDictDecimalMixin = object class NoneDecimalMixin:
FrozenDictBoolMixin = object _types = {NoneClass, decimal.Decimal}
TupleStrMixin = object class NoneBoolMixin:
TupleDecimalMixin = object _types = {NoneClass, BoolClass}
TupleBoolMixin = object class FrozenDictTupleMixin:
StrDecimalMixin = object _types = {frozendict.frozendict, tuple}
StrBoolMixin = object class FrozenDictStrMixin:
DecimalBoolMixin = object _types = {frozendict.frozendict, str}
class FrozenDictDecimalMixin:
_types = {frozendict.frozendict, decimal.Decimal}
class FrozenDictBoolMixin:
_types = {frozendict.frozendict, BoolClass}
class TupleStrMixin:
_types = {tuple, str}
class TupleDecimalMixin:
_types = {tuple, decimal.Decimal}
class TupleBoolMixin:
_types = {tuple, BoolClass}
class StrDecimalMixin:
_types = {str, decimal.Decimal}
class StrBoolMixin:
_types = {str, BoolClass}
class DecimalBoolMixin:
_types = {decimal.Decimal, BoolClass}
# qty 3 # qty 3
NoneFrozenDictTupleMixin = object class NoneFrozenDictTupleMixin:
NoneFrozenDictStrMixin = object _types = {NoneClass, frozendict.frozendict, tuple}
NoneFrozenDictDecimalMixin = object class NoneFrozenDictStrMixin:
NoneFrozenDictBoolMixin = object _types = {NoneClass, frozendict.frozendict, str}
NoneTupleStrMixin = object class NoneFrozenDictDecimalMixin:
NoneTupleDecimalMixin = object _types = {NoneClass, frozendict.frozendict, decimal.Decimal}
NoneTupleBoolMixin = object class NoneFrozenDictBoolMixin:
NoneStrDecimalMixin = object _types = {NoneClass, frozendict.frozendict, BoolClass}
NoneStrBoolMixin = object class NoneTupleStrMixin:
NoneDecimalBoolMixin = object _types = {NoneClass, tuple, str}
FrozenDictTupleStrMixin = object class NoneTupleDecimalMixin:
FrozenDictTupleDecimalMixin = object _types = {NoneClass, tuple, decimal.Decimal}
FrozenDictTupleBoolMixin = object class NoneTupleBoolMixin:
FrozenDictStrDecimalMixin = object _types = {NoneClass, tuple, BoolClass}
FrozenDictStrBoolMixin = object class NoneStrDecimalMixin:
FrozenDictDecimalBoolMixin = object _types = {NoneClass, str, decimal.Decimal}
TupleStrDecimalMixin = object class NoneStrBoolMixin:
TupleStrBoolMixin = object _types = {NoneClass, str, BoolClass}
TupleDecimalBoolMixin = object class NoneDecimalBoolMixin:
StrDecimalBoolMixin = object _types = {NoneClass, decimal.Decimal, BoolClass}
class FrozenDictTupleStrMixin:
_types = {frozendict.frozendict, tuple, str}
class FrozenDictTupleDecimalMixin:
_types = {frozendict.frozendict, tuple, decimal.Decimal}
class FrozenDictTupleBoolMixin:
_types = {frozendict.frozendict, tuple, BoolClass}
class FrozenDictStrDecimalMixin:
_types = {frozendict.frozendict, str, decimal.Decimal}
class FrozenDictStrBoolMixin:
_types = {frozendict.frozendict, str, BoolClass}
class FrozenDictDecimalBoolMixin:
_types = {frozendict.frozendict, decimal.Decimal, BoolClass}
class TupleStrDecimalMixin:
_types = {tuple, str, decimal.Decimal}
class TupleStrBoolMixin:
_types = {tuple, str, BoolClass}
class TupleDecimalBoolMixin:
_types = {tuple, decimal.Decimal, BoolClass}
class StrDecimalBoolMixin:
_types = {str, decimal.Decimal, BoolClass}
# qty 4 # qty 4
NoneFrozenDictTupleStrMixin = object class NoneFrozenDictTupleStrMixin:
NoneFrozenDictTupleDecimalMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str}
NoneFrozenDictTupleBoolMixin = object class NoneFrozenDictTupleDecimalMixin:
NoneFrozenDictStrDecimalMixin = object _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal}
NoneFrozenDictStrBoolMixin = object class NoneFrozenDictTupleBoolMixin:
NoneFrozenDictDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, BoolClass}
NoneTupleStrDecimalMixin = object class NoneFrozenDictStrDecimalMixin:
NoneTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, str, decimal.Decimal}
NoneTupleDecimalBoolMixin = object class NoneFrozenDictStrBoolMixin:
NoneStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, str, BoolClass}
FrozenDictTupleStrDecimalMixin = object class NoneFrozenDictDecimalBoolMixin:
FrozenDictTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, decimal.Decimal, BoolClass}
FrozenDictTupleDecimalBoolMixin = object class NoneTupleStrDecimalMixin:
FrozenDictStrDecimalBoolMixin = object _types = {NoneClass, tuple, str, decimal.Decimal}
TupleStrDecimalBoolMixin = object class NoneTupleStrBoolMixin:
_types = {NoneClass, tuple, str, BoolClass}
class NoneTupleDecimalBoolMixin:
_types = {NoneClass, tuple, decimal.Decimal, BoolClass}
class NoneStrDecimalBoolMixin:
_types = {NoneClass, str, decimal.Decimal, BoolClass}
class FrozenDictTupleStrDecimalMixin:
_types = {frozendict.frozendict, tuple, str, decimal.Decimal}
class FrozenDictTupleStrBoolMixin:
_types = {frozendict.frozendict, tuple, str, BoolClass}
class FrozenDictTupleDecimalBoolMixin:
_types = {frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
class FrozenDictStrDecimalBoolMixin:
_types = {frozendict.frozendict, str, decimal.Decimal, BoolClass}
class TupleStrDecimalBoolMixin:
_types = {tuple, str, decimal.Decimal, BoolClass}
# qty 5 # qty 5
NoneFrozenDictTupleStrDecimalMixin = object class NoneFrozenDictTupleStrDecimalMixin:
NoneFrozenDictTupleStrBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal}
NoneFrozenDictTupleDecimalBoolMixin = object class NoneFrozenDictTupleStrBoolMixin:
NoneFrozenDictStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, str, BoolClass}
NoneTupleStrDecimalBoolMixin = object class NoneFrozenDictTupleDecimalBoolMixin:
FrozenDictTupleStrDecimalBoolMixin = object _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
class NoneFrozenDictStrDecimalBoolMixin:
_types = {NoneClass, frozendict.frozendict, str, decimal.Decimal, BoolClass}
class NoneTupleStrDecimalBoolMixin:
_types = {NoneClass, tuple, str, decimal.Decimal, BoolClass}
class FrozenDictTupleStrDecimalBoolMixin:
_types = {frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
# qty 6 # qty 6
NoneFrozenDictTupleStrDecimalBoolMixin = object class NoneFrozenDictTupleStrDecimalBoolMixin:
_types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
# qty 8
class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin:
_types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes}
class ValidatorBase: class ValidatorBase:
@ -750,92 +873,6 @@ class Validator(typing.Protocol):
pass pass
def SchemaTypeCheckerClsFactory(union_type_cls: typing.Any) -> Validator:
if typing.get_origin(union_type_cls) is typing.Union:
union_classes = typing.get_args(union_type_cls)
else:
# note: when a union of a single class is passed in, the union disappears
union_classes = tuple([union_type_cls])
"""
I want the type hint... union_type_cls
and to use it as a base class but when I do, I get
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
"""
class SchemaTypeChecker:
@staticmethod
def __get_valid_classes_phrase(input_classes):
"""Returns a string phrase describing what types are allowed"""
all_classes = list(input_classes)
all_classes = sorted(all_classes, key=lambda cls: cls.__name__)
all_class_names = [cls.__name__ for cls in all_classes]
if len(all_class_names) == 1:
return "is {0}".format(all_class_names[0])
return "is one of [{0}]".format(", ".join(all_class_names))
@classmethod
def __type_error_message(
cls, var_value=None, var_name=None, valid_classes=None, key_type=None
):
"""
Keyword Args:
var_value (any): the variable which has the type_error
var_name (str): the name of the variable which has the typ error
valid_classes (tuple): the accepted classes for current_item's
value
key_type (bool): False if our value is a value in a dict
True if it is a key in a dict
False if our item is an item in a tuple
"""
key_or_value = "value"
if key_type:
key_or_value = "key"
valid_classes_phrase = cls.__get_valid_classes_phrase(valid_classes)
msg = "Invalid type. Required {1} type {2} and " "passed type was {3}".format(
var_name,
key_or_value,
valid_classes_phrase,
type(var_value).__name__,
)
return msg
@classmethod
def __get_type_error(cls, var_value, path_to_item, valid_classes, key_type=False):
error_msg = cls.__type_error_message(
var_name=path_to_item[-1],
var_value=var_value,
valid_classes=valid_classes,
key_type=key_type,
)
return ApiTypeError(
error_msg,
path_to_item=path_to_item,
valid_classes=valid_classes,
key_type=key_type,
)
@classmethod
def _validate_oapg(
cls,
arg,
validation_metadata: ValidationMetadata,
) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
"""
SchemaTypeChecker _validate_oapg
Validates arg's type
"""
arg_type = type(arg)
if arg_type in union_classes:
return super()._validate_oapg(arg, validation_metadata=validation_metadata)
raise cls.__get_type_error(
arg,
validation_metadata.path_to_item,
union_classes,
key_type=False,
)
return SchemaTypeChecker
class EnumMakerBase: class EnumMakerBase:
pass pass
@ -1996,7 +2033,6 @@ class ComposedBase(Discriminable):
# DictBase, ListBase, NumberBase, StrBase, BoolBase, NoneBase # DictBase, ListBase, NumberBase, StrBase, BoolBase, NoneBase
class ComposedSchema( class ComposedSchema(
SchemaTypeCheckerClsFactory(typing.Union[NoneClass, str, decimal.Decimal, BoolClass, tuple, frozendict.frozendict]),
ComposedBase, ComposedBase,
DictBase, DictBase,
ListBase, ListBase,
@ -2017,7 +2053,6 @@ class ComposedSchema(
class ListSchema( class ListSchema(
SchemaTypeCheckerClsFactory(tuple),
ListBase, ListBase,
Schema, Schema,
TupleMixin TupleMixin
@ -2032,7 +2067,6 @@ class ListSchema(
class NoneSchema( class NoneSchema(
SchemaTypeCheckerClsFactory(NoneClass),
NoneBase, NoneBase,
Schema, Schema,
NoneMixin NoneMixin
@ -2047,7 +2081,6 @@ class NoneSchema(
class NumberSchema( class NumberSchema(
SchemaTypeCheckerClsFactory(decimal.Decimal),
NumberBase, NumberBase,
Schema, Schema,
DecimalMixin DecimalMixin
@ -2243,7 +2276,6 @@ class Float64Schema(
class StrSchema( class StrSchema(
SchemaTypeCheckerClsFactory(str),
StrBase, StrBase,
Schema, Schema,
StrMixin StrMixin
@ -2296,8 +2328,8 @@ class DecimalSchema(DecimalBase, StrSchema):
class BytesSchema( class BytesSchema(
SchemaTypeCheckerClsFactory(bytes),
Schema, Schema,
BytesMixin
): ):
""" """
this class will subclass bytes and is immutable this class will subclass bytes and is immutable
@ -2307,8 +2339,8 @@ class BytesSchema(
class FileSchema( class FileSchema(
SchemaTypeCheckerClsFactory(FileIO),
Schema, Schema,
FileMixin
): ):
""" """
This class is NOT immutable This class is NOT immutable
@ -2336,7 +2368,6 @@ class BinaryBase:
class BinarySchema( class BinarySchema(
SchemaTypeCheckerClsFactory(typing.Union[bytes, FileIO]),
ComposedBase, ComposedBase,
BinaryBase, BinaryBase,
Schema, Schema,
@ -2353,7 +2384,6 @@ class BinarySchema(
class BoolSchema( class BoolSchema(
SchemaTypeCheckerClsFactory(BoolClass),
BoolBase, BoolBase,
Schema, Schema,
BoolMixin BoolMixin
@ -2368,9 +2398,6 @@ class BoolSchema(
class AnyTypeSchema( class AnyTypeSchema(
SchemaTypeCheckerClsFactory(
typing.Union[frozendict.frozendict, tuple, decimal.Decimal, str, BoolClass, NoneClass, bytes, FileIO]
),
DictBase, DictBase,
ListBase, ListBase,
NumberBase, NumberBase,
@ -2378,7 +2405,7 @@ class AnyTypeSchema(
BoolBase, BoolBase,
NoneBase, NoneBase,
Schema, Schema,
NoneFrozenDictTupleStrDecimalBoolMixin NoneFrozenDictTupleStrDecimalBoolFileBytesMixin
): ):
# Python representation of a schema defined as true or {} # Python representation of a schema defined as true or {}
pass pass
@ -2414,7 +2441,6 @@ class NotAnyTypeSchema(
class DictSchema( class DictSchema(
SchemaTypeCheckerClsFactory(frozendict.frozendict),
DictBase, DictBase,
Schema, Schema,
FrozenDictMixin FrozenDictMixin

View File

@ -33,6 +33,7 @@ class AdditionalPropertiesClass(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class AdditionalPropertiesClass(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -46,6 +46,7 @@ class Animal(
'Dog': Dog, 'Dog': Dog,
} }
} }
class properties: class properties:
className = schemas.StrSchema className = schemas.StrSchema
color = schemas.StrSchema color = schemas.StrSchema

View File

@ -46,6 +46,7 @@ class Animal(
'Dog': Dog, 'Dog': Dog,
} }
} }
class properties: class properties:
className = schemas.StrSchema className = schemas.StrSchema
color = schemas.StrSchema color = schemas.StrSchema

View File

@ -33,6 +33,7 @@ class AnyTypeAndFormat(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class AnyTypeAndFormat(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ApiResponse(
class MetaOapg: class MetaOapg:
class properties: class properties:
code = schemas.Int32Schema code = schemas.Int32Schema
type = schemas.StrSchema type = schemas.StrSchema

View File

@ -33,6 +33,7 @@ class ApiResponse(
class MetaOapg: class MetaOapg:
class properties: class properties:
code = schemas.Int32Schema code = schemas.Int32Schema
type = schemas.StrSchema type = schemas.StrSchema

View File

@ -23,7 +23,6 @@ from petstore_api import schemas # noqa: F401
class Apple( class Apple(
schemas.SchemaTypeCheckerClsFactory(typing.Union[schemas.NoneClass, frozendict.frozendict, ]),
schemas.DictBase, schemas.DictBase,
schemas.NoneBase, schemas.NoneBase,
schemas.Schema, schemas.Schema,
@ -40,6 +39,7 @@ class Apple(
required = { required = {
"cultivar", "cultivar",
} }
class properties: class properties:

View File

@ -23,7 +23,6 @@ from petstore_api import schemas # noqa: F401
class Apple( class Apple(
schemas.SchemaTypeCheckerClsFactory(typing.Union[schemas.NoneClass, frozendict.frozendict, ]),
schemas.DictBase, schemas.DictBase,
schemas.NoneBase, schemas.NoneBase,
schemas.Schema, schemas.Schema,
@ -40,6 +39,7 @@ class Apple(
required = { required = {
"cultivar", "cultivar",
} }
class properties: class properties:

View File

@ -36,6 +36,7 @@ class AppleReq(
required = { required = {
"cultivar", "cultivar",
} }
class properties: class properties:
cultivar = schemas.StrSchema cultivar = schemas.StrSchema
mealy = schemas.BoolSchema mealy = schemas.BoolSchema

View File

@ -36,6 +36,7 @@ class AppleReq(
required = { required = {
"cultivar", "cultivar",
} }
class properties: class properties:
cultivar = schemas.StrSchema cultivar = schemas.StrSchema
mealy = schemas.BoolSchema mealy = schemas.BoolSchema

View File

@ -33,6 +33,7 @@ class ArrayOfArrayOfNumberOnly(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ArrayOfArrayOfNumberOnly(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ArrayOfNumberOnly(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ArrayOfNumberOnly(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ArrayTest(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class ArrayTest(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -36,6 +36,7 @@ class Banana(
required = { required = {
"lengthCm", "lengthCm",
} }
class properties: class properties:
lengthCm = schemas.NumberSchema lengthCm = schemas.NumberSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class Banana(
required = { required = {
"lengthCm", "lengthCm",
} }
class properties: class properties:
lengthCm = schemas.NumberSchema lengthCm = schemas.NumberSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class BananaReq(
required = { required = {
"lengthCm", "lengthCm",
} }
class properties: class properties:
lengthCm = schemas.NumberSchema lengthCm = schemas.NumberSchema
sweet = schemas.BoolSchema sweet = schemas.BoolSchema

View File

@ -36,6 +36,7 @@ class BananaReq(
required = { required = {
"lengthCm", "lengthCm",
} }
class properties: class properties:
lengthCm = schemas.NumberSchema lengthCm = schemas.NumberSchema
sweet = schemas.BoolSchema sweet = schemas.BoolSchema

View File

@ -36,6 +36,7 @@ class BasquePig(
required = { required = {
"className", "className",
} }
class properties: class properties:

View File

@ -36,6 +36,7 @@ class BasquePig(
required = { required = {
"className", "className",
} }
class properties: class properties:

View File

@ -33,6 +33,7 @@ class Capitalization(
class MetaOapg: class MetaOapg:
class properties: class properties:
smallCamel = schemas.StrSchema smallCamel = schemas.StrSchema
CapitalCamel = schemas.StrSchema CapitalCamel = schemas.StrSchema

View File

@ -33,6 +33,7 @@ class Capitalization(
class MetaOapg: class MetaOapg:
class properties: class properties:
smallCamel = schemas.StrSchema smallCamel = schemas.StrSchema
CapitalCamel = schemas.StrSchema CapitalCamel = schemas.StrSchema

View File

@ -41,6 +41,7 @@ class Cat(
class MetaOapg: class MetaOapg:
class properties: class properties:
declawed = schemas.BoolSchema declawed = schemas.BoolSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class Cat(
class MetaOapg: class MetaOapg:
class properties: class properties:
declawed = schemas.BoolSchema declawed = schemas.BoolSchema
__annotations__ = { __annotations__ = {

View File

@ -36,6 +36,7 @@ class Category(
required = { required = {
"name", "name",
} }
class properties: class properties:
name = schemas.StrSchema name = schemas.StrSchema
id = schemas.Int64Schema id = schemas.Int64Schema

View File

@ -36,6 +36,7 @@ class Category(
required = { required = {
"name", "name",
} }
class properties: class properties:
name = schemas.StrSchema name = schemas.StrSchema
id = schemas.Int64Schema id = schemas.Int64Schema

View File

@ -41,6 +41,7 @@ class ChildCat(
class MetaOapg: class MetaOapg:
class properties: class properties:
name = schemas.StrSchema name = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class ChildCat(
class MetaOapg: class MetaOapg:
class properties: class properties:
name = schemas.StrSchema name = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -35,6 +35,7 @@ class ClassModel(
class MetaOapg: class MetaOapg:
class properties: class properties:
_class = schemas.StrSchema _class = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -35,6 +35,7 @@ class ClassModel(
class MetaOapg: class MetaOapg:
class properties: class properties:
_class = schemas.StrSchema _class = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class Client(
class MetaOapg: class MetaOapg:
class properties: class properties:
client = schemas.StrSchema client = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class Client(
class MetaOapg: class MetaOapg:
class properties: class properties:
client = schemas.StrSchema client = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class ComplexQuadrilateral(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -41,6 +41,7 @@ class ComplexQuadrilateral(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -43,9 +43,6 @@ class ComposedOneOfDifferentTypes(
schemas.DictSchema schemas.DictSchema
): ):
class MetaOapg:
def __new__( def __new__(
cls, cls,
*args: typing.Union[dict, frozendict.frozendict, ], *args: typing.Union[dict, frozendict.frozendict, ],

View File

@ -36,6 +36,7 @@ class DanishPig(
required = { required = {
"className", "className",
} }
class properties: class properties:

View File

@ -36,6 +36,7 @@ class DanishPig(
required = { required = {
"className", "className",
} }
class properties: class properties:

View File

@ -41,6 +41,7 @@ class Dog(
class MetaOapg: class MetaOapg:
class properties: class properties:
breed = schemas.StrSchema breed = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -41,6 +41,7 @@ class Dog(
class MetaOapg: class MetaOapg:
class properties: class properties:
breed = schemas.StrSchema breed = schemas.StrSchema
__annotations__ = { __annotations__ = {

View File

@ -33,6 +33,7 @@ class Drawing(
class MetaOapg: class MetaOapg:
class properties: class properties:
@classmethod @classmethod

View File

@ -33,6 +33,7 @@ class Drawing(
class MetaOapg: class MetaOapg:
class properties: class properties:
@classmethod @classmethod

View File

@ -33,6 +33,7 @@ class EnumArrays(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -33,6 +33,7 @@ class EnumArrays(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -36,6 +36,7 @@ class EnumTest(
required = { required = {
"enum_string_required", "enum_string_required",
} }
class properties: class properties:

View File

@ -36,6 +36,7 @@ class EnumTest(
required = { required = {
"enum_string_required", "enum_string_required",
} }
class properties: class properties:

View File

@ -41,6 +41,7 @@ class EquilateralTriangle(
class MetaOapg: class MetaOapg:
class properties: class properties:

View File

@ -41,6 +41,7 @@ class EquilateralTriangle(
class MetaOapg: class MetaOapg:
class properties: class properties:

Some files were not shown because too many files have changed in this diff Show More