Merge remote-tracking branch 'origin' into 7.0.x

This commit is contained in:
William Cheng
2023-03-03 21:52:50 +08:00
10595 changed files with 418520 additions and 73194 deletions

View File

@@ -800,14 +800,14 @@ class MediaType:
@dataclass
class ApiResponse:
response: urllib3.HTTPResponse
body: typing.Union[Unset, Schema]
headers: typing.Union[Unset, typing.List[HeaderParameter]]
body: typing.Union[Unset, Schema] = unset
headers: typing.Union[Unset, typing.Dict[str, Schema]] = unset
def __init__(
self,
response: urllib3.HTTPResponse,
body: typing.Union[Unset, typing.Type[Schema]],
headers: typing.Union[Unset, typing.List[HeaderParameter]]
body: typing.Union[Unset, Schema] = unset,
headers: typing.Union[Unset, typing.Dict[str, Schema]] = unset
):
"""
pycharm needs this to prevent 'Unexpected argument' warnings
@@ -1389,24 +1389,24 @@ class RequestBody(StyleFormSerializer, JSONDetector):
def __multipart_json_item(self, key: str, value: Schema) -> RequestField:
json_value = self.__json_encoder.default(value)
return RequestField(name=key, data=json.dumps(json_value), headers={'Content-Type': 'application/json'})
request_field = RequestField(name=key, data=json.dumps(json_value))
request_field.make_multipart(content_type='application/json')
return request_field
def __multipart_form_item(self, key: str, value: Schema) -> RequestField:
if isinstance(value, str):
return RequestField(name=key, data=str(value), headers={'Content-Type': 'text/plain'})
request_field = RequestField(name=key, data=str(value))
request_field.make_multipart(content_type='text/plain')
elif isinstance(value, bytes):
return RequestField(name=key, data=value, headers={'Content-Type': 'application/octet-stream'})
request_field = RequestField(name=key, data=value)
request_field.make_multipart(content_type='application/octet-stream')
elif isinstance(value, FileIO):
request_field = RequestField(
name=key,
data=value.read(),
filename=os.path.basename(value.name),
headers={'Content-Type': 'application/octet-stream'}
)
# TODO use content.encoding to limit allowed content types if they are present
request_field = RequestField.from_tuples(key, (os.path.basename(value.name), value.read()))
value.close()
return request_field
else:
return self.__multipart_json_item(key=key, value=value)
request_field = self.__multipart_json_item(key=key, value=value)
return request_field
def __serialize_multipart_form_data(
self, in_data: Schema
@@ -1496,4 +1496,4 @@ class RequestBody(StyleFormSerializer, JSONDetector):
return self.__serialize_application_x_www_form_data(cast_in_data)
elif content_type == 'application/octet-stream':
return self.__serialize_application_octet_stream(cast_in_data)
raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type))
raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type))

View File

@@ -80,14 +80,16 @@ class Configuration(object):
_default = None
def __init__(self, host=None,
api_key=None, api_key_prefix=None,
username=None, password=None,
discard_unknown_keys=False,
disabled_client_side_validations="",
server_index=None, server_variables=None,
server_operation_index=None, server_operation_variables=None,
):
def __init__(
self,
host=None,
discard_unknown_keys=False,
disabled_client_side_validations="",
server_index=None,
server_variables=None,
server_operation_index=None,
server_operation_variables=None,
):
"""Constructor
"""
self._base_path = "http://petstore.swagger.io:80/v2" if host is None else host
@@ -105,26 +107,6 @@ class Configuration(object):
"""Temp file folder for downloading files
"""
# Authentication Settings
self.api_key = {}
if api_key:
self.api_key = api_key
"""dict to store API key(s)
"""
self.api_key_prefix = {}
if api_key_prefix:
self.api_key_prefix = api_key_prefix
"""dict to store API prefix (e.g. Bearer)
"""
self.refresh_api_key_hook = None
"""function hook to refresh API key if expired
"""
self.username = username
"""Username for HTTP basic authentication
"""
self.password = password
"""Password for HTTP basic authentication
"""
self.discard_unknown_keys = discard_unknown_keys
self.disabled_client_side_validations = disabled_client_side_validations
self.logger = {}
"""Logging Settings

View File

