schemathesis 3.39.1__py3-none-any.whl → 3.39.3__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.
@@ -199,21 +199,26 @@ def add_examples(
199
199
  if invalid_headers:
200
200
  add_invalid_example_header_mark(original_test, invalid_headers)
201
201
  continue
202
- if example.media_type is not None:
203
- try:
204
- media_type = parse_content_type(example.media_type)
205
- if media_type == ("application", "x-www-form-urlencoded"):
206
- example.body = prepare_urlencoded(example.body)
207
- except ValueError:
208
- pass
202
+ adjust_urlencoded_payload(example)
209
203
  test = hypothesis.example(case=example)(test)
210
204
  return test
211
205
 
212
206
 
207
+ def adjust_urlencoded_payload(case: Case) -> None:
208
+ if case.media_type is not None:
209
+ try:
210
+ media_type = parse_content_type(case.media_type)
211
+ if media_type == ("application", "x-www-form-urlencoded"):
212
+ case.body = prepare_urlencoded(case.body)
213
+ except ValueError:
214
+ pass
215
+
216
+
213
217
  def add_coverage(
214
218
  test: Callable, operation: APIOperation, data_generation_methods: list[DataGenerationMethod]
215
219
  ) -> Callable:
216
220
  for example in _iter_coverage_cases(operation, data_generation_methods):
221
+ adjust_urlencoded_payload(example)
217
222
  test = hypothesis.example(case=example)(test)
218
223
  return test
219
224
 
@@ -322,7 +327,7 @@ def _iter_coverage_cases(
322
327
  case = operation.make_case(**template)
323
328
  case._explicit_method = method
324
329
  case.data_generation_method = DataGenerationMethod.negative
325
- case.meta = _make_meta(description=f"Unspecified HTTP method: {method}")
330
+ case.meta = _make_meta(description=f"Unspecified HTTP method: {method.upper()}")
326
331
  yield case
327
332
  # Generate duplicate query parameters
328
333
  if operation.query:
@@ -518,7 +523,7 @@ def prepare_urlencoded(data: Any) -> Any:
518
523
  for key, value in item.items():
519
524
  output.append((key, value))
520
525
  else:
521
- output.append(item)
526
+ output.append((item, "arbitrary-value"))
522
527
  return output
523
528
  return data
524
529
 
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
24
24
  @dataclass
25
25
  class JunitXMLHandler(EventHandler):
26
26
  file_handle: LazyFile
27
- test_cases: list = field(default_factory=list)
27
+ test_cases: dict = field(default_factory=dict)
28
28
 
29
29
  def handle_event(self, context: ExecutionContext, event: events.ExecutionEvent) -> None:
30
30
  if isinstance(event, (events.AfterExecution, events.AfterStatefulExecution)):
@@ -33,23 +33,31 @@ class JunitXMLHandler(EventHandler):
33
33
  name = f"{event_.result.method} {event_.result.path}"
34
34
  else:
35
35
  name = event_.result.verbose_name
36
- test_case = TestCase(name, elapsed_sec=event_.elapsed_time, allow_multiple_subelements=True)
36
+ if name in self.test_cases:
37
+ test_case = self.test_cases[name]
38
+ test_case.elapsed_sec += event_.elapsed_time
39
+ else:
40
+ test_case = TestCase(name, elapsed_sec=event_.elapsed_time, allow_multiple_subelements=True)
37
41
  if event_.status == Status.failure:
38
42
  _add_failure(test_case, event_.result.checks, context)
39
43
  elif event_.status == Status.error:
40
- test_case.add_error_info(message=build_error_message(context, event_.result.errors[-1]))
44
+ test_case.add_error_info(output=build_error_message(context, event_.result.errors[-1]))
41
45
  elif event_.status == Status.skip:
42
- test_case.add_skipped_info(message=event_.result.skip_reason)
43
- self.test_cases.append(test_case)
46
+ test_case.add_skipped_info(output=event_.result.skip_reason)
47
+ self.test_cases[name] = test_case
44
48
  elif isinstance(event, events.Finished):
45
- test_suites = [TestSuite("schemathesis", test_cases=self.test_cases, hostname=platform.node())]
49
+ test_suites = [
50
+ TestSuite("schemathesis", test_cases=list(self.test_cases.values()), hostname=platform.node())
51
+ ]
46
52
  to_xml_report_file(file_descriptor=self.file_handle, test_suites=test_suites, prettyprint=True)
47
53
 
48
54
 
49
55
  def _add_failure(test_case: TestCase, checks: list[SerializedCheck], context: ExecutionContext) -> None:
56
+ messages = []
50
57
  for idx, (code_sample, group) in enumerate(group_by_case(checks, context.code_sample_style), 1):
51
58
  checks = sorted(group, key=lambda c: c.name != "not_a_server_error")
52
- test_case.add_failure_info(message=build_failure_message(context, idx, code_sample, checks))
59
+ messages.append(build_failure_message(context, idx, code_sample, checks))
60
+ test_case.add_failure_info(message="\n\n".join(messages))
53
61
 
54
62
 
55
63
  def build_failure_message(context: ExecutionContext, idx: int, code_sample: str, checks: list[SerializedCheck]) -> str:
schemathesis/models.py CHANGED
@@ -632,6 +632,7 @@ class Case:
632
632
  id=self.id,
633
633
  _auth=self._auth,
634
634
  _has_explicit_auth=self._has_explicit_auth,
635
+ _explicit_method=self._explicit_method,
635
636
  )
636
637
 
637
638
 
@@ -317,7 +317,7 @@ def use_after_free(ctx: CheckContext, response: GenericResponse, original: Case)
317
317
 
318
318
  if not isinstance(original.operation.schema, BaseOpenAPISchema):
319
319
  return True
320
- if response.status_code == 404 or not original.source:
320
+ if response.status_code == 404 or not original.source or response.status_code >= 500:
321
321
  return None
322
322
  response = original.source.response
323
323
  case = original.source.case
@@ -160,6 +160,9 @@ class BaseOpenAPISchema(BaseSchema):
160
160
  ) -> bool:
