schemathesis 3.25.6__py3-none-any.whl → 3.39.7__py3-none-any.whl
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.
- schemathesis/__init__.py +6 -6
- schemathesis/_compat.py +2 -2
- schemathesis/_dependency_versions.py +4 -2
- schemathesis/_hypothesis.py +369 -56
- schemathesis/_lazy_import.py +1 -0
- schemathesis/_override.py +5 -4
- schemathesis/_patches.py +21 -0
- schemathesis/_rate_limiter.py +7 -0
- schemathesis/_xml.py +75 -22
- schemathesis/auths.py +78 -16
- schemathesis/checks.py +21 -9
- schemathesis/cli/__init__.py +783 -432
- schemathesis/cli/__main__.py +4 -0
- schemathesis/cli/callbacks.py +58 -13
- schemathesis/cli/cassettes.py +233 -47
- schemathesis/cli/constants.py +8 -2
- schemathesis/cli/context.py +22 -5
- schemathesis/cli/debug.py +2 -1
- schemathesis/cli/handlers.py +4 -1
- schemathesis/cli/junitxml.py +103 -22
- schemathesis/cli/options.py +15 -4
- schemathesis/cli/output/default.py +258 -112
- schemathesis/cli/output/short.py +23 -8
- schemathesis/cli/reporting.py +79 -0
- schemathesis/cli/sanitization.py +6 -0
- schemathesis/code_samples.py +5 -3
- schemathesis/constants.py +1 -0
- schemathesis/contrib/openapi/__init__.py +1 -1
- schemathesis/contrib/openapi/fill_missing_examples.py +3 -1
- schemathesis/contrib/openapi/formats/uuid.py +2 -1
- schemathesis/contrib/unique_data.py +3 -3
- schemathesis/exceptions.py +76 -65
- schemathesis/experimental/__init__.py +35 -0
- schemathesis/extra/_aiohttp.py +1 -0
- schemathesis/extra/_flask.py +4 -1
- schemathesis/extra/_server.py +1 -0
- schemathesis/extra/pytest_plugin.py +17 -25
- schemathesis/failures.py +77 -9
- schemathesis/filters.py +185 -8
- schemathesis/fixups/__init__.py +1 -0
- schemathesis/fixups/fast_api.py +2 -2
- schemathesis/fixups/utf8_bom.py +1 -2
- schemathesis/generation/__init__.py +20 -36
- schemathesis/generation/_hypothesis.py +59 -0
- schemathesis/generation/_methods.py +44 -0
- schemathesis/generation/coverage.py +931 -0
- schemathesis/graphql.py +0 -1
- schemathesis/hooks.py +89 -12
- schemathesis/internal/checks.py +84 -0
- schemathesis/internal/copy.py +22 -3
- schemathesis/internal/deprecation.py +6 -2
- schemathesis/internal/diff.py +15 -0
- schemathesis/internal/extensions.py +27 -0
- schemathesis/internal/jsonschema.py +2 -1
- schemathesis/internal/output.py +68 -0
- schemathesis/internal/result.py +1 -1
- schemathesis/internal/transformation.py +11 -0
- schemathesis/lazy.py +138 -25
- schemathesis/loaders.py +7 -5
- schemathesis/models.py +318 -211
- schemathesis/parameters.py +4 -0
- schemathesis/runner/__init__.py +50 -15
- schemathesis/runner/events.py +65 -5
- schemathesis/runner/impl/context.py +104 -0
- schemathesis/runner/impl/core.py +388 -177
- schemathesis/runner/impl/solo.py +19 -29
- schemathesis/runner/impl/threadpool.py +70 -79
- schemathesis/runner/probes.py +11 -9
- schemathesis/runner/serialization.py +150 -17
- schemathesis/sanitization.py +5 -1
- schemathesis/schemas.py +170 -102
- schemathesis/serializers.py +7 -2
- schemathesis/service/ci.py +1 -0
- schemathesis/service/client.py +39 -6
- schemathesis/service/events.py +5 -1
- schemathesis/service/extensions.py +224 -0
- schemathesis/service/hosts.py +6 -2
- schemathesis/service/metadata.py +25 -0
- schemathesis/service/models.py +211 -2
- schemathesis/service/report.py +6 -6
- schemathesis/service/serialization.py +45 -71
- schemathesis/service/usage.py +1 -0
- schemathesis/specs/graphql/_cache.py +26 -0
- schemathesis/specs/graphql/loaders.py +25 -5
- schemathesis/specs/graphql/nodes.py +1 -0
- schemathesis/specs/graphql/scalars.py +2 -2
- schemathesis/specs/graphql/schemas.py +130 -100
- schemathesis/specs/graphql/validation.py +1 -2
- schemathesis/specs/openapi/__init__.py +1 -0
- schemathesis/specs/openapi/_cache.py +123 -0
- schemathesis/specs/openapi/_hypothesis.py +78 -60
- schemathesis/specs/openapi/checks.py +504 -25
- schemathesis/specs/openapi/converter.py +31 -4
- schemathesis/specs/openapi/definitions.py +10 -17
- schemathesis/specs/openapi/examples.py +126 -12
- schemathesis/specs/openapi/expressions/__init__.py +37 -2
- schemathesis/specs/openapi/expressions/context.py +1 -1
- schemathesis/specs/openapi/expressions/extractors.py +26 -0
- schemathesis/specs/openapi/expressions/lexer.py +20 -18
- schemathesis/specs/openapi/expressions/nodes.py +29 -6
- schemathesis/specs/openapi/expressions/parser.py +26 -5
- schemathesis/specs/openapi/formats.py +44 -0
- schemathesis/specs/openapi/links.py +125 -42
- schemathesis/specs/openapi/loaders.py +77 -36
- schemathesis/specs/openapi/media_types.py +34 -0
- schemathesis/specs/openapi/negative/__init__.py +6 -3
- schemathesis/specs/openapi/negative/mutations.py +21 -6
- schemathesis/specs/openapi/parameters.py +39 -25
- schemathesis/specs/openapi/patterns.py +137 -0
- schemathesis/specs/openapi/references.py +37 -7
- schemathesis/specs/openapi/schemas.py +360 -241
- schemathesis/specs/openapi/security.py +25 -7
- schemathesis/specs/openapi/serialization.py +1 -0
- schemathesis/specs/openapi/stateful/__init__.py +198 -70
- schemathesis/specs/openapi/stateful/statistic.py +198 -0
- schemathesis/specs/openapi/stateful/types.py +14 -0
- schemathesis/specs/openapi/utils.py +6 -1
- schemathesis/specs/openapi/validation.py +1 -0
- schemathesis/stateful/__init__.py +35 -21
- schemathesis/stateful/config.py +97 -0
- schemathesis/stateful/context.py +135 -0
- schemathesis/stateful/events.py +274 -0
- schemathesis/stateful/runner.py +309 -0
- schemathesis/stateful/sink.py +68 -0
- schemathesis/stateful/state_machine.py +67 -38
- schemathesis/stateful/statistic.py +22 -0
- schemathesis/stateful/validation.py +100 -0
- schemathesis/targets.py +33 -1
- schemathesis/throttling.py +25 -5
- schemathesis/transports/__init__.py +354 -0
- schemathesis/transports/asgi.py +7 -0
- schemathesis/transports/auth.py +25 -2
- schemathesis/transports/content_types.py +3 -1
- schemathesis/transports/headers.py +2 -1
- schemathesis/transports/responses.py +9 -4
- schemathesis/types.py +9 -0
- schemathesis/utils.py +11 -16
- schemathesis-3.39.7.dist-info/METADATA +293 -0
- schemathesis-3.39.7.dist-info/RECORD +160 -0
- {schemathesis-3.25.6.dist-info → schemathesis-3.39.7.dist-info}/WHEEL +1 -1
- schemathesis/specs/openapi/filters.py +0 -49
- schemathesis/specs/openapi/stateful/links.py +0 -92
- schemathesis-3.25.6.dist-info/METADATA +0 -356
- schemathesis-3.25.6.dist-info/RECORD +0 -134
- {schemathesis-3.25.6.dist-info → schemathesis-3.39.7.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.25.6.dist-info → schemathesis-3.39.7.dist-info}/licenses/LICENSE +0 -0
schemathesis/lazy.py
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from contextlib import nullcontext
|
|
2
4
|
from dataclasses import dataclass, field
|
|
3
5
|
from inspect import signature
|
|
4
|
-
from typing import Any, Callable, Generator
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, Generator, Type
|
|
5
7
|
|
|
6
8
|
import pytest
|
|
7
|
-
from _pytest.fixtures import FixtureRequest
|
|
8
9
|
from hypothesis.core import HypothesisHandle
|
|
9
10
|
from hypothesis.errors import Flaky
|
|
10
11
|
from hypothesis.internal.escalation import format_exception, get_trimmed_traceback
|
|
11
12
|
from hypothesis.internal.reflection import impersonate
|
|
12
|
-
from
|
|
13
|
-
from pytest_subtests import SubTests, nullcontext
|
|
13
|
+
from pytest_subtests import SubTests
|
|
14
14
|
|
|
15
15
|
from ._compat import MultipleFailures, get_interesting_origin
|
|
16
|
-
from ._override import check_no_override_mark,
|
|
16
|
+
from ._override import CaseOverride, check_no_override_mark, get_override_from_mark, set_override_mark
|
|
17
17
|
from .auths import AuthStorage
|
|
18
18
|
from .code_samples import CodeSampleStyle
|
|
19
19
|
from .constants import FLAKY_FAILURE_MESSAGE, NOT_SET
|
|
20
|
-
from .generation import DataGenerationMethodInput, GenerationConfig
|
|
21
20
|
from .exceptions import CheckFailed, OperationSchemaError, SkipTest, get_grouped_exception
|
|
21
|
+
from .filters import FilterSet, FilterValue, MatcherFunc, RegexValue, filter_set_from_components, is_deprecated
|
|
22
22
|
from .hooks import HookDispatcher, HookScope
|
|
23
|
+
from .internal.deprecation import warn_filtration_arguments
|
|
23
24
|
from .internal.result import Ok
|
|
24
|
-
from .models import APIOperation
|
|
25
25
|
from .schemas import BaseSchema
|
|
26
|
-
from .types import Filter, GenericTest, NotSet
|
|
27
26
|
from .utils import (
|
|
28
27
|
GivenInput,
|
|
29
28
|
fail_on_no_matches,
|
|
@@ -35,26 +34,130 @@ from .utils import (
|
|
|
35
34
|
validate_given_args,
|
|
36
35
|
)
|
|
37
36
|
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from _pytest.fixtures import FixtureRequest
|
|
39
|
+
from pyrate_limiter import Limiter
|
|
40
|
+
|
|
41
|
+
from .generation import DataGenerationMethodInput, GenerationConfig
|
|
42
|
+
from .internal.output import OutputConfig
|
|
43
|
+
from .models import APIOperation
|
|
44
|
+
from .types import Filter, GenericTest, NotSet
|
|
45
|
+
|
|
38
46
|
|
|
39
47
|
@dataclass
|
|
40
48
|
class LazySchema:
|
|
41
49
|
fixture_name: str
|
|
42
50
|
base_url: str | None | NotSet = NOT_SET
|
|
43
|
-
method: Filter | None = NOT_SET
|
|
44
|
-
endpoint: Filter | None = NOT_SET
|
|
45
|
-
tag: Filter | None = NOT_SET
|
|
46
|
-
operation_id: Filter | None = NOT_SET
|
|
47
51
|
app: Any = NOT_SET
|
|
52
|
+
filter_set: FilterSet = field(default_factory=FilterSet)
|
|
48
53
|
hooks: HookDispatcher = field(default_factory=lambda: HookDispatcher(scope=HookScope.SCHEMA))
|
|
49
54
|
auth: AuthStorage = field(default_factory=AuthStorage)
|
|
50
55
|
validate_schema: bool = True
|
|
51
|
-
skip_deprecated_operations: bool = False
|
|
52
56
|
data_generation_methods: DataGenerationMethodInput | NotSet = NOT_SET
|
|
53
57
|
generation_config: GenerationConfig | NotSet = NOT_SET
|
|
58
|
+
output_config: OutputConfig | NotSet = NOT_SET
|
|
54
59
|
code_sample_style: CodeSampleStyle = CodeSampleStyle.default()
|
|
55
60
|
rate_limiter: Limiter | None = None
|
|
56
61
|
sanitize_output: bool = True
|
|
57
62
|
|
|
63
|
+
def include(
|
|
64
|
+
self,
|
|
65
|
+
func: MatcherFunc | None = None,
|
|
66
|
+
*,
|
|
67
|
+
name: FilterValue | None = None,
|
|
68
|
+
name_regex: str | None = None,
|
|
69
|
+
method: FilterValue | None = None,
|
|
70
|
+
method_regex: str | None = None,
|
|
71
|
+
path: FilterValue | None = None,
|
|
72
|
+
path_regex: str | None = None,
|
|
73
|
+
tag: FilterValue | None = None,
|
|
74
|
+
tag_regex: RegexValue | None = None,
|
|
75
|
+
operation_id: FilterValue | None = None,
|
|
76
|
+
operation_id_regex: RegexValue | None = None,
|
|
77
|
+
) -> LazySchema:
|
|
78
|
+
"""Include only operations that match the given filters."""
|
|
79
|
+
filter_set = self.filter_set.clone()
|
|
80
|
+
filter_set.include(
|
|
81
|
+
func,
|
|
82
|
+
name=name,
|
|
83
|
+
name_regex=name_regex,
|
|
84
|
+
method=method,
|
|
85
|
+
method_regex=method_regex,
|
|
86
|
+
path=path,
|
|
87
|
+
path_regex=path_regex,
|
|
88
|
+
tag=tag,
|
|
89
|
+
tag_regex=tag_regex,
|
|
90
|
+
operation_id=operation_id,
|
|
91
|
+
operation_id_regex=operation_id_regex,
|
|
92
|
+
)
|
|
93
|
+
return self.__class__(
|
|
94
|
+
fixture_name=self.fixture_name,
|
|
95
|
+
base_url=self.base_url,
|
|
96
|
+
app=self.app,
|
|
97
|
+
hooks=self.hooks,
|
|
98
|
+
auth=self.auth,
|
|
99
|
+
validate_schema=self.validate_schema,
|
|
100
|
+
data_generation_methods=self.data_generation_methods,
|
|
101
|
+
generation_config=self.generation_config,
|
|
102
|
+
output_config=self.output_config,
|
|
103
|
+
code_sample_style=self.code_sample_style,
|
|
104
|
+
rate_limiter=self.rate_limiter,
|
|
105
|
+
sanitize_output=self.sanitize_output,
|
|
106
|
+
filter_set=filter_set,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def exclude(
|
|
110
|
+
self,
|
|
111
|
+
func: MatcherFunc | None = None,
|
|
112
|
+
*,
|
|
113
|
+
name: FilterValue | None = None,
|
|
114
|
+
name_regex: str | None = None,
|
|
115
|
+
method: FilterValue | None = None,
|
|
116
|
+
method_regex: str | None = None,
|
|
117
|
+
path: FilterValue | None = None,
|
|
118
|
+
path_regex: str | None = None,
|
|
119
|
+
tag: FilterValue | None = None,
|
|
120
|
+
tag_regex: RegexValue | None = None,
|
|
121
|
+
operation_id: FilterValue | None = None,
|
|
122
|
+
operation_id_regex: RegexValue | None = None,
|
|
123
|
+
deprecated: bool = False,
|
|
124
|
+
) -> LazySchema:
|
|
125
|
+
"""Exclude operations that match the given filters."""
|
|
126
|
+
filter_set = self.filter_set.clone()
|
|
127
|
+
if deprecated:
|
|
128
|
+
if func is None:
|
|
129
|
+
func = is_deprecated
|
|
130
|
+
else:
|
|
131
|
+
filter_set.exclude(is_deprecated)
|
|
132
|
+
filter_set.exclude(
|
|
133
|
+
func,
|
|
134
|
+
name=name,
|
|
135
|
+
name_regex=name_regex,
|
|
136
|
+
method=method,
|
|
137
|
+
method_regex=method_regex,
|
|
138
|
+
path=path,
|
|
139
|
+
path_regex=path_regex,
|
|
140
|
+
tag=tag,
|
|
141
|
+
tag_regex=tag_regex,
|
|
142
|
+
operation_id=operation_id,
|
|
143
|
+
operation_id_regex=operation_id_regex,
|
|
144
|
+
)
|
|
145
|
+
return self.__class__(
|
|
146
|
+
fixture_name=self.fixture_name,
|
|
147
|
+
base_url=self.base_url,
|
|
148
|
+
app=self.app,
|
|
149
|
+
hooks=self.hooks,
|
|
150
|
+
auth=self.auth,
|
|
151
|
+
validate_schema=self.validate_schema,
|
|
152
|
+
data_generation_methods=self.data_generation_methods,
|
|
153
|
+
generation_config=self.generation_config,
|
|
154
|
+
output_config=self.output_config,
|
|
155
|
+
code_sample_style=self.code_sample_style,
|
|
156
|
+
rate_limiter=self.rate_limiter,
|
|
157
|
+
sanitize_output=self.sanitize_output,
|
|
158
|
+
filter_set=filter_set,
|
|
159
|
+
)
|
|
160
|
+
|
|
58
161
|
def hook(self, hook: str | Callable) -> Callable:
|
|
59
162
|
return self.hooks.register(hook)
|
|
60
163
|
|
|
@@ -68,20 +171,19 @@ class LazySchema:
|
|
|
68
171
|
skip_deprecated_operations: bool | NotSet = NOT_SET,
|
|
69
172
|
data_generation_methods: DataGenerationMethodInput | NotSet = NOT_SET,
|
|
70
173
|
generation_config: GenerationConfig | NotSet = NOT_SET,
|
|
174
|
+
output_config: OutputConfig | NotSet = NOT_SET,
|
|
71
175
|
code_sample_style: str | NotSet = NOT_SET,
|
|
72
176
|
) -> Callable:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if tag is NOT_SET:
|
|
78
|
-
tag = self.tag
|
|
79
|
-
if operation_id is NOT_SET:
|
|
80
|
-
operation_id = self.operation_id
|
|
177
|
+
for name in ("method", "endpoint", "tag", "operation_id", "skip_deprecated_operations"):
|
|
178
|
+
value = locals()[name]
|
|
179
|
+
if value is not NOT_SET:
|
|
180
|
+
warn_filtration_arguments(name)
|
|
81
181
|
if data_generation_methods is NOT_SET:
|
|
82
182
|
data_generation_methods = self.data_generation_methods
|
|
83
183
|
if generation_config is NOT_SET:
|
|
84
184
|
generation_config = self.generation_config
|
|
185
|
+
if output_config is NOT_SET:
|
|
186
|
+
output_config = self.output_config
|
|
85
187
|
if isinstance(code_sample_style, str):
|
|
86
188
|
_code_sample_style = CodeSampleStyle.from_str(code_sample_style)
|
|
87
189
|
else:
|
|
@@ -121,10 +223,12 @@ class LazySchema:
|
|
|
121
223
|
skip_deprecated_operations=skip_deprecated_operations,
|
|
122
224
|
data_generation_methods=data_generation_methods,
|
|
123
225
|
generation_config=generation_config,
|
|
226
|
+
output_config=output_config,
|
|
124
227
|
code_sample_style=_code_sample_style,
|
|
125
228
|
app=self.app,
|
|
126
229
|
rate_limiter=self.rate_limiter,
|
|
127
230
|
sanitize_output=self.sanitize_output,
|
|
231
|
+
filter_set=self.filter_set,
|
|
128
232
|
)
|
|
129
233
|
fixtures = get_fixtures(test, request, given_kwargs)
|
|
130
234
|
# Changing the node id is required for better reporting - the method and path will appear there
|
|
@@ -207,7 +311,7 @@ def _copy_marks(source: Callable, target: Callable) -> None:
|
|
|
207
311
|
target.pytestmark.extend(marks) # type: ignore
|
|
208
312
|
|
|
209
313
|
|
|
210
|
-
def _get_capturemanager(request: FixtureRequest) -> Generator:
|
|
314
|
+
def _get_capturemanager(request: FixtureRequest) -> Generator | Type[nullcontext]:
|
|
211
315
|
capturemanager = request.node.config.pluginmanager.get_plugin("capturemanager")
|
|
212
316
|
if capturemanager is not None:
|
|
213
317
|
return capturemanager.global_and_fixture_disabled
|
|
@@ -317,6 +421,7 @@ def get_schema(
|
|
|
317
421
|
endpoint: Filter | None = None,
|
|
318
422
|
tag: Filter | None = None,
|
|
319
423
|
operation_id: Filter | None = None,
|
|
424
|
+
filter_set: FilterSet,
|
|
320
425
|
app: Any = None,
|
|
321
426
|
test_function: GenericTest,
|
|
322
427
|
hooks: HookDispatcher,
|
|
@@ -325,6 +430,7 @@ def get_schema(
|
|
|
325
430
|
skip_deprecated_operations: bool | NotSet = NOT_SET,
|
|
326
431
|
data_generation_methods: DataGenerationMethodInput | NotSet = NOT_SET,
|
|
327
432
|
generation_config: GenerationConfig | NotSet = NOT_SET,
|
|
433
|
+
output_config: OutputConfig | NotSet = NOT_SET,
|
|
328
434
|
code_sample_style: CodeSampleStyle,
|
|
329
435
|
rate_limiter: Limiter | None,
|
|
330
436
|
sanitize_output: bool,
|
|
@@ -333,20 +439,27 @@ def get_schema(
|
|
|
333
439
|
schema = request.getfixturevalue(name)
|
|
334
440
|
if not isinstance(schema, BaseSchema):
|
|
335
441
|
raise ValueError(f"The given schema must be an instance of BaseSchema, got: {type(schema)}")
|
|
336
|
-
|
|
337
|
-
|
|
442
|
+
|
|
443
|
+
filter_set = filter_set_from_components(
|
|
444
|
+
include=True,
|
|
338
445
|
method=method,
|
|
339
446
|
endpoint=endpoint,
|
|
340
447
|
tag=tag,
|
|
341
448
|
operation_id=operation_id,
|
|
449
|
+
skip_deprecated_operations=skip_deprecated_operations,
|
|
450
|
+
parent=schema.filter_set.merge(filter_set),
|
|
451
|
+
)
|
|
452
|
+
return schema.clone(
|
|
453
|
+
base_url=base_url,
|
|
454
|
+
filter_set=filter_set,
|
|
342
455
|
app=app,
|
|
343
456
|
test_function=test_function,
|
|
344
457
|
hooks=schema.hooks.merge(hooks),
|
|
345
458
|
auth=auth,
|
|
346
459
|
validate_schema=validate_schema,
|
|
347
|
-
skip_deprecated_operations=skip_deprecated_operations,
|
|
348
460
|
data_generation_methods=data_generation_methods,
|
|
349
461
|
generation_config=generation_config,
|
|
462
|
+
output_config=output_config,
|
|
350
463
|
code_sample_style=code_sample_style,
|
|
351
464
|
rate_limiter=rate_limiter,
|
|
352
465
|
sanitize_output=sanitize_output,
|
schemathesis/loaders.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
import re
|
|
3
4
|
import sys
|
|
4
5
|
from functools import lru_cache
|
|
5
|
-
from typing import
|
|
6
|
+
from typing import TYPE_CHECKING, Any, BinaryIO, Callable, TextIO, TypeVar
|
|
6
7
|
|
|
7
8
|
from .exceptions import SchemaError, SchemaErrorType, extract_requests_exception_details
|
|
8
9
|
|
|
9
10
|
if TYPE_CHECKING:
|
|
10
|
-
from .transports.responses import GenericResponse
|
|
11
11
|
import yaml
|
|
12
12
|
|
|
13
|
+
from .transports.responses import GenericResponse
|
|
14
|
+
|
|
13
15
|
R = TypeVar("R", bound="GenericResponse")
|
|
14
16
|
|
|
15
17
|
|
|
@@ -49,13 +51,13 @@ def _raise_for_status(response: GenericResponse) -> None:
|
|
|
49
51
|
else:
|
|
50
52
|
type_ = SchemaErrorType.HTTP_CLIENT_ERROR
|
|
51
53
|
else:
|
|
52
|
-
return
|
|
54
|
+
return
|
|
53
55
|
raise SchemaError(message=message, type=type_, url=response.request.url, response=response, extras=[])
|
|
54
56
|
|
|
55
57
|
|
|
56
58
|
def load_app(path: str) -> Any:
|
|
57
59
|
"""Import an application from a string."""
|
|
58
|
-
path, name = (re.split(
|
|
60
|
+
path, name = ([*re.split(":(?![\\\\/])", path, maxsplit=1), ""])[:2]
|
|
59
61
|
__import__(path)
|
|
60
62
|
# accessing the module from sys.modules returns a proper module, while `__import__`
|
|
61
63
|
# may return a parent module (system dependent)
|
|
@@ -90,7 +92,7 @@ def get_yaml_loader() -> type[yaml.SafeLoader]:
|
|
|
90
92
|
|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*
|
|
91
93
|
|[-+]?\.(?:inf|Inf|INF)
|
|
92
94
|
|\.(?:nan|NaN|NAN))$""",
|
|
93
|
-
re.
|
|
95
|
+
re.VERBOSE,
|
|
94
96
|
),
|
|
95
97
|
list("-+0123456789."),
|
|
96
98
|
)
|