schemathesis 3.38.0__py3-none-any.whl → 3.38.2__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.
@@ -232,6 +232,8 @@ def _iter_coverage_cases(
232
232
  phase=TestPhase.COVERAGE,
233
233
  description=None,
234
234
  location=None,
235
+ parameter=None,
236
+ parameter_location=None,
235
237
  )
236
238
  generators: dict[tuple[str, str], Generator[coverage.GeneratedValue, None, None]] = {}
237
239
  template: dict[str, Any] = {}
@@ -276,6 +278,8 @@ def _iter_coverage_cases(
276
278
  case.meta = copy(meta)
277
279
  case.meta.description = value.description
278
280
  case.meta.location = value.location
281
+ case.meta.parameter = body.media_type
282
+ case.meta.parameter_location = "body"
279
283
  yield case
280
284
  for next_value in gen:
281
285
  case = operation.make_case(**{**template, "body": next_value.value, "media_type": body.media_type})
@@ -283,6 +287,8 @@ def _iter_coverage_cases(
283
287
  case.meta = copy(meta)
284
288
  case.meta.description = next_value.description
285
289
  case.meta.location = next_value.location
290
+ case.meta.parameter = body.media_type
291
+ case.meta.parameter_location = "body"
286
292
  yield case
287
293
  elif DataGenerationMethod.positive in data_generation_methods:
288
294
  case = operation.make_case(**template)
@@ -302,7 +308,27 @@ def _iter_coverage_cases(
302
308
  case.meta = copy(meta)
303
309
  case.meta.description = value.description
304
310
  case.meta.location = value.location
311
+ case.meta.parameter = name
312
+ case.meta.parameter_location = location
305
313
  yield case
314
+ # Generate missing required parameters
315
+ if DataGenerationMethod.negative in data_generation_methods:
316
+ for parameter in operation.iter_parameters():
317
+ if parameter.is_required and parameter.location != "path":
318
+ name = parameter.name
319
+ location = parameter.location
320
+ container_name = LOCATION_TO_CONTAINER[location]
321
+ container = template[container_name]
322
+ case = operation.make_case(
323
+ **{**template, container_name: {k: v for k, v in container.items() if k != name}}
324
+ )
325
+ case.data_generation_method = DataGenerationMethod.negative
326
+ case.meta = copy(meta)
327
+ case.meta.description = f"Missing `{name}` at {location}"
328
+ case.meta.location = parameter.location
329
+ case.meta.parameter = name
330
+ case.meta.parameter_location = location
331
+ yield case
306
332
 
307
333
 
308
334
  def find_invalid_headers(headers: Mapping) -> Generator[tuple[str, str], None, None]:
@@ -244,12 +244,24 @@ http_interactions:"""
244
244
  write_double_quoted(stream, interaction.description)
245
245
  else:
246
246
  stream.write("null")
247
- stream.write("\n location: ")
248
247
 
248
+ stream.write("\n location: ")
249
249
  if interaction.location is not None:
250
250
  write_double_quoted(stream, interaction.location)
251
251
  else:
252
252
  stream.write("null")
253
+
254
+ stream.write("\n parameter: ")
255
+ if interaction.parameter is not None:
256
+ write_double_quoted(stream, interaction.parameter)
257
+ else:
258
+ stream.write("null")
259
+
260
+ stream.write("\n parameter_location: ")
261
+ if interaction.parameter_location is not None:
262
+ write_double_quoted(stream, interaction.parameter_location)
263
+ else:
264
+ stream.write("null")
253
265
  stream.write(
254
266
  f"""
255
267
  phase: {phase}
@@ -21,7 +21,7 @@ CheckFunction = Callable[["CheckContext", "GenericResponse", "Case"], Optional[b
21
21
  @dataclass
22
22
  class NegativeDataRejectionConfig:
23
23
  # 5xx will pass through
24
- allowed_statuses: list[str] = field(default_factory=lambda: ["4xx", "5xx"])
24
+ allowed_statuses: list[str] = field(default_factory=lambda: ["400", "401", "403", "404", "422", "5xx"])
25
25
 
26
26
 
27
27
  @dataclass
schemathesis/models.py CHANGED
@@ -158,10 +158,24 @@ class GenerationMetadata:
158
158
  cookies: DataGenerationMethod | None
159
159
  body: DataGenerationMethod | None
160
160
  phase: TestPhase
161
+ # Temporary attributes to carry info specific to the coverage phase
161
162
  description: str | None
162
163
  location: str | None
163
-
164
- __slots__ = ("query", "path_parameters", "headers", "cookies", "body", "phase", "description", "location")
164
+ parameter: str | None
165
+ parameter_location: str | None
166
+
167
+ __slots__ = (
168
+ "query",
169
+ "path_parameters",
170
+ "headers",
171
+ "cookies",
172
+ "body",
173
+ "phase",
174
+ "description",
175
+ "location",
176
+ "parameter",
177
+ "parameter_location",
178
+ )
165
179
 
166
180
 
167
181
  @dataclass(repr=False)
@@ -1073,6 +1087,8 @@ class Interaction:
1073
1087
  # NOTE: It will be better to keep it in a separate attribute
1074
1088
  description: str | None
1075
1089
  location: str | None
1090
+ parameter: str | None
1091
+ parameter_location: str | None
1076
1092
  recorded_at: str = field(default_factory=lambda: datetime.datetime.now(TIMEZONE).isoformat())
1077
1093
 
1078
1094
  @classmethod
@@ -1104,6 +1120,8 @@ class Interaction:
1104
1120
  phase=case.meta.phase if case.meta is not None else None,
1105
1121
  description=case.meta.description if case.meta is not None else None,
1106
1122
  location=case.meta.location if case.meta is not None else None,
1123
+ parameter=case.meta.parameter if case.meta is not None else None,
1124
+ parameter_location=case.meta.parameter_location if case.meta is not None else None,
1107
1125
  )
1108
1126
 
1109
1127
  @classmethod
@@ -1129,6 +1147,8 @@ class Interaction:
1129
1147
  phase=case.meta.phase if case.meta is not None else None,
1130
1148
  description=case.meta.description if case.meta is not None else None,
1131
1149
  location=case.meta.location if case.meta is not None else None,
1150
+ parameter=case.meta.parameter if case.meta is not None else None,
1151
+ parameter_location=case.meta.parameter_location if case.meta is not None else None,
1132
1152
  )
1133
1153
 
1134
1154
 
@@ -398,6 +398,8 @@ class SerializedInteraction:
398
398
  phase: TestPhase | None
399
399
  description: str | None
400
400
  location: str | None
401
+ parameter: str | None
402
+ parameter_location: str | None
401
403
  recorded_at: str
402
404
 
403
405
  @classmethod
@@ -411,6 +413,8 @@ class SerializedInteraction:
411
413
  phase=interaction.phase,
412
414
  description=interaction.description,
413
415
  location=interaction.location,
416
+ parameter=interaction.parameter,
417
+ parameter_location=interaction.parameter_location,
414
418
  recorded_at=interaction.recorded_at,
415
419
  )
416
420
 
@@ -179,6 +179,8 @@ def get_case_strategy(
179
179
  phase=phase,
180
180
  description=None,
181
181
  location=None,
182
+ parameter=None,
183
+ parameter_location=None,
182
184
  ),
183
185
  )
184
186
  auth_context = auths.AuthContext(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: schemathesis
3
- Version: 3.38.0
3
+ Version: 3.38.2
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://schemathesis.readthedocs.io/en/stable/changelog.html
@@ -1,7 +1,7 @@
1
1
  schemathesis/__init__.py,sha256=UW2Bq8hDDkcBeAAA7PzpBFXkOOxkmHox-mfQwzHDjL0,1914
2
2
  schemathesis/_compat.py,sha256=y4RZd59i2NCnZ91VQhnKeMn_8t3SgvLOk2Xm8nymUHY,1837
3
3
  schemathesis/_dependency_versions.py,sha256=pjEkkGAfOQJYNb-9UOo84V8nj_lKHr_TGDVdFwY2UU0,816
4
- schemathesis/_hypothesis.py,sha256=VZp_ttyI1y2Vx_Bu8S1pxZG8iHxA1pFgfP-jduzSjrk,15269
4
+ schemathesis/_hypothesis.py,sha256=-fXguhIC3AoSzgf5ZzQI6W9M7_lSwsf2wTVzbiGAK58,16595
5
5
  schemathesis/_lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
6
6
  schemathesis/_override.py,sha256=TAjYB3eJQmlw9K_xiR9ptt9Wj7if4U7UFlUhGjpBAoM,1625
7
7
  schemathesis/_patches.py,sha256=Hsbpn4UVeXUQD2Kllrbq01CSWsTYENWa0VJTyhX5C2k,895
@@ -18,7 +18,7 @@ schemathesis/graphql.py,sha256=XiuKcfoOB92iLFC8zpz2msLkM0_V0TLdxPNBqrrGZ8w,216
18
18
  schemathesis/hooks.py,sha256=f0AUPxyBenpe1YGIWDY_uwSRoT2mE4Tp4Qase7f0L08,14953
19
19
  schemathesis/lazy.py,sha256=Ddhkk7Tpc_VcRGYkCtKDmP2gpjxVmEZ3b01ZTNjbm8I,19004
20
20
  schemathesis/loaders.py,sha256=MoEhcdOEBJxNRn5X-ZNhWB9jZDHQQNpkNfEdQjf_NDw,4590
21
- schemathesis/models.py,sha256=s69MSs_y3ZNxmAiMl8h4ifuBPc8JW5FZHzDHU8Ebl4A,49204
21
+ schemathesis/models.py,sha256=2kMMJ3JVe4_91uhRxgsZ_G1FOyksxTiYAo52M5asWLA,49868
22
22
  schemathesis/parameters.py,sha256=_LN3NL5XwoRfvjcU8o2ArrNFK9sbBZo25UFdxuywkRw,2425
23
23
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  schemathesis/sanitization.py,sha256=Lycn1VVfula9B6XpzkxTHja7CZ7RHqbUh9kBic0Yi4M,9056
@@ -31,7 +31,7 @@ schemathesis/utils.py,sha256=LwqxqoAKmRiAdj-qUbNmgQgsamc49V5lc5TnOIDuuMA,4904
31
31
  schemathesis/cli/__init__.py,sha256=rAebJYQrORWsl4WR6sLUseJCQQZbDEsaQex52kmn6kI,74536
32
32
  schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,92
33
33
  schemathesis/cli/callbacks.py,sha256=-VA_I_mVma9WxFNtUR8d2KNICKJD5ScayfSdKKPEP5Y,16321
34
- schemathesis/cli/cassettes.py,sha256=ZRWFoJVwrEOymQYlraEFR8blemog1FnpWeZgtMx0kCE,19648
34
+ schemathesis/cli/cassettes.py,sha256=zji-B-uuwyr0Z0BzQX-DLMV6lWb58JtLExcUE1v3m4Y,20153
35
35
  schemathesis/cli/constants.py,sha256=wk-0GsoJIel8wFFerQ6Kf_6eAYUtIWkwMFwyAqv3yj4,1635
36
36
  schemathesis/cli/context.py,sha256=j_lvYQiPa6Q7P4P_IGCM9V2y2gJSpDbpxIIzR5oFB2I,2567
37
37
  schemathesis/cli/debug.py,sha256=_YA-bX1ujHl4bqQDEum7M-I2XHBTEGbvgkhvcvKhmgU,658
@@ -63,7 +63,7 @@ schemathesis/generation/_hypothesis.py,sha256=74fzLPHugZgMQXerWYFAMqCAjtAXz5E4ge
63
63
  schemathesis/generation/_methods.py,sha256=r8oVlJ71_gXcnEhU-byw2E0R2RswQQFm8U7yGErSqbw,1204
64
64
  schemathesis/generation/coverage.py,sha256=hMtISl3fYaTmE78sFCBd42BPJfPvgSEZJztlXnKxTRo,38310
65
65
  schemathesis/internal/__init__.py,sha256=93HcdG3LF0BbQKbCteOsFMa1w6nXl8yTmx87QLNJOik,161
66
- schemathesis/internal/checks.py,sha256=wUApc22zY6_tAWMEA3kAYLQRwHIhy4AngZYREy0AiPw,2413
66
+ schemathesis/internal/checks.py,sha256=SBx2gesB-XzgVSMX_u7Mb416jSxJ68eQKtcdkWlkyOo,2441
67
67
  schemathesis/internal/copy.py,sha256=DcL56z-d69kKR_5u8mlHvjSL1UTyUKNMAwexrwHFY1s,1031
68
68
  schemathesis/internal/datetime.py,sha256=zPLBL0XXLNfP-KYel3H2m8pnsxjsA_4d-zTOhJg2EPQ,136
69
69
  schemathesis/internal/deprecation.py,sha256=Ty5VBFBlufkITpP0WWTPIPbnB7biDi0kQgXVYWZp820,1273
@@ -77,7 +77,7 @@ schemathesis/internal/validation.py,sha256=G7i8jIMUpAeOnDsDF_eWYvRZe_yMprRswx0QA
77
77
  schemathesis/runner/__init__.py,sha256=b96aoJQo9Kash0GNKI-uCiLMEKOI8cxKjKCKQlWxkUw,21925
78
78
  schemathesis/runner/events.py,sha256=cRKKSDvHvKLBIyFBz-J0JtAKshbGGKco9eaMyLCgzsY,11734
79
79
  schemathesis/runner/probes.py,sha256=no5AfO3kse25qvHevjeUfB0Q3C860V2AYzschUW3QMQ,5688
80
- schemathesis/runner/serialization.py,sha256=SOmdLJSr0YPHptBiqMaiiW3xzXOyBcA5jwiZy-9ZUjY,20593
80
+ schemathesis/runner/serialization.py,sha256=vZi1wd9HX9Swp9VJ_hZFeDgy3Y726URpHra-TbPvQhk,20762
81
81
  schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
82
82
  schemathesis/runner/impl/context.py,sha256=hjJoDHpL9wUXVUGlC-Mx82tUpNAi7qecEB847T-XEvY,3043
83
83
  schemathesis/runner/impl/core.py,sha256=3bCwPcZB1br-clz3oQz8KV9yF9hZK7t3F29ZEq2ErBQ,47642
@@ -106,7 +106,7 @@ schemathesis/specs/graphql/schemas.py,sha256=b7QwglKbcYQCMjuYmqDsVoFu2o4xaA_kduU
106
106
  schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzMSpnVoRWvxy0,1635
107
107
  schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
108
108
  schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
109
- schemathesis/specs/openapi/_hypothesis.py,sha256=uKcWfiiCNcIBLilzUc6EDxll1hv7CTiBz3ZhKtE_-j4,22916
109
+ schemathesis/specs/openapi/_hypothesis.py,sha256=nU8UDn1PzGCre4IVmwIuO9-CZv1KJe1fYY0d2BojhSo,22981
110
110
  schemathesis/specs/openapi/checks.py,sha256=ugo7-6iAu2fX8OmQgyvSunMO9Nt9cr6PNdT3vyX8Z4I,23914
111
111
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
112
112
  schemathesis/specs/openapi/converter.py,sha256=Yxw9lS_JKEyi-oJuACT07fm04bqQDlAu-iHwzkeDvE4,3546
@@ -153,8 +153,8 @@ schemathesis/transports/auth.py,sha256=urSTO9zgFO1qU69xvnKHPFQV0SlJL3d7_Ojl0tLnZ
153
153
  schemathesis/transports/content_types.py,sha256=MiKOm-Hy5i75hrROPdpiBZPOTDzOwlCdnthJD12AJzI,2187
154
154
  schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
155
155
  schemathesis/transports/responses.py,sha256=OFD4ZLqwEFpo7F9vaP_SVgjhxAqatxIj38FS4XVq8Qs,1680
156
- schemathesis-3.38.0.dist-info/METADATA,sha256=xtyRXDtAqdBhey-HDZvagpAMxwIucdSFY6n4wSpyr_k,12956
157
- schemathesis-3.38.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
158
- schemathesis-3.38.0.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
159
- schemathesis-3.38.0.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
160
- schemathesis-3.38.0.dist-info/RECORD,,
156
+ schemathesis-3.38.2.dist-info/METADATA,sha256=hqeX6MagooG7ljuzUgKYAIxgixMTXQj0xmAy3bC-VJw,12956
157
+ schemathesis-3.38.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
158
+ schemathesis-3.38.2.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
159
+ schemathesis-3.38.2.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
160
+ schemathesis-3.38.2.dist-info/RECORD,,