starmallow 0.6.5__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {starmallow-0.6.5 → starmallow-0.7.0}/PKG-INFO +1 -1
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/__init__.py +1 -1
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/ext/marshmallow/openapi.py +31 -0
- starmallow-0.7.0/starmallow/union_field.py +86 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/utils.py +21 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/basic_api.py +5 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_basic_api.py +49 -1
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_delimited_params.py +1 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/.editorconfig +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/.gitignore +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/.pre-commit-config.yaml +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/Dockerfile +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/LICENSE.md +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/README.md +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/docker-compose.yml +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/docs/design_ideas.md +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/cache_server.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/flask_server.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/goals.ipynb +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/gunicorn.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/recommended_server.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/examples/sample_server.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/pyproject.toml +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/applications.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/background.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/concurrency.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/constants.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/dataclasses.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/datastructures.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/decorators.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/delimited_field.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/docs.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/endpoint.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/endpoints.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/exception_handlers.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/exceptions.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/ext/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/ext/marshmallow/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/fields.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/middleware/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/middleware/asyncexitstack.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/params.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/request_resolver.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/requests.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/responses.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/routing.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/schema_generator.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/api_key.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/base.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/http.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/oauth2.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/open_id_connect_url.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/security/utils.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/serializers.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/types.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/starmallow/websockets.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_cookie.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_cookie_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_cookie_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_header.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_header_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_header_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_query.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_query_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_query_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_base.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_base_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_base_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_basic.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_basic_realm.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_basic_realm_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_bearer.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_bearer_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_bearer_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_digest.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_digest_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_digest_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_authorization_code_bearer.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_authorization_code_bearer_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_optional_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_password_bearer_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_password_bearer_optional_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/openid_connect/__init__.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/openid_connect/test_openid_connect.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/openid_connect/test_openid_connect_description.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/security/openid_connect/test_openid_connect_optional.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_properties.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_response_extra.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_bad.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_custom_model_in_callback.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_custom_validationerror.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_default_validationerror.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_response_class.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_router.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_annotated.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_dataclass_fields.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_http_endpoints.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_input.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_middleware.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_requests_orjson.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_requests_ujson.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_resolved_param_contextmanagers.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_resolved_params.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_responses.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_responses_orjson.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_responses_ujson.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/test_ws_router.py +0 -0
- {starmallow-0.6.5 → starmallow-0.7.0}/tests/utils.py +0 -0
@@ -14,6 +14,7 @@ from apispec.ext.marshmallow.openapi import OpenAPIConverter as ApiSpecOpenAPICo
|
|
14
14
|
from marshmallow.utils import is_collection
|
15
15
|
from packaging.version import Version
|
16
16
|
|
17
|
+
from starmallow.union_field import Union as UnionField
|
17
18
|
from starmallow.utils import MARSHMALLOW_ITERABLES
|
18
19
|
|
19
20
|
# marshmallow field => (JSON Schema type, format)
|
@@ -98,6 +99,7 @@ class OpenAPIConverter(ApiSpecOpenAPIConverter):
|
|
98
99
|
self.add_attribute_function(self.field2title)
|
99
100
|
self.add_attribute_function(self.field2uniqueItems)
|
100
101
|
self.add_attribute_function(self.field2enum)
|
102
|
+
self.add_attribute_function(self.field2union)
|
101
103
|
|
102
104
|
# Overriding to add exclusiveMinimum and exclusiveMaximum support
|
103
105
|
def field2range(self: FieldConverterMixin, field: mf.Field, ret) -> dict:
|
@@ -211,6 +213,35 @@ class OpenAPIConverter(ApiSpecOpenAPIConverter):
|
|
211
213
|
|
212
214
|
return ret
|
213
215
|
|
216
|
+
def field2union(self: FieldConverterMixin, field: mf.Field, **kwargs: Any) -> dict:
|
217
|
+
ret = {}
|
218
|
+
|
219
|
+
if isinstance(field, UnionField):
|
220
|
+
union_types = []
|
221
|
+
untyped = False
|
222
|
+
for _, subfield in field.union_fields:
|
223
|
+
for field_class in type(subfield).__mro__:
|
224
|
+
if field_class in self.field_mapping:
|
225
|
+
type_, fmt = self.field_mapping[field_class]
|
226
|
+
|
227
|
+
union_type = {}
|
228
|
+
if type_:
|
229
|
+
union_type['type'] = type_
|
230
|
+
if fmt:
|
231
|
+
union_type['fmt'] = fmt
|
232
|
+
|
233
|
+
if union_type:
|
234
|
+
union_types.append(union_type)
|
235
|
+
else:
|
236
|
+
# at least one untyped, so can't reliably create a schema
|
237
|
+
untyped = True
|
238
|
+
break
|
239
|
+
|
240
|
+
if union_types and not untyped:
|
241
|
+
ret['type'] = {'oneOf': union_types}
|
242
|
+
|
243
|
+
return ret
|
244
|
+
|
214
245
|
# Overrice to add 'deprecated' support
|
215
246
|
def _field2parameter(
|
216
247
|
self, field: mf.Field, *, name: str, location: str,
|
@@ -0,0 +1,86 @@
|
|
1
|
+
'''Copied from marshmallow_dataclass, https://github.com/lovasoa/marshmallow_dataclass/blob/master/marshmallow_dataclass/union_field.py
|
2
|
+
Didn't want to add the dependency to this project1
|
3
|
+
'''
|
4
|
+
|
5
|
+
import copy
|
6
|
+
import inspect
|
7
|
+
from typing import Any, List, Optional, Tuple
|
8
|
+
|
9
|
+
import typeguard
|
10
|
+
from marshmallow import Schema, ValidationError, fields
|
11
|
+
|
12
|
+
try:
|
13
|
+
from typeguard import TypeCheckError # type: ignore[attr-defined]
|
14
|
+
except ImportError:
|
15
|
+
# typeguard < 3
|
16
|
+
TypeCheckError = TypeError # type: ignore[misc, assignment]
|
17
|
+
|
18
|
+
if "argname" not in inspect.signature(typeguard.check_type).parameters:
|
19
|
+
|
20
|
+
def _check_type(value, expected_type, argname: str):
|
21
|
+
return typeguard.check_type(value=value, expected_type=expected_type)
|
22
|
+
|
23
|
+
else:
|
24
|
+
# typeguard < 3.0.0rc2
|
25
|
+
def _check_type(value, expected_type, argname: str):
|
26
|
+
return typeguard.check_type( # type: ignore[call-overload]
|
27
|
+
value=value, expected_type=expected_type, argname=argname,
|
28
|
+
)
|
29
|
+
|
30
|
+
|
31
|
+
class Union(fields.Field):
|
32
|
+
"""A union field, composed other `Field` classes or instances.
|
33
|
+
This field serializes elements based on their type, with one of its child fields.
|
34
|
+
|
35
|
+
Example: ::
|
36
|
+
|
37
|
+
number_or_string = UnionField([
|
38
|
+
(float, fields.Float()),
|
39
|
+
(str, fields.Str())
|
40
|
+
])
|
41
|
+
|
42
|
+
:param union_fields: A list of types and their associated field instance.
|
43
|
+
:param kwargs: The same keyword arguments that :class:`Field` receives.
|
44
|
+
"""
|
45
|
+
|
46
|
+
def __init__(self, union_fields: List[Tuple[type, fields.Field]], **kwargs):
|
47
|
+
super().__init__(**kwargs)
|
48
|
+
self.union_fields = union_fields
|
49
|
+
|
50
|
+
def _bind_to_schema(self, field_name: str, schema: Schema) -> None:
|
51
|
+
super()._bind_to_schema(field_name, schema)
|
52
|
+
new_union_fields = []
|
53
|
+
for typ, field in self.union_fields:
|
54
|
+
field = copy.deepcopy(field)
|
55
|
+
field._bind_to_schema(field_name, self)
|
56
|
+
new_union_fields.append((typ, field))
|
57
|
+
|
58
|
+
self.union_fields = new_union_fields
|
59
|
+
|
60
|
+
def _serialize(self, value: Any, attr: Optional[str], obj, **kwargs) -> Any:
|
61
|
+
errors = []
|
62
|
+
if value is None:
|
63
|
+
return value
|
64
|
+
for typ, field in self.union_fields:
|
65
|
+
try:
|
66
|
+
_check_type(value=value, expected_type=typ, argname=attr or "anonymous")
|
67
|
+
return field._serialize(value, attr, obj, **kwargs)
|
68
|
+
except TypeCheckError as e:
|
69
|
+
errors.append(e)
|
70
|
+
raise TypeError(
|
71
|
+
f"Unable to serialize value with any of the fields in the union: {errors}",
|
72
|
+
)
|
73
|
+
|
74
|
+
def _deserialize(self, value: Any, attr: Optional[str], data, **kwargs) -> Any:
|
75
|
+
errors = []
|
76
|
+
for typ, field in self.union_fields:
|
77
|
+
try:
|
78
|
+
result = field.deserialize(value, **kwargs)
|
79
|
+
_check_type(
|
80
|
+
value=result, expected_type=typ, argname=attr or "anonymous",
|
81
|
+
)
|
82
|
+
return result
|
83
|
+
except (TypeCheckError, ValidationError) as e:
|
84
|
+
errors.append(e)
|
85
|
+
|
86
|
+
raise ValidationError(errors)
|
@@ -34,12 +34,14 @@ import dpath.util
|
|
34
34
|
import marshmallow as ma
|
35
35
|
import marshmallow.fields as mf
|
36
36
|
import marshmallow_dataclass.collection_field as collection_field
|
37
|
+
import typing_inspect
|
37
38
|
from marshmallow.validate import Equal, OneOf
|
38
39
|
from starlette.responses import Response
|
39
40
|
from typing_inspect import is_final_type, is_generic_type, is_literal_type
|
40
41
|
|
41
42
|
from starmallow.concurrency import contextmanager_in_threadpool
|
42
43
|
from starmallow.datastructures import DefaultPlaceholder, DefaultType
|
44
|
+
from starmallow.union_field import Union as UnionField
|
43
45
|
|
44
46
|
if TYPE_CHECKING: # pragma: nocover
|
45
47
|
from starmallow.routing import APIRoute
|
@@ -136,6 +138,25 @@ def get_model_field(model: Any, **kwargs) -> mf.Field:
|
|
136
138
|
if not is_generic_type(model) and lenient_issubclass(model, Enum):
|
137
139
|
return mf.Enum(model, **kwargs)
|
138
140
|
|
141
|
+
# Union
|
142
|
+
if typing_inspect.is_union_type(model):
|
143
|
+
if typing_inspect.is_optional_type(model):
|
144
|
+
kwargs["allow_none"] = kwargs.get("allow_none", True)
|
145
|
+
kwargs["dump_default"] = kwargs.get("dump_default", None)
|
146
|
+
if not kwargs.get("required"):
|
147
|
+
kwargs["load_default"] = kwargs.get("load_default", None)
|
148
|
+
kwargs.setdefault("required", False)
|
149
|
+
|
150
|
+
arguments = get_args(model)
|
151
|
+
subtypes = [t for t in arguments if t is not NoneType] # type: ignore
|
152
|
+
if len(subtypes) == 1:
|
153
|
+
return get_model_field(model, **kwargs)
|
154
|
+
|
155
|
+
return UnionField(
|
156
|
+
[(subtyp, get_model_field(subtyp, required=True)) for subtyp in subtypes],
|
157
|
+
**kwargs
|
158
|
+
)
|
159
|
+
|
139
160
|
origin = get_origin(model)
|
140
161
|
if origin not in PY_ITERABLES:
|
141
162
|
raise Exception(f'Unknown model type, model is {model}')
|
@@ -116,6 +116,11 @@ def get_final_id(item_id: FinalItem = Path()):
|
|
116
116
|
return item_id
|
117
117
|
|
118
118
|
|
119
|
+
@app.get("/path/union/{item_id}")
|
120
|
+
def get_union_id(item_id: int | float | bool):
|
121
|
+
return item_id
|
122
|
+
|
123
|
+
|
119
124
|
#########################################################
|
120
125
|
# Test Path parameters
|
121
126
|
#########################################################
|
@@ -470,6 +470,51 @@ openapi_schema = {
|
|
470
470
|
],
|
471
471
|
},
|
472
472
|
},
|
473
|
+
"/path/union/{item_id}": {
|
474
|
+
"get": {
|
475
|
+
"responses": {
|
476
|
+
"200": {
|
477
|
+
"description": "Successful Response",
|
478
|
+
"content": {"application/json": {"schema": {}}},
|
479
|
+
},
|
480
|
+
"422": {
|
481
|
+
"description": "Validation Error",
|
482
|
+
"content": {
|
483
|
+
"application/json": {
|
484
|
+
"schema": {
|
485
|
+
"$ref": "#/components/schemas/HTTPValidationError",
|
486
|
+
},
|
487
|
+
},
|
488
|
+
},
|
489
|
+
},
|
490
|
+
},
|
491
|
+
"summary": "Get Union Id",
|
492
|
+
"operationId": "get_union_id_path_union__item_id__get",
|
493
|
+
"parameters": [
|
494
|
+
{
|
495
|
+
'in': 'path',
|
496
|
+
'name': 'item_id',
|
497
|
+
'required': True,
|
498
|
+
'schema': {
|
499
|
+
'title': 'Item Id',
|
500
|
+
"type": {
|
501
|
+
"oneOf": [
|
502
|
+
{
|
503
|
+
"type": "integer",
|
504
|
+
},
|
505
|
+
{
|
506
|
+
"type": "number",
|
507
|
+
},
|
508
|
+
{
|
509
|
+
"type": "boolean",
|
510
|
+
},
|
511
|
+
],
|
512
|
+
},
|
513
|
+
},
|
514
|
+
},
|
515
|
+
],
|
516
|
+
},
|
517
|
+
},
|
473
518
|
"/path/param/{item_id}": {
|
474
519
|
"get": {
|
475
520
|
"responses": {
|
@@ -2259,7 +2304,10 @@ openapi_schema = {
|
|
2259
2304
|
"path,expected_status,expected_response",
|
2260
2305
|
[
|
2261
2306
|
("/api_route", 200, {"message": "Hello World"}),
|
2262
|
-
("/
|
2307
|
+
("/path/union/500.0", 200, 500.0),
|
2308
|
+
("/path/union/200", 200, 200),
|
2309
|
+
("/path/union/true", 200, True),
|
2310
|
+
("/api_route", 200, {"message": "Hello World"}),
|
2263
2311
|
("/nonexistent", 404, {"detail": "Not Found"}),
|
2264
2312
|
("/openapi.json", 200, openapi_schema),
|
2265
2313
|
],
|
@@ -235,6 +235,7 @@ openapi_schema = {
|
|
235
235
|
[
|
236
236
|
("/path/1,2,3,4", {}, 200, [1, 2, 3, 4]),
|
237
237
|
("/query?item_ids=5,4,3,2", {}, 200, [5, 4, 3, 2]),
|
238
|
+
("/query?item_ids=", {}, 200, []),
|
238
239
|
("/header", {'item_ids': '6,8,7'}, 200, [6, 8, 7]),
|
239
240
|
("/openapi.json", {}, 200, openapi_schema),
|
240
241
|
],
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_cookie_description.py
RENAMED
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_cookie_optional.py
RENAMED
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_header_description.py
RENAMED
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_header_optional.py
RENAMED
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/api_key/test_api_key_query_description.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/http/test_http_basic_realm_description.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_authorization_code_bearer.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_optional_description.py
RENAMED
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/oauth2/test_oauth2_password_bearer_optional.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/security/openid_connect/test_openid_connect_optional.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_custom_model_in_callback.py
RENAMED
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_custom_validationerror.py
RENAMED
File without changes
|
{starmallow-0.6.5 → starmallow-0.7.0}/tests/test_additional_responses_default_validationerror.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|