@@ -8,6 +8,10 @@
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
import dataclasses
import typing
from urllib3._collections import HTTPHeaderDict
class OpenApiException(Exception):
@@ -97,19 +101,26 @@ class ApiKeyError(OpenApiException, KeyError):
super(ApiKeyError, self).__init__(full_msg)
class ApiException(OpenApiException):
T = typing.TypeVar("T")
def __init__(self, status=None, reason=None, api_response: 'dynamic_servers.api_client.ApiResponse' = None):
if api_response:
self.status = api_response.response.status
self.reason = api_response.response.reason
self.body = api_response.response.data
self.headers = api_response.response.getheaders()
else:
self.status = status
self.reason = reason
self.body = None
self.headers = None
@dataclasses.dataclass
class ApiException(OpenApiException, typing.Generic[T]):
status: int
reason: str
api_response: typing.Optional[T] = None
@property
def body(self) -> typing.Union[str, bytes, None]:
if not self.api_response:
return None
return self.api_response.response.data
@property
def headers(self) -> typing.Optional[HTTPHeaderDict]:
if not self.api_response:
return None
return self.api_response.response.getheaders()
def __str__(self):
"""Custom error messages for exception"""

View File

@@ -6,7 +6,7 @@
# if you have many models here with many references from one model to another this may
# raise a RecursionError
# to avoid this, import only the models that you directly need like:
# from from dynamic_servers.model.pet import Pet
# from dynamic_servers.model.pet import Pet
# or import this package, but before doing it, use:
# import sys
# sys.setrecursionlimit(n)

View File

@@ -183,7 +183,11 @@ class BaseApi(api_client.Api):
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
if not 200 <= response.status <= 299:
raise exceptions.ApiException(api_response=api_response)
raise exceptions.ApiException(
status=response.status,
reason=response.reason,
api_response=api_response
)
return api_response

View File

@@ -128,7 +128,11 @@ class BaseApi(api_client.Api):
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
if not 200 <= response.status <= 299:
raise exceptions.ApiException(api_response=api_response)
raise exceptions.ApiException(
status=response.status,
reason=response.reason,
api_response=api_response
)
return api_response

View File

@@ -126,7 +126,11 @@ class BaseApi(api_client.Api):
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
if not 200 <= response.status <= 299:
raise exceptions.ApiException(api_response=api_response)
raise exceptions.ApiException(
status=response.status,
reason=response.reason,
api_response=api_response
)
return api_response

View File

@@ -121,7 +121,11 @@ class BaseApi(api_client.Api):
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
if not 200 <= response.status <= 299:
raise exceptions.ApiException(api_response=api_response)
raise exceptions.ApiException(
status=response.status,
reason=response.reason,
api_response=api_response
)
return api_response

View File

