schemathesis 4.1.4__py3-none-any.whl → 4.2.0__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.
Files changed (70) hide show
  1. schemathesis/cli/commands/run/executor.py +1 -1
  2. schemathesis/cli/commands/run/handlers/base.py +28 -1
  3. schemathesis/cli/commands/run/handlers/cassettes.py +10 -12
  4. schemathesis/cli/commands/run/handlers/junitxml.py +5 -6
  5. schemathesis/cli/commands/run/handlers/output.py +7 -1
  6. schemathesis/cli/ext/fs.py +1 -1
  7. schemathesis/config/_diff_base.py +3 -1
  8. schemathesis/config/_operations.py +2 -0
  9. schemathesis/config/_phases.py +21 -4
  10. schemathesis/config/_projects.py +10 -2
  11. schemathesis/core/adapter.py +34 -0
  12. schemathesis/core/errors.py +29 -5
  13. schemathesis/core/jsonschema/__init__.py +13 -0
  14. schemathesis/core/jsonschema/bundler.py +163 -0
  15. schemathesis/{specs/openapi/constants.py → core/jsonschema/keywords.py} +0 -8
  16. schemathesis/core/jsonschema/references.py +122 -0
  17. schemathesis/core/jsonschema/types.py +41 -0
  18. schemathesis/core/media_types.py +6 -4
  19. schemathesis/core/parameters.py +37 -0
  20. schemathesis/core/transforms.py +25 -2
  21. schemathesis/core/validation.py +19 -0
  22. schemathesis/engine/context.py +1 -1
  23. schemathesis/engine/errors.py +11 -18
  24. schemathesis/engine/phases/stateful/_executor.py +1 -1
  25. schemathesis/engine/phases/unit/_executor.py +30 -13
  26. schemathesis/errors.py +4 -0
  27. schemathesis/filters.py +2 -2
  28. schemathesis/generation/coverage.py +87 -11
  29. schemathesis/generation/hypothesis/__init__.py +4 -1
  30. schemathesis/generation/hypothesis/builder.py +108 -70
  31. schemathesis/generation/meta.py +5 -14
  32. schemathesis/generation/overrides.py +17 -17
  33. schemathesis/pytest/lazy.py +1 -1
  34. schemathesis/pytest/plugin.py +1 -6
  35. schemathesis/schemas.py +22 -72
  36. schemathesis/specs/graphql/schemas.py +27 -16
  37. schemathesis/specs/openapi/_hypothesis.py +83 -68
  38. schemathesis/specs/openapi/adapter/__init__.py +10 -0
  39. schemathesis/specs/openapi/adapter/parameters.py +504 -0
  40. schemathesis/specs/openapi/adapter/protocol.py +57 -0
  41. schemathesis/specs/openapi/adapter/references.py +19 -0
  42. schemathesis/specs/openapi/adapter/responses.py +329 -0
  43. schemathesis/specs/openapi/adapter/security.py +141 -0
  44. schemathesis/specs/openapi/adapter/v2.py +28 -0
  45. schemathesis/specs/openapi/adapter/v3_0.py +28 -0
  46. schemathesis/specs/openapi/adapter/v3_1.py +28 -0
  47. schemathesis/specs/openapi/checks.py +99 -90
  48. schemathesis/specs/openapi/converter.py +114 -27
  49. schemathesis/specs/openapi/examples.py +210 -168
  50. schemathesis/specs/openapi/negative/__init__.py +12 -7
  51. schemathesis/specs/openapi/negative/mutations.py +68 -40
  52. schemathesis/specs/openapi/references.py +2 -175
  53. schemathesis/specs/openapi/schemas.py +142 -490
  54. schemathesis/specs/openapi/serialization.py +15 -7
  55. schemathesis/specs/openapi/stateful/__init__.py +17 -12
  56. schemathesis/specs/openapi/stateful/inference.py +13 -11
  57. schemathesis/specs/openapi/stateful/links.py +5 -20
  58. schemathesis/specs/openapi/types/__init__.py +3 -0
  59. schemathesis/specs/openapi/types/v3.py +68 -0
  60. schemathesis/specs/openapi/utils.py +1 -13
  61. schemathesis/transport/requests.py +3 -11
  62. schemathesis/transport/serialization.py +63 -27
  63. schemathesis/transport/wsgi.py +1 -8
  64. {schemathesis-4.1.4.dist-info → schemathesis-4.2.0.dist-info}/METADATA +2 -2
  65. {schemathesis-4.1.4.dist-info → schemathesis-4.2.0.dist-info}/RECORD +68 -53
  66. schemathesis/specs/openapi/parameters.py +0 -405
  67. schemathesis/specs/openapi/security.py +0 -162
  68. {schemathesis-4.1.4.dist-info → schemathesis-4.2.0.dist-info}/WHEEL +0 -0
  69. {schemathesis-4.1.4.dist-info → schemathesis-4.2.0.dist-info}/entry_points.txt +0 -0
  70. {schemathesis-4.1.4.dist-info → schemathesis-4.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,329 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import TYPE_CHECKING, Any, ItemsView, Iterator, Mapping, cast
5
+
6
+ from schemathesis.core import NOT_SET, NotSet
7
+ from schemathesis.core.compat import RefResolutionError, RefResolver
8
+ from schemathesis.core.errors import InvalidSchema
9
+ from schemathesis.core.jsonschema.bundler import bundle
10
+ from schemathesis.core.jsonschema.types import JsonSchema
11
+ from schemathesis.specs.openapi import types
12
+ from schemathesis.specs.openapi.adapter.protocol import SpecificationAdapter
13
+ from schemathesis.specs.openapi.adapter.references import maybe_resolve
14
+ from schemathesis.specs.openapi.converter import to_json_schema
15
+ from schemathesis.specs.openapi.utils import expand_status_code
16
+
17
+ if TYPE_CHECKING:
18
+ from jsonschema.protocols import Validator
19
+
20
+
21
+ @dataclass
22
+ class OpenApiResponse:
23
+ """OpenAPI response definition."""
24
+
25
+ status_code: str
26
+ definition: Mapping[str, Any]
27
+ resolver: RefResolver
28
+ scope: str
29
+ adapter: SpecificationAdapter
30
+
31
+ __slots__ = ("status_code", "definition", "resolver", "scope", "adapter", "_schema", "_validator", "_headers")
32
+
33
+ def __post_init__(self) -> None:
34
+ self._schema: JsonSchema | None | NotSet = NOT_SET
35
+ self._validator: Validator | NotSet = NOT_SET
36
+ self._headers: OpenApiResponseHeaders | NotSet = NOT_SET
37
+
38
+ @property
39
+ def schema(self) -> JsonSchema | None:
40
+ """The response body schema extracted from its definition.
41
+
42
+ Returns `None` if the response has no schema.
43
+ """
44
+ if self._schema is NOT_SET:
45
+ self._schema = self.adapter.extract_response_schema(
46
+ self.definition, self.resolver, self.scope, self.adapter.nullable_keyword
47
+ )
48
+ assert not isinstance(self._schema, NotSet)
49
+ return self._schema
50
+
51
+ @property
52
+ def validator(self) -> Validator | None:
53
+ """JSON Schema validator for this response."""
54
+ from jsonschema import Draft202012Validator
55
+
56
+ schema = self.schema
57
+ if schema is None:
58
+ return None
59
+ if self._validator is NOT_SET:
60
+ self.adapter.jsonschema_validator_cls.check_schema(schema)
61
+ self._validator = self.adapter.jsonschema_validator_cls(
62
+ schema,
63
+ # Use a recent JSON Schema format checker to get most of formats checked for older drafts as well
64
+ format_checker=Draft202012Validator.FORMAT_CHECKER,
65
+ resolver=RefResolver.from_schema(schema),
66
+ )
67
+ assert not isinstance(self._validator, NotSet)
68
+ return self._validator
69
+
70
+ @property
71
+ def headers(self) -> OpenApiResponseHeaders:
72
+ """A collection of header definitions for this response."""
73
+ if self._headers is NOT_SET:
74
+ headers = self.definition.get("headers", {})
75
+ self._headers = OpenApiResponseHeaders(
76
+ dict(_iter_resolved_headers(headers, self.resolver, self.scope, self.adapter))
77
+ )
78
+ assert not isinstance(self._headers, NotSet)
79
+ return self._headers
80
+
81
+ def iter_examples(self) -> Iterator[tuple[str, object]]:
82
+ """Iterate over examples of this response."""
83
+ return self.adapter.iter_response_examples(self.definition, self.status_code)
84
+
85
+ def iter_links(self) -> Iterator[tuple[str, Mapping[str, Any]]]:
86
+ links = self.definition.get(self.adapter.links_keyword)
87
+ if links is None:
88
+ return
89
+ for name, link in links.items():
90
+ _, link = maybe_resolve(link, self.resolver, self.scope)
91
+ yield name, link
92
+
93
+
94
+ @dataclass
95
+ class OpenApiResponses:
96
+ """Collection of OpenAPI response definitions."""
97
+
98
+ _inner: dict[str, OpenApiResponse]
99
+ resolver: RefResolver
100
+ scope: str
101
+ adapter: SpecificationAdapter
102
+
103
+ __slots__ = ("_inner", "resolver", "scope", "adapter")
104
+
105
+ @classmethod
106
+ def from_definition(
107
+ cls, definition: types.v3.Responses, resolver: RefResolver, scope: str, adapter: SpecificationAdapter
108
+ ) -> OpenApiResponses:
109
+ """Build new collection of responses from their raw definition."""
110
+ # TODO: Add also `v2` type
111
+ return cls(
112
+ dict(_iter_resolved_responses(definition=definition, resolver=resolver, scope=scope, adapter=adapter)),
113
+ resolver=resolver,
114
+ scope=scope,
115
+ adapter=adapter,
116
+ )
117
+
118
+ def items(self) -> ItemsView[str, OpenApiResponse]:
119
+ return self._inner.items()
120
+
121
+ def add(self, status_code: str, definition: dict[str, Any]) -> OpenApiResponse:
122
+ instance = OpenApiResponse(
123
+ status_code=status_code,
124
+ definition=definition,
125
+ resolver=self.resolver,
126
+ scope=self.scope,
127
+ adapter=self.adapter,
128
+ )
129
+ self._inner[status_code] = instance
130
+ return instance
131
+
132
+ @property
133
+ def status_codes(self) -> tuple[str, ...]:
134
+ """All defined status codes."""
135
+ # Defined as a tuple, so it can be used in a cache key
136
+ return tuple(self._inner)
137
+
138
+ def find_by_status_code(self, status_code: int) -> OpenApiResponse | None:
139
+ """Find the most specific response definition matching the given HTTP status code."""
140
+ responses = self._inner
141
+ # Full match has the highest priority
142
+ full_match = responses.get(str(status_code))
143
+ if full_match is not None:
144
+ return full_match
145
+ # Then, ones with wildcards
146
+ keys = sorted(responses, key=lambda k: k.count("X"))
147
+ for key in keys:
148
+ if key == "default":
149
+ continue
150
+ status_codes = expand_status_code(key)
151
+ if status_code in status_codes:
152
+ return responses[key]
153
+ # The default response has the lowest priority
154
+ return responses.get("default")
155
+
156
+ def iter_examples(self) -> Iterator[tuple[str, object]]:
157
+ """Iterate over all examples for all responses."""
158
+ for response in self._inner.values():
159
+ # Check only 2xx responses
160
+ if response.status_code.startswith("2"):
161
+ yield from response.iter_examples()
162
+
163
+
164
+ def _iter_resolved_responses(
165
+ definition: types.v3.Responses, resolver: RefResolver, scope: str, adapter: SpecificationAdapter
166
+ ) -> Iterator[tuple[str, OpenApiResponse]]:
167
+ for key, response in definition.items():
168
+ status_code = str(key)
169
+ scope, resolved = maybe_resolve(response, resolver, scope)
170
+ yield (
171
+ status_code,
172
+ OpenApiResponse(
173
+ status_code=status_code, definition=resolved, resolver=resolver, scope=scope, adapter=adapter
174
+ ),
175
+ )
176
+
177
+
178
+ def extract_response_schema_v2(
179
+ response: Mapping[str, Any], resolver: RefResolver, scope: str, nullable_keyword: str
180
+ ) -> JsonSchema | None:
181
+ schema = response.get("schema")
182
+ if schema is not None:
183
+ return _prepare_schema(schema, resolver, scope, nullable_keyword)
184
+ return None
185
+
186
+
187
+ def extract_response_schema_v3(
188
+ response: Mapping[str, Any], resolver: RefResolver, scope: str, nullable_keyword: str
189
+ ) -> JsonSchema | None:
190
+ options = iter(response.get("content", {}).values())
191
+ media_type = next(options, None)
192
+ # "schema" is an optional key in the `MediaType` object
193
+ if media_type and "schema" in media_type:
194
+ return _prepare_schema(media_type["schema"], resolver, scope, nullable_keyword)
195
+ return None
196
+
197
+
198
+ def _prepare_schema(schema: JsonSchema, resolver: RefResolver, scope: str, nullable_keyword: str) -> JsonSchema:
199
+ schema = _bundle_in_scope(schema, resolver, scope)
200
+ # Do not clone the schema, as bundling already does it
201
+ return to_json_schema(schema, nullable_keyword, is_response_schema=True, update_quantifiers=False, clone=False)
202
+
203
+
204
+ def _bundle_in_scope(schema: JsonSchema, resolver: RefResolver, scope: str) -> JsonSchema:
205
+ resolver.push_scope(scope)
206
+ try:
207
+ return bundle(schema, resolver, inline_recursive=False)
208
+ except RefResolutionError as exc:
209
+ raise InvalidSchema.from_reference_resolution_error(exc, None, None) from None
210
+ finally:
211
+ resolver.pop_scope()
212
+
213
+
214
+ @dataclass
215
+ class OpenApiResponseHeaders:
216
+ """Collection of OpenAPI response header definitions."""
217
+
218
+ _inner: dict[str, OpenApiResponseHeader]
219
+
220
+ __slots__ = ("_inner",)
221
+
222
+ def __bool__(self) -> bool:
223
+ return bool(self._inner)
224
+
225
+ def items(self) -> ItemsView[str, OpenApiResponseHeader]:
226
+ return self._inner.items()
227
+
228
+
229
+ @dataclass
230
+ class OpenApiResponseHeader:
231
+ """OpenAPI response header definition."""
232
+
233
+ name: str
234
+ definition: Mapping[str, Any]
235
+ resolver: RefResolver
236
+ scope: str
237
+ adapter: SpecificationAdapter
238
+
239
+ __slots__ = ("name", "definition", "resolver", "scope", "adapter", "_schema", "_validator")
240
+
241
+ def __post_init__(self) -> None:
242
+ self._schema: JsonSchema | NotSet = NOT_SET
243
+ self._validator: Validator | NotSet = NOT_SET
244
+
245
+ @property
246
+ def is_required(self) -> bool:
247
+ return self.definition.get(self.adapter.header_required_keyword, False)
248
+
249
+ @property
250
+ def schema(self) -> JsonSchema:
251
+ """The header schema extracted from its definition."""
252
+ if self._schema is NOT_SET:
253
+ self._schema = self.adapter.extract_header_schema(
254
+ self.definition, self.resolver, self.scope, self.adapter.nullable_keyword
255
+ )
256
+ assert not isinstance(self._schema, NotSet)
257
+ return self._schema
258
+
259
+ @property
260
+ def validator(self) -> Validator:
261
+ """JSON Schema validator for this header."""
262
+ from jsonschema import Draft202012Validator
263
+
264
+ schema = self.schema
265
+ if self._validator is NOT_SET:
266
+ self.adapter.jsonschema_validator_cls.check_schema(schema)
267
+ self._validator = self.adapter.jsonschema_validator_cls(
268
+ schema,
269
+ # Use a recent JSON Schema format checker to get most of formats checked for older drafts as well
270
+ format_checker=Draft202012Validator.FORMAT_CHECKER,
271
+ resolver=RefResolver.from_schema(schema),
272
+ )
273
+ assert not isinstance(self._validator, NotSet)
274
+ return self._validator
275
+
276
+
277
+ def _iter_resolved_headers(
278
+ definition: types.v3.Headers, resolver: RefResolver, scope: str, adapter: SpecificationAdapter
279
+ ) -> Iterator[tuple[str, OpenApiResponseHeader]]:
280
+ for name, header in definition.items():
281
+ scope, resolved = maybe_resolve(header, resolver, scope)
282
+ yield (
283
+ name,
284
+ OpenApiResponseHeader(name=name, definition=resolved, resolver=resolver, scope=scope, adapter=adapter),
285
+ )
286
+
287
+
288
+ def extract_header_schema_v2(
289
+ header: Mapping[str, Any], resolver: RefResolver, scope: str, nullable_keyword: str
290
+ ) -> JsonSchema:
291
+ return _prepare_schema(cast(dict, header), resolver, scope, nullable_keyword)
292
+
293
+
294
+ def extract_header_schema_v3(
295
+ header: Mapping[str, Any], resolver: RefResolver, scope: str, nullable_keyword: str
296
+ ) -> JsonSchema:
297
+ schema = header.get("schema", {})
298
+ return _prepare_schema(schema, resolver, scope, nullable_keyword)
299
+
300
+
301
+ def iter_response_examples_v2(response: Mapping[str, Any], status_code: str) -> Iterator[tuple[str, object]]:
302
+ # In Swagger 2.0, examples are directly in the response under "examples"
303
+ examples = response.get("examples", {})
304
+ return iter(examples.items())
305
+
306
+
307
+ def iter_response_examples_v3(response: Mapping[str, Any], status_code: str) -> Iterator[tuple[str, object]]:
308
+ for media_type, definition in response.get("content", {}).items():
309
+ # Try to get a more descriptive example name from the `$ref` value
310
+ schema_ref = definition.get("schema", {}).get("$ref")
311
+ if schema_ref:
312
+ name = schema_ref.split("/")[-1]
313
+ else:
314
+ name = f"{status_code}/{media_type}"
315
+
316
+ for examples_container_keyword, example_keyword in (
317
+ ("examples", "example"),
318
+ ("x-examples", "x-example"),
319
+ ):
320
+ examples = definition.get(examples_container_keyword, {})
321
+ if isinstance(examples, dict):
322
+ for example in examples.values():
323
+ if "value" in example:
324
+ yield name, example["value"]
325
+ elif isinstance(examples, list):
326
+ for example in examples:
327
+ yield name, example
328
+ if example_keyword in definition:
329
+ yield name, definition[example_keyword]
@@ -0,0 +1,141 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import TYPE_CHECKING, Any, Iterator, Mapping
5
+
6
+ if TYPE_CHECKING:
7
+ from schemathesis.core.compat import RefResolver
8
+ from schemathesis.specs.openapi.adapter.protocol import SpecificationAdapter
9
+
10
+ ORIGINAL_SECURITY_TYPE_KEY = "x-original-securuty-type"
11
+
12
+
13
+ @dataclass
14
+ class OpenApiSecurityParameters:
15
+ """Security parameters for an API operation."""
16
+
17
+ _parameters: list[Mapping[str, Any]]
18
+
19
+ __slots__ = ("_parameters",)
20
+
21
+ @classmethod
22
+ def from_definition(
23
+ cls,
24
+ schema: Mapping[str, Any],
25
+ operation: Mapping[str, Any],
26
+ resolver: RefResolver,
27
+ adapter: SpecificationAdapter,
28
+ ) -> OpenApiSecurityParameters:
29
+ return cls(list(adapter.extract_security_parameters(schema, operation, resolver)))
30
+
31
+ def iter_parameters(self) -> Iterator[Mapping[str, Any]]:
32
+ return iter(self._parameters)
33
+
34
+
35
+ def extract_security_parameters_v2(
36
+ schema: Mapping[str, Any], operation: Mapping[str, Any], resolver: RefResolver
37
+ ) -> Iterator[Mapping[str, Any]]:
38
+ """Extract all required security parameters for this operation."""
39
+ defined = extract_security_definitions_v2(schema, resolver)
40
+ required = get_security_requirements(schema, operation)
41
+ optional = has_optional_auth(schema, operation)
42
+
43
+ for key in required:
44
+ if key not in defined:
45
+ continue
46
+ definition = defined[key]
47
+ ty = definition["type"]
48
+
49
+ if ty == "apiKey":
50
+ param = make_api_key_schema(definition, type="string")
51
+ elif ty == "basic":
52
+ parameter_schema = make_auth_header_schema(definition)
53
+ param = make_auth_header(**parameter_schema)
54
+ else:
55
+ continue
56
+
57
+ param[ORIGINAL_SECURITY_TYPE_KEY] = ty
58
+
59
+ if optional:
60
+ param = {**param, "required": False}
61
+
62
+ yield param
63
+
64
+
65
+ def extract_security_parameters_v3(
66
+ schema: Mapping[str, Any],
67
+ operation: Mapping[str, Any],
68
+ resolver: RefResolver,
69
+ ) -> Iterator[Mapping[str, Any]]:
70
+ """Extract all required security parameters for this operation."""
71
+ defined = extract_security_definitions_v3(schema, resolver)
72
+ required = get_security_requirements(schema, operation)
73
+ optional = has_optional_auth(schema, operation)
74
+
75
+ for key in required:
76
+ if key not in defined:
77
+ continue
78
+ definition = defined[key]
79
+ ty = definition["type"]
80
+
81
+ if ty == "apiKey":
82
+ param = make_api_key_schema(definition, schema={"type": "string"})
83
+ elif ty == "http":
84
+ parameter_schema = make_auth_header_schema(definition)
85
+ param = make_auth_header(schema=parameter_schema)
86
+ else:
87
+ continue
88
+
89
+ param[ORIGINAL_SECURITY_TYPE_KEY] = ty
90
+
91
+ if optional:
92
+ param = {**param, "required": False}
93
+
94
+ yield param
95
+
96
+
97
+ def make_auth_header_schema(definition: dict[str, Any]) -> dict[str, str]:
98
+ schema = definition.get("scheme", "basic").lower()
99
+ return {"type": "string", "format": f"_{schema}_auth"}
100
+
101
+
102
+ def make_auth_header(**kwargs: Any) -> dict[str, Any]:
103
+ return {"name": "Authorization", "in": "header", "required": True, **kwargs}
104
+
105
+
106
+ def make_api_key_schema(definition: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
107
+ return {"name": definition["name"], "required": True, "in": definition["in"], **kwargs}
108
+
109
+
110
+ def get_security_requirements(schema: Mapping[str, Any], operation: Mapping[str, Any]) -> list[str]:
111
+ requirements = operation.get("security", schema.get("security", []))
112
+ return [key for requirement in requirements for key in requirement]
113
+
114
+
115
+ def has_optional_auth(schema: Mapping[str, Any], operation: Mapping[str, Any]) -> bool:
116
+ return {} in operation.get("security", schema.get("security", []))
117
+
118
+
119
+ def extract_security_definitions_v2(schema: Mapping[str, Any], resolver: RefResolver) -> Mapping[str, Any]:
120
+ return schema.get("securityDefinitions", {})
121
+
122
+
123
+ def extract_security_definitions_v3(schema: Mapping[str, Any], resolver: RefResolver) -> Mapping[str, Any]:
124
+ """In Open API 3 security definitions are located in ``components`` and may have references inside."""
125
+ components = schema.get("components", {})
126
+ security_schemes = components.get("securitySchemes", {})
127
+ # At this point, the resolution scope could differ from the root scope, that's why we need to restore it
128
+ # as now we resolve root-level references
129
+ if len(resolver._scopes_stack) > 1:
130
+ scope = resolver.resolution_scope
131
+ resolver.pop_scope()
132
+ else:
133
+ scope = None
134
+ resolve = resolver.resolve
135
+ try:
136
+ if "$ref" in security_schemes:
137
+ return resolve(security_schemes["$ref"])[1]
138
+ return {key: resolve(value["$ref"])[1] if "$ref" in value else value for key, value in security_schemes.items()}
139
+ finally:
140
+ if scope is not None:
141
+ resolver._scopes_stack.append(scope)
@@ -0,0 +1,28 @@
1
+ from jsonschema import Draft4Validator
2
+
3
+ from schemathesis.specs.openapi.adapter import parameters, responses, security
4
+ from schemathesis.specs.openapi.adapter.protocol import (
5
+ BuildPathParameter,
6
+ ExtractHeaderSchema,
7
+ ExtractParameterSchema,
8
+ ExtractResponseSchema,
9
+ ExtractSecurityParameters,
10
+ IterParameters,
11
+ IterResponseExamples,
12
+ )
13
+
14
+ nullable_keyword = "x-nullable"
15
+ header_required_keyword = "x-required"
16
+ links_keyword = "x-links"
17
+ example_keyword = "x-example"
18
+ examples_container_keyword = "x-examples"
19
+
20
+ extract_parameter_schema: ExtractParameterSchema = parameters.extract_parameter_schema_v2
21
+ extract_response_schema: ExtractResponseSchema = responses.extract_response_schema_v2
22
+ extract_header_schema: ExtractHeaderSchema = responses.extract_header_schema_v2
23
+ iter_parameters: IterParameters = parameters.iter_parameters_v2
24
+ build_path_parameter: BuildPathParameter = parameters.build_path_parameter_v2
25
+ iter_response_examples: IterResponseExamples = responses.iter_response_examples_v2
26
+ extract_security_parameters: ExtractSecurityParameters = security.extract_security_parameters_v2
27
+
28
+ jsonschema_validator_cls = Draft4Validator
@@ -0,0 +1,28 @@
1
+ from jsonschema import Draft4Validator
2
+
3
+ from schemathesis.specs.openapi.adapter import parameters, responses, security
4
+ from schemathesis.specs.openapi.adapter.protocol import (
5
+ BuildPathParameter,
6
+ ExtractHeaderSchema,
7
+ ExtractParameterSchema,
8
+ ExtractResponseSchema,
9
+ ExtractSecurityParameters,
10
+ IterParameters,
11
+ IterResponseExamples,
12
+ )
13
+
14
+ nullable_keyword = "nullable"
15
+ header_required_keyword = "required"
16
+ links_keyword = "links"
17
+ example_keyword = "example"
18
+ examples_container_keyword = "examples"
19
+
20
+ extract_parameter_schema: ExtractParameterSchema = parameters.extract_parameter_schema_v3
21
+ extract_response_schema: ExtractResponseSchema = responses.extract_response_schema_v3
22
+ extract_header_schema: ExtractHeaderSchema = responses.extract_header_schema_v3
23
+ iter_parameters: IterParameters = parameters.iter_parameters_v3
24
+ build_path_parameter: BuildPathParameter = parameters.build_path_parameter_v3_0
25
+ iter_response_examples: IterResponseExamples = responses.iter_response_examples_v3
26
+ extract_security_parameters: ExtractSecurityParameters = security.extract_security_parameters_v3
27
+
28
+ jsonschema_validator_cls = Draft4Validator
@@ -0,0 +1,28 @@
1
+ from jsonschema import Draft202012Validator
2
+
3
+ from schemathesis.specs.openapi.adapter import parameters, responses, security
4
+ from schemathesis.specs.openapi.adapter.protocol import (
5
+ BuildPathParameter,
6
+ ExtractHeaderSchema,
7
+ ExtractParameterSchema,
8
+ ExtractResponseSchema,
9
+ ExtractSecurityParameters,
10
+ IterParameters,
11
+ IterResponseExamples,
12
+ )
13
+
14
+ nullable_keyword = "nullable"
15
+ header_required_keyword = "required"
16
+ links_keyword = "links"
17
+ example_keyword = "example"
18
+ examples_container_keyword = "examples"
19
+
20
+ extract_parameter_schema: ExtractParameterSchema = parameters.extract_parameter_schema_v3
21
+ extract_response_schema: ExtractResponseSchema = responses.extract_response_schema_v3
22
+ extract_header_schema: ExtractHeaderSchema = responses.extract_header_schema_v3
23
+ iter_parameters: IterParameters = parameters.iter_parameters_v3
24
+ build_path_parameter: BuildPathParameter = parameters.build_path_parameter_v3_1
25
+ iter_response_examples: IterResponseExamples = responses.iter_response_examples_v3
26
+ extract_security_parameters: ExtractSecurityParameters = security.extract_security_parameters_v3
27
+
28
+ jsonschema_validator_cls = Draft202012Validator