schemathesis 4.3.5__py3-none-any.whl → 4.3.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.
Potentially problematic release.
This version of schemathesis might be problematic. Click here for more details.
- schemathesis/config/_phases.py +1 -1
- schemathesis/generation/case.py +5 -1
- schemathesis/specs/openapi/stateful/dependencies/models.py +7 -7
- schemathesis/specs/openapi/stateful/dependencies/naming.py +25 -6
- schemathesis/specs/openapi/stateful/dependencies/resources.py +26 -0
- {schemathesis-4.3.5.dist-info → schemathesis-4.3.7.dist-info}/METADATA +1 -1
- {schemathesis-4.3.5.dist-info → schemathesis-4.3.7.dist-info}/RECORD +10 -10
- {schemathesis-4.3.5.dist-info → schemathesis-4.3.7.dist-info}/WHEEL +0 -0
- {schemathesis-4.3.5.dist-info → schemathesis-4.3.7.dist-info}/entry_points.txt +0 -0
- {schemathesis-4.3.5.dist-info → schemathesis-4.3.7.dist-info}/licenses/LICENSE +0 -0
schemathesis/config/_phases.py
CHANGED
|
@@ -102,7 +102,7 @@ class CoveragePhaseConfig(DiffBase):
|
|
|
102
102
|
) -> None:
|
|
103
103
|
self.enabled = enabled
|
|
104
104
|
self.generate_duplicate_query_parameters = generate_duplicate_query_parameters
|
|
105
|
-
self.unexpected_methods = unexpected_methods
|
|
105
|
+
self.unexpected_methods = unexpected_methods if unexpected_methods is not None else DEFAULT_UNEXPECTED_METHODS
|
|
106
106
|
self.generation = generation or GenerationConfig()
|
|
107
107
|
self.checks = checks or ChecksConfig()
|
|
108
108
|
self._is_default = (
|
schemathesis/generation/case.py
CHANGED
|
@@ -4,7 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from typing import TYPE_CHECKING, Any, Mapping
|
|
5
5
|
|
|
6
6
|
from schemathesis import transport
|
|
7
|
-
from schemathesis.checks import CHECKS, CheckContext, CheckFunction, run_checks
|
|
7
|
+
from schemathesis.checks import CHECKS, CheckContext, CheckFunction, load_all_checks, run_checks
|
|
8
8
|
from schemathesis.core import NOT_SET, SCHEMATHESIS_TEST_CASE_HEADER, NotSet, curl
|
|
9
9
|
from schemathesis.core.failures import FailureGroup, failure_report_title, format_failures
|
|
10
10
|
from schemathesis.core.transport import Response
|
|
@@ -251,6 +251,10 @@ class Case:
|
|
|
251
251
|
__tracebackhide__ = True
|
|
252
252
|
from requests.structures import CaseInsensitiveDict
|
|
253
253
|
|
|
254
|
+
# In some cases checks may not be loaded.
|
|
255
|
+
# For example - non-Schemathesis tests that manually construct `Case` instances
|
|
256
|
+
load_all_checks()
|
|
257
|
+
|
|
254
258
|
response = Response.from_any(response)
|
|
255
259
|
|
|
256
260
|
config = self.operation.schema.config.checks_config_for(
|
|
@@ -58,7 +58,7 @@ class DependencyGraph:
|
|
|
58
58
|
links: dict[str, LinkDefinition] = {}
|
|
59
59
|
for input_slot in consumer.inputs:
|
|
60
60
|
if input_slot.resource is output_slot.resource:
|
|
61
|
-
body_pointer =
|
|
61
|
+
body_pointer = extend_pointer(
|
|
62
62
|
output_slot.pointer, input_slot.resource_field, output_slot.cardinality
|
|
63
63
|
)
|
|
64
64
|
link_name = f"{consumer.method.capitalize()}{input_slot.resource.name}"
|
|
@@ -127,14 +127,14 @@ class DependencyGraph:
|
|
|
127
127
|
raise AssertionError(message)
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
def
|
|
131
|
-
if not
|
|
132
|
-
|
|
130
|
+
def extend_pointer(base: str, field: str, cardinality: Cardinality) -> str:
|
|
131
|
+
if not base.endswith("/"):
|
|
132
|
+
base += "/"
|
|
133
133
|
if cardinality == Cardinality.MANY:
|
|
134
134
|
# For arrays, reference first element: /data → /data/0
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return
|
|
135
|
+
base += "0/"
|
|
136
|
+
base += encode_pointer(field)
|
|
137
|
+
return base
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
@dataclass
|
|
@@ -4,26 +4,45 @@ from __future__ import annotations
|
|
|
4
4
|
def from_parameter(parameter: str, path: str) -> str | None:
|
|
5
5
|
# TODO: support other naming patterns
|
|
6
6
|
# Named like "userId" -> look for "User" resource
|
|
7
|
-
if parameter.endswith("Id"):
|
|
7
|
+
if parameter.endswith("Id") and len(parameter) > 2:
|
|
8
8
|
return to_pascal_case(parameter[:-2])
|
|
9
9
|
# Named like "user_id" -> look for "User" resource
|
|
10
10
|
elif parameter.endswith("_id"):
|
|
11
11
|
return to_pascal_case(parameter[:-3])
|
|
12
12
|
# Just "id" -> infer from path context
|
|
13
13
|
elif parameter == "id":
|
|
14
|
-
return from_path(path)
|
|
14
|
+
return from_path(path, parameter_name=parameter)
|
|
15
15
|
return None
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def from_path(path: str) -> str | None:
|
|
19
|
-
|
|
18
|
+
def from_path(path: str, parameter_name: str | None = None) -> str | None:
|
|
19
|
+
"""Detect resource name from OpenAPI path."""
|
|
20
|
+
segments = [s for s in path.split("/") if s]
|
|
20
21
|
|
|
21
22
|
if not segments:
|
|
22
23
|
# API Root
|
|
23
24
|
return None
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
# If parameter name provided, find the resource it refers to
|
|
27
|
+
if parameter_name:
|
|
28
|
+
placeholder = f"{{{parameter_name}}}"
|
|
29
|
+
try:
|
|
30
|
+
param_index = segments.index(placeholder)
|
|
31
|
+
if param_index > 0:
|
|
32
|
+
resource_segment = segments[param_index - 1]
|
|
33
|
+
if "{" not in resource_segment:
|
|
34
|
+
singular = to_singular(resource_segment)
|
|
35
|
+
return to_pascal_case(singular)
|
|
36
|
+
except ValueError:
|
|
37
|
+
pass # Parameter not found in path
|
|
38
|
+
|
|
39
|
+
# Fallback to last non-parameter segment
|
|
40
|
+
non_param_segments = [s for s in segments if "{" not in s]
|
|
41
|
+
if non_param_segments:
|
|
42
|
+
singular = to_singular(non_param_segments[-1])
|
|
43
|
+
return to_pascal_case(singular)
|
|
44
|
+
|
|
45
|
+
return None
|
|
27
46
|
|
|
28
47
|
|
|
29
48
|
IRREGULAR_TO_PLURAL = {
|
|
@@ -15,6 +15,7 @@ from schemathesis.specs.openapi.stateful.dependencies.models import (
|
|
|
15
15
|
DefinitionSource,
|
|
16
16
|
ResourceDefinition,
|
|
17
17
|
ResourceMap,
|
|
18
|
+
extend_pointer,
|
|
18
19
|
)
|
|
19
20
|
from schemathesis.specs.openapi.stateful.dependencies.naming import from_path
|
|
20
21
|
from schemathesis.specs.openapi.stateful.dependencies.schemas import (
|
|
@@ -144,6 +145,27 @@ def iter_resources_from_response(
|
|
|
144
145
|
else:
|
|
145
146
|
pointer = unwrapped.pointer
|
|
146
147
|
yield ExtractedResource(resource=resource, cardinality=cardinality, pointer=pointer)
|
|
148
|
+
# Look for sub-resources
|
|
149
|
+
properties = unwrapped.schema.get("properties")
|
|
150
|
+
if isinstance(properties, dict):
|
|
151
|
+
for field, subschema in properties.items():
|
|
152
|
+
if isinstance(subschema, dict):
|
|
153
|
+
reference = subschema.get("$ref")
|
|
154
|
+
if isinstance(reference, str):
|
|
155
|
+
result = _extract_resource_and_cardinality(
|
|
156
|
+
schema=subschema,
|
|
157
|
+
path=path,
|
|
158
|
+
resources=resources,
|
|
159
|
+
updated_resources=updated_resources,
|
|
160
|
+
resolver=resolver,
|
|
161
|
+
parent_ref=reference,
|
|
162
|
+
)
|
|
163
|
+
if result is not None:
|
|
164
|
+
subresource, cardinality = result
|
|
165
|
+
subresource_pointer = extend_pointer(pointer, field, cardinality=cardinality)
|
|
166
|
+
yield ExtractedResource(
|
|
167
|
+
resource=subresource, cardinality=cardinality, pointer=subresource_pointer
|
|
168
|
+
)
|
|
147
169
|
|
|
148
170
|
|
|
149
171
|
def _recover_ref_from_allof(*, branches: list[dict], pointer: str, resolver: RefResolver) -> str | None:
|
|
@@ -264,6 +286,10 @@ def _extract_resource_from_schema(
|
|
|
264
286
|
if resource is None or resource.source < DefinitionSource.SCHEMA_WITH_PROPERTIES:
|
|
265
287
|
_, resolved = maybe_resolve(schema, resolver, "")
|
|
266
288
|
|
|
289
|
+
if "type" in resolved and resolved["type"] != "object" and "properties" not in resolved:
|
|
290
|
+
# Skip strings, etc
|
|
291
|
+
return None
|
|
292
|
+
|
|
267
293
|
properties = resolved.get("properties")
|
|
268
294
|
if properties:
|
|
269
295
|
fields = sorted(properties)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.7
|
|
4
4
|
Summary: Property-based testing framework for Open API and GraphQL based apps
|
|
5
5
|
Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
|
|
6
6
|
Project-URL: Changelog, https://github.com/schemathesis/schemathesis/blob/master/CHANGELOG.md
|
|
@@ -39,7 +39,7 @@ schemathesis/config/_health_check.py,sha256=zC9inla5ibMBlEy5WyM4_TME7ju_KH3Bwfo2
|
|
|
39
39
|
schemathesis/config/_operations.py,sha256=JvfMkieYBkbEmZRb4cTvQLfvHQLhmsxa3GXzgjOtmFc,12383
|
|
40
40
|
schemathesis/config/_output.py,sha256=3G9SOi-4oNcQPHeNRG3HggFCwvcKOW1kF28a9m0H-pU,4434
|
|
41
41
|
schemathesis/config/_parameters.py,sha256=i76Hwaf834fBAMmtKfKTl1SFCicJ-Y-5tZt5QNGW2fA,618
|
|
42
|
-
schemathesis/config/_phases.py,sha256=
|
|
42
|
+
schemathesis/config/_phases.py,sha256=vezsRZAdDmtPcOjwdwAmtdb6Hkkj9gMRsdVKah71Zio,8777
|
|
43
43
|
schemathesis/config/_projects.py,sha256=MpXFBIkNAWAzE_NWQISI9R8dlbCVId2eXGdIqZBgK98,20468
|
|
44
44
|
schemathesis/config/_rate_limit.py,sha256=ekEW-jP_Ichk_O6hYpj-h2TTTKfp7Fm0nyFUbvlWcbA,456
|
|
45
45
|
schemathesis/config/_report.py,sha256=ZECDpaCY4WWHD5UbjvgZoSjLz-rlTvfd5Ivzdgzqf2I,3891
|
|
@@ -92,7 +92,7 @@ schemathesis/engine/phases/unit/__init__.py,sha256=9dDcxyj887pktnE9YDIPNaR-vc7iq
|
|
|
92
92
|
schemathesis/engine/phases/unit/_executor.py,sha256=YDibV3lkC2UMHLvh1FSmnlaQ-SJS-R0MU2qEF4NBbf0,17235
|
|
93
93
|
schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
|
|
94
94
|
schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
|
|
95
|
-
schemathesis/generation/case.py,sha256=
|
|
95
|
+
schemathesis/generation/case.py,sha256=SLMw6zkzmeiZdaIij8_0tjTF70BrMlRSWREaqWii0uM,12508
|
|
96
96
|
schemathesis/generation/coverage.py,sha256=dZYX0gkHDHDenrubVQ58P3ww2xf91fEqk9s54AIokw4,59699
|
|
97
97
|
schemathesis/generation/meta.py,sha256=tXhUZBEdpQMn68uMx1SW8Vv59Uf6Wl6yzs-VB9lu_8o,2589
|
|
98
98
|
schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
|
|
@@ -166,10 +166,10 @@ schemathesis/specs/openapi/stateful/inference.py,sha256=B99jSTDVi2yKxU7-raIb91xp
|
|
|
166
166
|
schemathesis/specs/openapi/stateful/links.py,sha256=SSA66mU50FFBz7e6sA37CfL-Vt0OY3gont72oFSvZYU,8163
|
|
167
167
|
schemathesis/specs/openapi/stateful/dependencies/__init__.py,sha256=0JM-FrY6Awv6gl-qDHaaK7pXbt_GKutBKPyIaph8apA,7842
|
|
168
168
|
schemathesis/specs/openapi/stateful/dependencies/inputs.py,sha256=1qVVIlzx52qsy55Pht9dYNtn2dewRSiHegfrBO1RD8c,10347
|
|
169
|
-
schemathesis/specs/openapi/stateful/dependencies/models.py,sha256=
|
|
170
|
-
schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=
|
|
169
|
+
schemathesis/specs/openapi/stateful/dependencies/models.py,sha256=P1GsX0P8YQboQJDG7DXEksJU279Vt_wYqpHb6uk1Hkg,11280
|
|
170
|
+
schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=HfpkCB1GglX1BAKXer3llvPkQsk8wx0QZhZq7ANcdMM,12214
|
|
171
171
|
schemathesis/specs/openapi/stateful/dependencies/outputs.py,sha256=zvVUfQWNIuhMkKDpz5hsVGkkvkefLt1EswpJAnHajOw,1186
|
|
172
|
-
schemathesis/specs/openapi/stateful/dependencies/resources.py,sha256=
|
|
172
|
+
schemathesis/specs/openapi/stateful/dependencies/resources.py,sha256=p58XoADpMKFAun0Bx_rul-kiUlfA9PXjxHJ97dT2tBE,11202
|
|
173
173
|
schemathesis/specs/openapi/stateful/dependencies/schemas.py,sha256=yMu13RsXIPDeZT1tATTxI1vkpYhjs-XFSFEvx3_Xh_Q,14094
|
|
174
174
|
schemathesis/specs/openapi/types/__init__.py,sha256=VPsWtLJle__Kodw_QqtQ3OuvBzBcCIKsTOrXy3eA7OU,66
|
|
175
175
|
schemathesis/specs/openapi/types/v3.py,sha256=Vondr9Amk6JKCIM6i6RGcmTUjFfPgOOqzBXqerccLpo,1468
|
|
@@ -179,8 +179,8 @@ schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEz
|
|
|
179
179
|
schemathesis/transport/requests.py,sha256=wriRI9fprTplE_qEZLEz1TerX6GwkE3pwr6ZnU2o6vQ,10648
|
|
180
180
|
schemathesis/transport/serialization.py,sha256=GwO6OAVTmL1JyKw7HiZ256tjV4CbrRbhQN0ep1uaZwI,11157
|
|
181
181
|
schemathesis/transport/wsgi.py,sha256=kQtasFre6pjdJWRKwLA_Qb-RyQHCFNpaey9ubzlFWKI,5907
|
|
182
|
-
schemathesis-4.3.
|
|
183
|
-
schemathesis-4.3.
|
|
184
|
-
schemathesis-4.3.
|
|
185
|
-
schemathesis-4.3.
|
|
186
|
-
schemathesis-4.3.
|
|
182
|
+
schemathesis-4.3.7.dist-info/METADATA,sha256=hxCdew3yx_fJyUv0iunB3526jFD0HhlSnKCv9DCXV_o,8540
|
|
183
|
+
schemathesis-4.3.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
184
|
+
schemathesis-4.3.7.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
|
|
185
|
+
schemathesis-4.3.7.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
|
|
186
|
+
schemathesis-4.3.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|