@@ -50,17 +50,17 @@ class FileIO(io.FileIO):
Note: this class is not immutable
"""
def __new__(cls, arg: typing.Union[io.FileIO, io.BufferedReader]):
if isinstance(arg, (io.FileIO, io.BufferedReader)):
if arg.closed:
def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader]):
if isinstance(_arg, (io.FileIO, io.BufferedReader)):
if _arg.closed:
raise ApiValueError('Invalid file state; file is closed and must be open')
arg.close()
inst = super(FileIO, cls).__new__(cls, arg.name)
super(FileIO, inst).__init__(arg.name)
_arg.close()
inst = super(FileIO, cls).__new__(cls, _arg.name)
super(FileIO, inst).__init__(_arg.name)
return inst
raise ApiValueError('FileIO must be passed arg which contains the open file')
raise ApiValueError('FileIO must be passed _arg which contains the open file')
def __init__(self, arg: typing.Union[io.FileIO, io.BufferedReader]):
def __init__(self, _arg: typing.Union[io.FileIO, io.BufferedReader]):
pass
@@ -148,14 +148,27 @@ class ValidationMetadata(frozendict.frozendict):
return self.get('validated_path_to_schemas')
def add_deeper_validated_schemas(validation_metadata: ValidationMetadata, path_to_schemas: dict):
# this is called if validation_ran_earlier and current and deeper locations need to be added
current_path_to_item = validation_metadata.path_to_item
other_path_to_schemas = {}
for path_to_item, schemas in validation_metadata.validated_path_to_schemas.items():
if len(path_to_item) < len(current_path_to_item):
continue
path_begins_with_current_path = path_to_item[:len(current_path_to_item)] == current_path_to_item
if path_begins_with_current_path:
other_path_to_schemas[path_to_item] = schemas
update(path_to_schemas, other_path_to_schemas)
class Singleton:
"""
Enums and singletons are the same
The same instance is returned for a given key of (cls, arg)
The same instance is returned for a given key of (cls, _arg)
"""
_instances = {}
def __new__(cls, arg: typing.Any, **kwargs):
def __new__(cls, _arg: typing.Any, **kwargs):
"""
cls base classes: BoolClass, NoneClass, str, decimal.Decimal
The 3rd key is used in the tuple below for a corner case where an enum contains integer 1
@@ -163,15 +176,15 @@ class Singleton:
Decimal('1.0') == Decimal('1')
But if we omitted the 3rd value in the key, then Decimal('1.0') would be stored as Decimal('1')
and json serializing that instance would be '1' rather than the expected '1.0'
Adding the 3rd value, the str of arg ensures that 1.0 -> Decimal('1.0') which is serialized as 1.0
Adding the 3rd value, the str of _arg ensures that 1.0 -> Decimal('1.0') which is serialized as 1.0
"""
key = (cls, arg, str(arg))
key = (cls, _arg, str(_arg))
if key not in cls._instances:
if isinstance(arg, (none_type, bool, BoolClass, NoneClass)):
if isinstance(_arg, (none_type, bool, BoolClass, NoneClass)):
inst = super().__new__(cls)
cls._instances[key] = inst
else:
cls._instances[key] = super().__new__(cls, arg)
cls._instances[key] = super().__new__(cls, _arg)
return cls._instances[key]
def __repr__(self):
@@ -385,16 +398,16 @@ class Schema:
_validate_oapg returns a key value pair
where the key is the path to the item, and the value will be the required manufactured class
made out of the matching schemas
2. value is an instance of the the correct schema type
2. value is an instance of the correct schema type
the value is NOT validated by _validate_oapg, _validate_oapg only checks that the instance is of the correct schema type
for this value, _validate_oapg does NOT return an entry for it in _path_to_schemas
and in list/dict _get_items_oapg,_get_properties_oapg the value will be directly assigned
because value is of the correct type, and validation was run earlier when the instance was created
"""
_path_to_schemas = {}
if validation_metadata.validated_path_to_schemas:
update(_path_to_schemas, validation_metadata.validated_path_to_schemas)
if not validation_metadata.validation_ran_earlier(cls):
if validation_metadata.validation_ran_earlier(cls):
add_deeper_validated_schemas(validation_metadata, _path_to_schemas)
else:
other_path_to_schemas = cls._validate_oapg(arg, validation_metadata=validation_metadata)
update(_path_to_schemas, other_path_to_schemas)
# loop through it make a new class for each entry
@@ -499,12 +512,12 @@ class Schema:
def __remove_unsets(kwargs):
return {key: val for key, val in kwargs.items() if val is not unset}
def __new__(cls, *args: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema'], _configuration: typing.Optional[Configuration] = None, **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema', Unset]):
def __new__(cls, *_args: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema'], _configuration: typing.Optional[Configuration] = None, **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema', Unset]):
"""
Schema __new__
Args:
args (int/float/decimal.Decimal/str/list/tuple/dict/frozendict.frozendict/bool/None): the value
_args (int/float/decimal.Decimal/str/list/tuple/dict/frozendict.frozendict/bool/None): the value
kwargs (str, int/float/decimal.Decimal/str/list/tuple/dict/frozendict.frozendict/bool/None): dict values
_configuration: contains the Configuration that enables json schema validation keywords
like minItems, minLength etc
@@ -513,14 +526,14 @@ class Schema:
are instance properties if they are named normally :(
"""
__kwargs = cls.__remove_unsets(kwargs)
if not args and not __kwargs:
if not _args and not __kwargs:
raise TypeError(
'No input given. args or kwargs must be given.'
)
if not __kwargs and args and not isinstance(args[0], dict):
__arg = args[0]
if not __kwargs and _args and not isinstance(_args[0], dict):
__arg = _args[0]
else:
__arg = cls.__get_input_dict(*args, **__kwargs)
__arg = cls.__get_input_dict(*_args, **__kwargs)
__from_server = False
__validated_path_to_schemas = {}
__arg = cast_to_allowed_types(
@@ -537,7 +550,7 @@ class Schema:
def __init__(
self,
*args: typing.Union[
*_args: typing.Union[
dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema'],
_configuration: typing.Optional[Configuration] = None,
**kwargs: typing.Union[
@@ -868,7 +881,7 @@ class ValidatorBase:
schema_keyword not in configuration._disabled_client_side_validations)
@staticmethod
def _raise_validation_errror_message_oapg(value, constraint_msg, constraint_value, path_to_item, additional_txt=""):
def _raise_validation_error_message_oapg(value, constraint_msg, constraint_value, path_to_item, additional_txt=""):
raise ApiValueError(
"Invalid value `{value}`, {constraint_msg} `{constraint_value}`{additional_txt} at {path_to_item}".format(
value=value,
@@ -963,7 +976,7 @@ class StrBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('maxLength', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'max_length') and
len(arg) > cls.MetaOapg.max_length):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="length must be less than or equal to",
constraint_value=cls.MetaOapg.max_length,
@@ -973,7 +986,7 @@ class StrBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('minLength', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'min_length') and
len(arg) < cls.MetaOapg.min_length):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="length must be greater than or equal to",
constraint_value=cls.MetaOapg.min_length,
@@ -988,14 +1001,14 @@ class StrBase(ValidatorBase):
if flags != 0:
# Don't print the regex flags if the flags are not
# specified in the OAS document.
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must match regular expression",
constraint_value=regex_dict['pattern'],
path_to_item=validation_metadata.path_to_item,
additional_txt=" with flags=`{}`".format(flags)
)
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must match regular expression",
constraint_value=regex_dict['pattern'],
@@ -1211,7 +1224,7 @@ class NumberBase(ValidatorBase):
return self._as_float
except AttributeError:
if self.as_tuple().exponent >= 0:
raise ApiValueError(f'{self} is not an float')
raise ApiValueError(f'{self} is not a float')
self._as_float = float(self)
return self._as_float
@@ -1228,7 +1241,7 @@ class NumberBase(ValidatorBase):
multiple_of_value = cls.MetaOapg.multiple_of
if (not (float(arg) / multiple_of_value).is_integer()):
# Note 'multipleOf' will be as good as the floating point arithmetic.
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="value must be a multiple of",
constraint_value=multiple_of_value,
@@ -1249,7 +1262,7 @@ class NumberBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('exclusiveMaximum', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'exclusive_maximum') and
arg >= cls.MetaOapg.exclusive_maximum):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must be a value less than",
constraint_value=cls.MetaOapg.exclusive_maximum,
@@ -1259,7 +1272,7 @@ class NumberBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('maximum', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'inclusive_maximum') and
arg > cls.MetaOapg.inclusive_maximum):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must be a value less than or equal to",
constraint_value=cls.MetaOapg.inclusive_maximum,
@@ -1269,7 +1282,7 @@ class NumberBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('exclusiveMinimum', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'exclusive_minimum') and
arg <= cls.MetaOapg.exclusive_minimum):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must be a value greater than",
constraint_value=cls.MetaOapg.exclusive_maximum,
@@ -1279,7 +1292,7 @@ class NumberBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('minimum', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'inclusive_minimum') and
arg < cls.MetaOapg.inclusive_minimum):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="must be a value greater than or equal to",
constraint_value=cls.MetaOapg.inclusive_minimum,
@@ -1332,6 +1345,7 @@ class ListBase(ValidatorBase):
validated_path_to_schemas=validation_metadata.validated_path_to_schemas
)
if item_validation_metadata.validation_ran_earlier(item_cls):
add_deeper_validated_schemas(item_validation_metadata, path_to_schemas)
continue
other_path_to_schemas = item_cls._validate_oapg(
value, validation_metadata=item_validation_metadata)
@@ -1347,7 +1361,7 @@ class ListBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('maxItems', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'max_items') and
len(arg) > cls.MetaOapg.max_items):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="number of items must be less than or equal to",
constraint_value=cls.MetaOapg.max_items,
@@ -1357,7 +1371,7 @@ class ListBase(ValidatorBase):
if (cls._is_json_validation_enabled_oapg('minItems', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'min_items') and
len(arg) < cls.MetaOapg.min_items):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="number of items must be greater than or equal to",
constraint_value=cls.MetaOapg.min_items,
@@ -1368,7 +1382,7 @@ class ListBase(ValidatorBase):
hasattr(cls.MetaOapg, 'unique_items') and cls.MetaOapg.unique_items and arg):
unique_items = set(arg)
if len(arg) > len(unique_items):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="duplicate items were found, and the tuple must not contain duplicates because",
constraint_value='unique_items==True',
@@ -1595,6 +1609,7 @@ class DictBase(Discriminable, ValidatorBase):
validated_path_to_schemas=validation_metadata.validated_path_to_schemas
)
if arg_validation_metadata.validation_ran_earlier(schema):
add_deeper_validated_schemas(arg_validation_metadata, path_to_schemas)
continue
other_path_to_schemas = schema._validate_oapg(value, validation_metadata=arg_validation_metadata)
update(path_to_schemas, other_path_to_schemas)
@@ -1611,7 +1626,7 @@ class DictBase(Discriminable, ValidatorBase):
if (cls._is_json_validation_enabled_oapg('maxProperties', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'max_properties') and
len(arg) > cls.MetaOapg.max_properties):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="number of properties must be less than or equal to",
constraint_value=cls.MetaOapg.max_properties,
@@ -1621,7 +1636,7 @@ class DictBase(Discriminable, ValidatorBase):
if (cls._is_json_validation_enabled_oapg('minProperties', validation_metadata.configuration) and
hasattr(cls.MetaOapg, 'min_properties') and
len(arg) < cls.MetaOapg.min_properties):
cls._raise_validation_errror_message_oapg(
cls._raise_validation_error_message_oapg(
value=arg,
constraint_msg="number of properties must be greater than or equal to",
constraint_value=cls.MetaOapg.min_properties,
@@ -1683,6 +1698,7 @@ class DictBase(Discriminable, ValidatorBase):
validated_path_to_schemas=validation_metadata.validated_path_to_schemas
)
if updated_vm.validation_ran_earlier(discriminated_cls):
add_deeper_validated_schemas(updated_vm, _path_to_schemas)
return _path_to_schemas
other_path_to_schemas = discriminated_cls._validate_oapg(arg, validation_metadata=updated_vm)
update(_path_to_schemas, other_path_to_schemas)
@@ -1781,18 +1797,11 @@ def cast_to_allowed_types(
if isinstance(arg, Schema):
# store the already run validations
schema_classes = set()
source_schema_was_unset = len(arg.__class__.__bases__) == 2 and UnsetAnyTypeSchema in arg.__class__.__bases__
if not source_schema_was_unset:
"""
Do not include UnsetAnyTypeSchema and its base class because
it did not exist in the original spec schema definition
It was added to ensure that all instances are of type Schema and the allowed base types
"""
for cls in arg.__class__.__bases__:
if cls is Singleton:
# Skip Singleton
continue
schema_classes.add(cls)
for cls in arg.__class__.__bases__:
if cls is Singleton:
# Skip Singleton
continue
schema_classes.add(cls)
validated_path_to_schemas[path_to_item] = schema_classes
type_error = ApiTypeError(f"Invalid type. Required value type is str and passed type was {type(arg)} at {path_to_item}")
@@ -1845,6 +1854,7 @@ class ComposedBase(Discriminable):
path_to_schemas = defaultdict(set)
for allof_cls in cls.MetaOapg.all_of():
if validation_metadata.validation_ran_earlier(allof_cls):
add_deeper_validated_schemas(validation_metadata, path_to_schemas)
continue
other_path_to_schemas = allof_cls._validate_oapg(arg, validation_metadata=validation_metadata)
update(path_to_schemas, other_path_to_schemas)
@@ -1865,6 +1875,7 @@ class ComposedBase(Discriminable):
continue
if validation_metadata.validation_ran_earlier(oneof_cls):
oneof_classes.append(oneof_cls)
add_deeper_validated_schemas(validation_metadata, path_to_schemas)
continue
try:
path_to_schemas = oneof_cls._validate_oapg(arg, validation_metadata=validation_metadata)
@@ -1898,6 +1909,7 @@ class ComposedBase(Discriminable):
for anyof_cls in cls.MetaOapg.any_of():
if validation_metadata.validation_ran_earlier(anyof_cls):
anyof_classes.append(anyof_cls)
add_deeper_validated_schemas(validation_metadata, path_to_schemas)
continue
try:
@@ -2011,6 +2023,7 @@ class ComposedBase(Discriminable):
if discriminated_cls is not None and not updated_vm.validation_ran_earlier(discriminated_cls):
# TODO use an exception from this package here
add_deeper_validated_schemas(updated_vm, path_to_schemas)
assert discriminated_cls in path_to_schemas[updated_vm.path_to_item]
return path_to_schemas
@@ -2046,8 +2059,8 @@ class ListSchema(
def from_openapi_data_oapg(cls, arg: typing.List[typing.Any], _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: typing.Union[typing.List[typing.Any], typing.Tuple[typing.Any]], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[typing.List[typing.Any], typing.Tuple[typing.Any]], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class NoneSchema(
@@ -2060,8 +2073,8 @@ class NoneSchema(
def from_openapi_data_oapg(cls, arg: None, _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: None, **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: None, **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class NumberSchema(
@@ -2078,8 +2091,8 @@ class NumberSchema(
def from_openapi_data_oapg(cls, arg: typing.Union[int, float], _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: typing.Union[decimal.Decimal, int, float], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[decimal.Decimal, int, float], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class IntBase:
@@ -2121,8 +2134,8 @@ class IntSchema(IntBase, NumberSchema):
def from_openapi_data_oapg(cls, arg: int, _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: typing.Union[decimal.Decimal, int], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[decimal.Decimal, int], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class Int32Base:
@@ -2275,31 +2288,31 @@ class StrSchema(
def from_openapi_data_oapg(cls, arg: str, _configuration: typing.Optional[Configuration] = None) -> 'StrSchema':
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: typing.Union[str, date, datetime, uuid.UUID], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[str, date, datetime, uuid.UUID], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class UUIDSchema(UUIDBase, StrSchema):
def __new__(cls, arg: typing.Union[str, uuid.UUID], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[str, uuid.UUID], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class DateSchema(DateBase, StrSchema):
def __new__(cls, arg: typing.Union[str, date], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[str, date], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class DateTimeSchema(DateTimeBase, StrSchema):
def __new__(cls, arg: typing.Union[str, datetime], **kwargs: Configuration):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: typing.Union[str, datetime], **kwargs: Configuration):
return super().__new__(cls, _arg, **kwargs)
class DecimalSchema(DecimalBase, StrSchema):
def __new__(cls, arg: str, **kwargs: Configuration):
def __new__(cls, _arg: str, **kwargs: Configuration):
"""
Note: Decimals may not be passed in because cast_to_allowed_types is only invoked once for payloads
which can be simple (str) or complex (dicts or lists with nested values)
@@ -2308,7 +2321,7 @@ class DecimalSchema(DecimalBase, StrSchema):
if one was using it for a StrSchema (where it should be cast to str) or one is using it for NumberSchema
where it should stay as Decimal.
"""
return super().__new__(cls, arg, **kwargs)
return super().__new__(cls, _arg, **kwargs)
class BytesSchema(
@@ -2318,8 +2331,8 @@ class BytesSchema(
"""
this class will subclass bytes and is immutable
"""
def __new__(cls, arg: bytes, **kwargs: Configuration):
return super(Schema, cls).__new__(cls, arg)
def __new__(cls, _arg: bytes, **kwargs: Configuration):
return super(Schema, cls).__new__(cls, _arg)
class FileSchema(
@@ -2343,8 +2356,8 @@ class FileSchema(
- to be able to preserve file name info
"""
def __new__(cls, arg: typing.Union[io.FileIO, io.BufferedReader], **kwargs: Configuration):
return super(Schema, cls).__new__(cls, arg)
def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader], **kwargs: Configuration):
return super(Schema, cls).__new__(cls, _arg)
class BinaryBase:
@@ -2365,8 +2378,8 @@ class BinarySchema(
FileSchema,
]
def __new__(cls, arg: typing.Union[io.FileIO, io.BufferedReader, bytes], **kwargs: Configuration):
return super().__new__(cls, arg)
def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader, bytes], **kwargs: Configuration):
return super().__new__(cls, _arg)
class BoolSchema(
@@ -2379,8 +2392,8 @@ class BoolSchema(
def from_openapi_data_oapg(cls, arg: bool, _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, arg: bool, **kwargs: ValidationMetadata):
return super().__new__(cls, arg, **kwargs)
def __new__(cls, _arg: bool, **kwargs: ValidationMetadata):
return super().__new__(cls, _arg, **kwargs)
class AnyTypeSchema(
@@ -2416,12 +2429,12 @@ class NotAnyTypeSchema(
def __new__(
cls,
*args,
*_args,
_configuration: typing.Optional[Configuration] = None,
) -> 'NotAnyTypeSchema':
return super().__new__(
cls,
*args,
*_args,
_configuration=_configuration,
)
@@ -2435,8 +2448,8 @@ class DictSchema(
def from_openapi_data_oapg(cls, arg: typing.Dict[str, typing.Any], _configuration: typing.Optional[Configuration] = None):
return super().from_openapi_data_oapg(arg, _configuration=_configuration)
def __new__(cls, *args: typing.Union[dict, frozendict.frozendict], **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, bytes, Schema, Unset, ValidationMetadata]):
return super().__new__(cls, *args, **kwargs)
def __new__(cls, *_args: typing.Union[dict, frozendict.frozendict], **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, bytes, Schema, Unset, ValidationMetadata]):
return super().__new__(cls, *_args, **kwargs)
schema_type_classes = {NoneSchema, DictSchema, ListSchema, NumberSchema, StrSchema, BoolSchema, AnyTypeSchema}
@@ -2459,4 +2472,4 @@ LOG_CACHE_USAGE = False
def log_cache_usage(cache_fn):
if LOG_CACHE_USAGE:
print(cache_fn.__name__, cache_fn.cache_info())
print(cache_fn.__name__, cache_fn.cache_info())

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
#
# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com"
# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
git_user_id=$1
git_repo_id=$2

View File

@@ -7,7 +7,7 @@
- bundle install -j $(nproc)
parallel:
matrix:
- RUBY_VERSION: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0']
- RUBY_VERSION: ['2.7', '3.0', '3.1']
image: "ruby:$RUBY_VERSION"
cache:
paths:

View File

@@ -1,12 +1,9 @@
language: ruby
cache: bundler
rvm:
- 2.3
- 2.4
- 2.5
- 2.6
- 2.7
- 3.0
- 3.1
script:
- bundle install --path vendor/bundle
- bundle exec rspec

View File

@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
s.summary = "OpenAPI Extension with dynamic servers Ruby Gem"
s.description = "This specification shows how to use dynamic servers."
s.license = "Unlicense"
s.required_ruby_version = ">= 2.4"
s.required_ruby_version = ">= 2.7"
s.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'

View File

@@ -32,6 +32,7 @@ module DynamicServers
end
else
super arg
@message = arg
end
end

View File

@@ -62,6 +62,16 @@ module DynamicServers
# Defines the access token (Bearer) used with OAuth2.
attr_accessor :access_token
# Defines a Proc used to fetch or refresh access tokens (Bearer) used with OAuth2.
# Overrides the access_token if set
# @return [Proc]
attr_accessor :access_token_getter
# Set this to return data as binary instead of downloading a temp file. When enabled (set to true)
# HTTP responses with return type `File` will be returned as a stream of binary data.
# Default to false.
attr_accessor :return_binary_data
# Set this to enable/disable debugging. When enabled (set to true), HTTP request/response
# details will be logged with `logger.debug` (see the `logger` attribute).
# Default to false.
@@ -208,6 +218,12 @@ module DynamicServers
end
end
# Gets access_token using access_token_getter or uses the static access_token
def access_token_with_refresh
return access_token if access_token_getter.nil?
access_token_getter.call
end
# Gets Basic Auth token string
def basic_auth_token
'Basic ' + ["#{username}:#{password}"].pack('m').delete("\r\n")

View File

@@ -89,6 +89,8 @@ describe DynamicServers::ApiClient do
end
end
describe '#deserialize' do
it "handles Array<Integer>" do
api_client = DynamicServers::ApiClient.new