schemathesis 4.3.9__py3-none-any.whl → 4.3.10__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/core/jsonschema/keywords.py +40 -38
- schemathesis/generation/coverage.py +17 -5
- schemathesis/specs/openapi/stateful/dependencies/naming.py +34 -11
- schemathesis/specs/openapi/stateful/dependencies/schemas.py +2 -2
- {schemathesis-4.3.9.dist-info → schemathesis-4.3.10.dist-info}/METADATA +1 -1
- {schemathesis-4.3.9.dist-info → schemathesis-4.3.10.dist-info}/RECORD +9 -9
- {schemathesis-4.3.9.dist-info → schemathesis-4.3.10.dist-info}/WHEEL +0 -0
- {schemathesis-4.3.9.dist-info → schemathesis-4.3.10.dist-info}/entry_points.txt +0 -0
- {schemathesis-4.3.9.dist-info → schemathesis-4.3.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,38 +1,40 @@
|
|
|
1
|
-
ALL_KEYWORDS =
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
1
|
+
ALL_KEYWORDS = frozenset(
|
|
2
|
+
{
|
|
3
|
+
"additionalItems",
|
|
4
|
+
"additionalProperties",
|
|
5
|
+
"allOf",
|
|
6
|
+
"anyOf",
|
|
7
|
+
"const",
|
|
8
|
+
"contains",
|
|
9
|
+
"contentEncoding",
|
|
10
|
+
"contentMediaType",
|
|
11
|
+
"dependencies",
|
|
12
|
+
"enum",
|
|
13
|
+
"else",
|
|
14
|
+
"exclusiveMaximum",
|
|
15
|
+
"exclusiveMinimum",
|
|
16
|
+
"format",
|
|
17
|
+
"if",
|
|
18
|
+
"items",
|
|
19
|
+
"maxItems",
|
|
20
|
+
"maxLength",
|
|
21
|
+
"maxProperties",
|
|
22
|
+
"maximum",
|
|
23
|
+
"minItems",
|
|
24
|
+
"minLength",
|
|
25
|
+
"minProperties",
|
|
26
|
+
"minimum",
|
|
27
|
+
"multipleOf",
|
|
28
|
+
"not",
|
|
29
|
+
"oneOf",
|
|
30
|
+
"pattern",
|
|
31
|
+
"patternProperties",
|
|
32
|
+
"properties",
|
|
33
|
+
"propertyNames",
|
|
34
|
+
"$ref",
|
|
35
|
+
"required",
|
|
36
|
+
"then",
|
|
37
|
+
"type",
|
|
38
|
+
"uniqueItems",
|
|
39
|
+
}
|
|
40
|
+
)
|
|
@@ -8,6 +8,8 @@ from functools import lru_cache, partial
|
|
|
8
8
|
from itertools import combinations
|
|
9
9
|
|
|
10
10
|
from schemathesis.core.jsonschema.bundler import BUNDLE_STORAGE_KEY
|
|
11
|
+
from schemathesis.core.jsonschema.keywords import ALL_KEYWORDS
|
|
12
|
+
from schemathesis.generation.hypothesis.strategies import combine
|
|
11
13
|
|
|
12
14
|
try:
|
|
13
15
|
from json.encoder import _make_iterencode # type: ignore[attr-defined]
|
|
@@ -74,6 +76,14 @@ STRATEGIES_FOR_TYPE = {
|
|
|
74
76
|
"array": ARRAY_STRATEGY,
|
|
75
77
|
"object": OBJECT_STRATEGY,
|
|
76
78
|
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_strategy_for_type(ty: str | list[str]) -> st.SearchStrategy:
|
|
82
|
+
if isinstance(ty, str):
|
|
83
|
+
return STRATEGIES_FOR_TYPE[ty]
|
|
84
|
+
return combine([STRATEGIES_FOR_TYPE[t] for t in ty if t in STRATEGIES_FOR_TYPE])
|
|
85
|
+
|
|
86
|
+
|
|
77
87
|
FORMAT_STRATEGIES = {**BUILT_IN_STRING_FORMATS, **get_default_format_strategies(), **STRING_FORMATS}
|
|
78
88
|
|
|
79
89
|
UNKNOWN_PROPERTY_KEY = "x-schemathesis-unknown-property"
|
|
@@ -269,11 +279,11 @@ class CoverageContext:
|
|
|
269
279
|
if isinstance(schema, bool):
|
|
270
280
|
return 0
|
|
271
281
|
keys = sorted([k for k in schema if not k.startswith("x-") and k not in ["description", "example", "examples"]])
|
|
272
|
-
if keys == ["type"]
|
|
273
|
-
return cached_draw(
|
|
282
|
+
if keys == ["type"]:
|
|
283
|
+
return cached_draw(get_strategy_for_type(schema["type"]))
|
|
274
284
|
if keys == ["format", "type"]:
|
|
275
285
|
if schema["type"] != "string":
|
|
276
|
-
return cached_draw(
|
|
286
|
+
return cached_draw(get_strategy_for_type(schema["type"]))
|
|
277
287
|
elif schema["format"] in FORMAT_STRATEGIES:
|
|
278
288
|
return cached_draw(FORMAT_STRATEGIES[schema["format"]])
|
|
279
289
|
if (keys == ["maxLength", "minLength", "type"] or keys == ["maxLength", "type"]) and schema["type"] == "string":
|
|
@@ -505,12 +515,14 @@ def cover_schema_iter(
|
|
|
505
515
|
# Can't resolve a reference - at this point, we can't generate anything useful as `$ref` is in the current schema root
|
|
506
516
|
return
|
|
507
517
|
|
|
508
|
-
if schema
|
|
518
|
+
if schema is True:
|
|
509
519
|
types = ["null", "boolean", "string", "number", "array", "object"]
|
|
510
520
|
schema = {}
|
|
511
521
|
elif schema is False:
|
|
512
522
|
types = []
|
|
513
523
|
schema = {"not": {}}
|
|
524
|
+
elif not any(k in ALL_KEYWORDS for k in schema):
|
|
525
|
+
types = ["null", "boolean", "string", "number", "array", "object"]
|
|
514
526
|
else:
|
|
515
527
|
types = schema.get("type", [])
|
|
516
528
|
push_examples_to_properties(schema)
|
|
@@ -1320,7 +1332,7 @@ def _negative_type(
|
|
|
1320
1332
|
}.get(ctx.location)
|
|
1321
1333
|
|
|
1322
1334
|
if "number" in types:
|
|
1323
|
-
|
|
1335
|
+
strategies.pop("integer", None)
|
|
1324
1336
|
if "integer" in types:
|
|
1325
1337
|
strategies["number"] = FLOAT_STRATEGY.filter(_is_non_integer_float)
|
|
1326
1338
|
if ctx.location == ParameterLocation.QUERY:
|
|
@@ -2,16 +2,35 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def from_parameter(parameter: str, path: str) -> str | None:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# Named like "user_id" -> look for "User" resource
|
|
10
|
-
elif parameter.endswith("_id"):
|
|
11
|
-
return to_pascal_case(parameter[:-3])
|
|
12
|
-
# Just "id" -> infer from path context
|
|
13
|
-
elif parameter == "id":
|
|
5
|
+
parameter = parameter.strip()
|
|
6
|
+
lower = parameter.lower()
|
|
7
|
+
|
|
8
|
+
if lower == "id":
|
|
14
9
|
return from_path(path, parameter_name=parameter)
|
|
10
|
+
|
|
11
|
+
# Capital-sensitive
|
|
12
|
+
capital_suffixes = ("Id", "Uuid", "Guid")
|
|
13
|
+
for suffix in capital_suffixes:
|
|
14
|
+
if parameter.endswith(suffix):
|
|
15
|
+
prefix = parameter[: -len(suffix)]
|
|
16
|
+
if len(prefix) >= 2:
|
|
17
|
+
return to_pascal_case(prefix)
|
|
18
|
+
|
|
19
|
+
# Snake_case (case-insensitive is fine here)
|
|
20
|
+
snake_suffixes = ("_guid", "_uuid", "_id", "-guid", "-uuid", "-id")
|
|
21
|
+
for suffix in snake_suffixes:
|
|
22
|
+
if lower.endswith(suffix):
|
|
23
|
+
prefix = parameter[: -len(suffix)]
|
|
24
|
+
if len(prefix) >= 2:
|
|
25
|
+
return to_pascal_case(prefix)
|
|
26
|
+
|
|
27
|
+
# Special cases that need exact match
|
|
28
|
+
# Twilio-style, capital S
|
|
29
|
+
if parameter.endswith("Sid"):
|
|
30
|
+
prefix = parameter[:-3]
|
|
31
|
+
if len(prefix) >= 2:
|
|
32
|
+
return to_pascal_case(prefix)
|
|
33
|
+
|
|
15
34
|
return None
|
|
16
35
|
|
|
17
36
|
|
|
@@ -335,8 +354,12 @@ def to_plural(word: str) -> str:
|
|
|
335
354
|
|
|
336
355
|
|
|
337
356
|
def to_pascal_case(text: str) -> str:
|
|
338
|
-
|
|
339
|
-
|
|
357
|
+
# snake_case/kebab-case - split and capitalize each word
|
|
358
|
+
if "_" in text or "-" in text:
|
|
359
|
+
parts = text.replace("-", "_").split("_")
|
|
360
|
+
return "".join(word.capitalize() for word in parts if word)
|
|
361
|
+
# camelCase - just uppercase first letter, preserve the rest
|
|
362
|
+
return text[0].upper() + text[1:] if text else text
|
|
340
363
|
|
|
341
364
|
|
|
342
365
|
def to_snake_case(text: str) -> str:
|
|
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Callable, Mapping
|
|
|
5
5
|
|
|
6
6
|
from schemathesis.core.jsonschema import ALL_KEYWORDS
|
|
7
7
|
from schemathesis.core.jsonschema.bundler import BUNDLE_STORAGE_KEY, bundle
|
|
8
|
-
from schemathesis.core.jsonschema.types import JsonSchema, JsonSchemaObject
|
|
8
|
+
from schemathesis.core.jsonschema.types import JsonSchema, JsonSchemaObject, get_type
|
|
9
9
|
from schemathesis.core.transforms import encode_pointer
|
|
10
10
|
from schemathesis.specs.openapi.adapter.parameters import resource_name_from_ref
|
|
11
11
|
from schemathesis.specs.openapi.adapter.references import maybe_resolve
|
|
@@ -425,7 +425,7 @@ def _detect_externally_tagged_pattern(schema: Mapping[str, Any], path: str) -> s
|
|
|
425
425
|
if name.lower() not in possible_names:
|
|
426
426
|
continue
|
|
427
427
|
|
|
428
|
-
if isinstance(subschema, dict):
|
|
428
|
+
if isinstance(subschema, dict) and "object" in get_type(subschema):
|
|
429
429
|
return name
|
|
430
430
|
|
|
431
431
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 4.3.
|
|
3
|
+
Version: 4.3.10
|
|
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
|
|
@@ -70,7 +70,7 @@ schemathesis/core/validation.py,sha256=b0USkKzkWvdz3jOW1JXYc_TfYshfKZeP7xAUnMqcN
|
|
|
70
70
|
schemathesis/core/version.py,sha256=dOBUWrY3-uA2NQXJp9z7EtZgkR6jYeLg8sMhQCL1mcI,205
|
|
71
71
|
schemathesis/core/jsonschema/__init__.py,sha256=gBZGsXIpK2EFfcp8x0b69dqzWAm2OeZHepKImkkLvoE,320
|
|
72
72
|
schemathesis/core/jsonschema/bundler.py,sha256=a8cQMJ7EQe3eWvS3haS2ZpxOUwzA4PY4OLI0Uyx045A,8472
|
|
73
|
-
schemathesis/core/jsonschema/keywords.py,sha256=
|
|
73
|
+
schemathesis/core/jsonschema/keywords.py,sha256=ssys1lgo4T_-B0VjWTAp91cga1wxwufxlb3-MI75ioY,796
|
|
74
74
|
schemathesis/core/jsonschema/references.py,sha256=c2Q4IKWUbwENNtkbFaqf8r3LLZu6GFE5YLnYQlg5tPg,6069
|
|
75
75
|
schemathesis/core/jsonschema/types.py,sha256=C7f9g8yKFuoxC5_0YNIh8QAyGU0-tj8pzTMfMDjjjVM,1248
|
|
76
76
|
schemathesis/core/output/__init__.py,sha256=SiHqONFskXl73AtP5dV29L14nZoKo7B-IeG52KZB32M,1446
|
|
@@ -93,7 +93,7 @@ schemathesis/engine/phases/unit/_executor.py,sha256=YDibV3lkC2UMHLvh1FSmnlaQ-SJS
|
|
|
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
95
|
schemathesis/generation/case.py,sha256=SLMw6zkzmeiZdaIij8_0tjTF70BrMlRSWREaqWii0uM,12508
|
|
96
|
-
schemathesis/generation/coverage.py,sha256=
|
|
96
|
+
schemathesis/generation/coverage.py,sha256=uUUND4zF17hqs9L1VtNz41KtxcW-BB9JDsrNBA-w2-w,60813
|
|
97
97
|
schemathesis/generation/meta.py,sha256=tXhUZBEdpQMn68uMx1SW8Vv59Uf6Wl6yzs-VB9lu_8o,2589
|
|
98
98
|
schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
|
|
99
99
|
schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
|
|
@@ -167,10 +167,10 @@ schemathesis/specs/openapi/stateful/links.py,sha256=SSA66mU50FFBz7e6sA37CfL-Vt0O
|
|
|
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=PSactImp4OqsYMHUl2gB2pgvUlZCCKJRJKeaalclFzU,11511
|
|
169
169
|
schemathesis/specs/openapi/stateful/dependencies/models.py,sha256=Kl482Hwq2M8lYAdqGmf_8Yje3voSj1WLDUIujRUDWDQ,12286
|
|
170
|
-
schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=
|
|
170
|
+
schemathesis/specs/openapi/stateful/dependencies/naming.py,sha256=NnXEFY1W3i18jEEYGgC_8oLoE7YOxdXgcMYtZvLj10w,12920
|
|
171
171
|
schemathesis/specs/openapi/stateful/dependencies/outputs.py,sha256=zvVUfQWNIuhMkKDpz5hsVGkkvkefLt1EswpJAnHajOw,1186
|
|
172
172
|
schemathesis/specs/openapi/stateful/dependencies/resources.py,sha256=p58XoADpMKFAun0Bx_rul-kiUlfA9PXjxHJ97dT2tBE,11202
|
|
173
|
-
schemathesis/specs/openapi/stateful/dependencies/schemas.py,sha256=
|
|
173
|
+
schemathesis/specs/openapi/stateful/dependencies/schemas.py,sha256=RaG1BJH4D7-o5Qs2rIRQvS8ERntMUEs2I5jXUFaKMRo,14147
|
|
174
174
|
schemathesis/specs/openapi/types/__init__.py,sha256=VPsWtLJle__Kodw_QqtQ3OuvBzBcCIKsTOrXy3eA7OU,66
|
|
175
175
|
schemathesis/specs/openapi/types/v3.py,sha256=Vondr9Amk6JKCIM6i6RGcmTUjFfPgOOqzBXqerccLpo,1468
|
|
176
176
|
schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
|
|
@@ -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.10.dist-info/METADATA,sha256=BrfLLUJxe-ve_0xCRM77F5ksA27XYwnQaS_tf7pawQM,8541
|
|
183
|
+
schemathesis-4.3.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
184
|
+
schemathesis-4.3.10.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
|
|
185
|
+
schemathesis-4.3.10.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
|
|
186
|
+
schemathesis-4.3.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|