161
161
  if method not in HTTP_METHODS:
162
162
  return True
163
+ if self.filter_set.is_empty():
164
+ return False
165
+ path = self.get_full_path(path)
163
166
  # Attribute assignment is way faster than creating a new namespace every time
164
167
  operation = _ctx_cache.operation
165
168
  operation.method = method
@@ -175,17 +178,15 @@ class BaseOpenAPISchema(BaseSchema):
175
178
  paths = self.raw_schema["paths"]
176
179
  except KeyError:
177
180
  return
178
- get_full_path = self.get_full_path
179
181
  resolve = self.resolver.resolve
180
182
  should_skip = self._should_skip
181
183
  for path, path_item in paths.items():
182
- full_path = get_full_path(path)
183
184
  try:
184
185
  if "$ref" in path_item:
185
186
  _, path_item = resolve(path_item["$ref"])
186
187
  # Straightforward iteration is faster than converting to a set & calculating length.
187
188
  for method, definition in path_item.items():
188
- if should_skip(full_path, method, definition):
189
+ if should_skip(path, method, definition):
189
190
  continue
190
191
  yield definition
191
192
  except SCHEMA_PARSING_ERRORS:
@@ -282,7 +283,6 @@ class BaseOpenAPISchema(BaseSchema):
282
283
 
283
284
  context = HookContext()
284
285
  # Optimization: local variables are faster than attribute access
285
- get_full_path = self.get_full_path
286
286
  dispatch_hook = self.dispatch_hook
287
287
  resolve_path_item = self._resolve_path_item
288
288
  resolve_shared_parameters = self._resolve_shared_parameters
@@ -294,7 +294,6 @@ class BaseOpenAPISchema(BaseSchema):
294
294
  for path, path_item in paths.items():
295
295
  method = None
296
296
  try:
297
- full_path = get_full_path(path) # Should be available for later use
298
297
  dispatch_hook("before_process_path", context, path, path_item)
299
298
  scope, path_item = resolve_path_item(path_item)
300
299
  with in_scope(self.resolver, scope):
@@ -304,7 +303,7 @@ class BaseOpenAPISchema(BaseSchema):
304
303
  continue
305
304
  try:
306
305
  resolved = resolve_operation(entry)
307
- if should_skip(full_path, method, resolved):
306
+ if should_skip(path, method, resolved):
308
307
  continue
309
308
  parameters = resolved.get("parameters", ())
310
309
  parameters = collect_parameters(itertools.chain(parameters, shared_parameters), resolved)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 3.39.1
3
+ Version: 3.39.3
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
@@ -41,7 +41,7 @@ Requires-Dist: hypothesis[zoneinfo]<7,>=6.103.4; python_version == '3.8'
41
41
  Requires-Dist: jsonschema[format]<5.0,>=4.18.0
42
42
  Requires-Dist: junit-xml<2.0,>=1.9
43
43
  Requires-Dist: pyrate-limiter<4.0,>=2.10
44
- Requires-Dist: pytest-subtests<0.14.0,>=0.2.1
44
+ Requires-Dist: pytest-subtests<0.15.0,>=0.2.1
45
45
  Requires-Dist: pytest<9,>=4.6.4
46
46
  Requires-Dist: pyyaml<7.0,>=5.1
47
47
  Requires-Dist: requests<3,>=2.22
@@ -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=PsmomVk_mXZaqhOZJh5qftYSJ7qJs3wwBTSITiBXvT0,24273
4
+ schemathesis/_hypothesis.py,sha256=UTvx-hN-kUMZqBPDcDrg4KFbGfQLLMfMCtD82OSmv_k,24401
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=p5AXgjVGtka0jn9MOeyBaRUtNbqZTs4iaJqytYTacHc,14856
19
19
  schemathesis/lazy.py,sha256=Ddhkk7Tpc_VcRGYkCtKDmP2gpjxVmEZ3b01ZTNjbm8I,19004
20
20
  schemathesis/loaders.py,sha256=MoEhcdOEBJxNRn5X-ZNhWB9jZDHQQNpkNfEdQjf_NDw,4590
21
- schemathesis/models.py,sha256=QNeK1sGcNAhrJ452YZoLZIRsOHS6cOt1AYFLJhBPcJs,49962
21
+ schemathesis/models.py,sha256=4MX3ErKMdueUXGcVPZuvMTbesUglbuj0ukgCmg3nhP8,50014
22
22
  schemathesis/parameters.py,sha256=izlu4MFYT1RWrC4RBxrV6weeCal-ODbdLQLMb0PYCZY,2327
23
23
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  schemathesis/sanitization.py,sha256=Lycn1VVfula9B6XpzkxTHja7CZ7RHqbUh9kBic0Yi4M,9056
@@ -36,7 +36,7 @@ schemathesis/cli/constants.py,sha256=wk-0GsoJIel8wFFerQ6Kf_6eAYUtIWkwMFwyAqv3yj4
36
36
  schemathesis/cli/context.py,sha256=j_lvYQiPa6Q7P4P_IGCM9V2y2gJSpDbpxIIzR5oFB2I,2567
37
37
  schemathesis/cli/debug.py,sha256=_YA-bX1ujHl4bqQDEum7M-I2XHBTEGbvgkhvcvKhmgU,658
38
38
  schemathesis/cli/handlers.py,sha256=EXSAFe5TQlHANz1AVlSttfsoDT2oeaeFbqq1N7e2udw,467
39
- schemathesis/cli/junitxml.py,sha256=iWbD5G2mzxrLiC24OuGHCLwkgHQg80OXY00stnGaXL0,5054
39
+ schemathesis/cli/junitxml.py,sha256=_psBdqGwH4OKySSWeva41mbgGLav86UnWhQyOt99gnU,5331
40
40
  schemathesis/cli/options.py,sha256=yL7nrzKkbGCc4nQya9wpTW48XGz_OT9hOFrzPxRrDe4,2853
41
41
  schemathesis/cli/reporting.py,sha256=KC3sxSc1u4aFQ-0Q8CQ3G4HTEl7QxlubGnJgNKmVJdQ,3627
42
42
  schemathesis/cli/sanitization.py,sha256=Onw_NWZSom6XTVNJ5NHnC0PAhrYAcGzIXJbsBCzLkn4,1005
@@ -107,7 +107,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
107
107
  schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
108
108
  schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
109
109
  schemathesis/specs/openapi/_hypothesis.py,sha256=nU8UDn1PzGCre4IVmwIuO9-CZv1KJe1fYY0d2BojhSo,22981
110
- schemathesis/specs/openapi/checks.py,sha256=6FMWic9JHF1DsIieYjx5qIdeKeddsw-Jlb7HuK-Ifdw,25318
110
+ schemathesis/specs/openapi/checks.py,sha256=fWtI7rq4wi6qK2E9U_hdJlIyIBVTCB4Klh_3hrCNsps,25349
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
113
113
  schemathesis/specs/openapi/definitions.py,sha256=WTkWwCgTc3OMxfKsqh6YDoGfZMTThSYrHGp8h0vLAK0,93935
@@ -119,7 +119,7 @@ schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9
119
119
  schemathesis/specs/openapi/parameters.py,sha256=LUahlWKCDSlp94v2IA1Q90pyeECgO6FmrqbzCU-9Z0Y,14658
120
120
  schemathesis/specs/openapi/patterns.py,sha256=aEOiJeqI_qcE9bE2Viz6TUA8UppiTHm6QFxrLJryag8,5520
121
121
  schemathesis/specs/openapi/references.py,sha256=euxM02kQGMHh4Ss1jWjOY_gyw_HazafKITIsvOEiAvI,9831
122
- schemathesis/specs/openapi/schemas.py,sha256=MLU2h9DrQNCDkk74MFFSj-8BsKjkJsf9lJQHPxLFVps,53845
122
+ schemathesis/specs/openapi/schemas.py,sha256=JA9SiBnwYg75kYnd4_0CWOuQv_XTfYwuDeGmFe4RtVo,53724
123
123
  schemathesis/specs/openapi/security.py,sha256=Z-6pk2Ga1PTUtBe298KunjVHsNh5A-teegeso7zcPIE,7138
124
124
  schemathesis/specs/openapi/serialization.py,sha256=5qGdFHZ3n80UlbSXrO_bkr4Al_7ci_Z3aSUjZczNDQY,11384
125
125
  schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
@@ -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.39.1.dist-info/METADATA,sha256=nlt5mHbH7Af2CKtH8Ah7flGWMEA5faS72Mo1QVK1v3Y,12956
157
- schemathesis-3.39.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
158
- schemathesis-3.39.1.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
159
- schemathesis-3.39.1.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
160
- schemathesis-3.39.1.dist-info/RECORD,,
156
+ schemathesis-3.39.3.dist-info/METADATA,sha256=pGuuU539A3Wb2FUy6vbkjX0qHjEV8fREory0-ehDFPg,12956
157
+ schemathesis-3.39.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
158
+ schemathesis-3.39.3.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
159
+ schemathesis-3.39.3.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
160
+ schemathesis-3.39.3.dist-info/RECORD,,