schemathesis 3.35.2__py3-none-any.whl → 3.35.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.
@@ -50,17 +50,17 @@ def create_test(
50
50
  auth_storage = get_auth_storage_from_test(test)
51
51
  strategies = []
52
52
  skip_on_not_negated = len(data_generation_methods) == 1 and DataGenerationMethod.negative in data_generation_methods
53
+ as_strategy_kwargs = as_strategy_kwargs or {}
54
+ as_strategy_kwargs.update(
55
+ {
56
+ "hooks": hook_dispatcher,
57
+ "auth_storage": auth_storage,
58
+ "generation_config": generation_config,
59
+ "skip_on_not_negated": skip_on_not_negated,
60
+ }
61
+ )
53
62
  for data_generation_method in data_generation_methods:
54
- strategies.append(
55
- operation.as_strategy(
56
- hooks=hook_dispatcher,
57
- auth_storage=auth_storage,
58
- data_generation_method=data_generation_method,
59
- generation_config=generation_config,
60
- skip_on_not_negated=skip_on_not_negated,
61
- **(as_strategy_kwargs or {}),
62
- )
63
- )
63
+ strategies.append(operation.as_strategy(data_generation_method=data_generation_method, **as_strategy_kwargs))
64
64
  strategy = combine_strategies(strategies)
65
65
  _given_kwargs = (_given_kwargs or {}).copy()
66
66
  _given_kwargs.setdefault("case", strategy)
@@ -125,10 +125,10 @@ def reset_targets() -> None:
125
125
 
126
126
 
127
127
  @click.group(context_settings=CONTEXT_SETTINGS)
128
- @click.option("--pre-run", help="A module to execute before running the tests.", type=str, hidden=True)
128
+ @click.option("--pre-run", help="[DEPRECATED] A module to execute before running the tests", type=str, hidden=True)
129
129
  @click.version_option()
130
130
  def schemathesis(pre_run: str | None = None) -> None:
131
- """Automated API testing employing fuzzing techniques for OpenAPI and GraphQL."""
131
+ """Property-based API testing for OpenAPI and GraphQL."""
132
132
  # Don't use `envvar=HOOKS_MODULE_ENV_VAR` arg to raise a deprecation warning for hooks
133
133
  hooks: str | None
134
134
  if pre_run:
@@ -149,11 +149,18 @@ class CommandWithGroupedOptions(click.Command):
149
149
  for param in self.get_params(ctx):
150
150
  rv = param.get_help_record(ctx)
151
151
  if rv is not None:
152
+ (option_repr, message) = rv
153
+ if isinstance(param.type, click.Choice):
154
+ message += (
155
+ getattr(param.type, "choices_repr", None)
156
+ or f" [possible values: {', '.join(param.type.choices)}]"
157
+ )
158
+
152
159
  if isinstance(param, GroupedOption):
153
160
  group = param.group
154
161
  else:
155
162
  group = "Global options"
156
- groups[group].append(rv)
163
+ groups[group].append((option_repr, message))
157
164
  for group in GROUPS:
158
165
  with formatter.section(group or "Options"):
159
166
  formatter.write_dl(groups[group], col_max=40)
@@ -185,12 +192,12 @@ def grouped_option(*args: Any, **kwargs: Any) -> Callable:
185
192
 
186
193
  with_request_proxy = grouped_option(
187
194
  "--request-proxy",
188
- help="Set the proxy for all network requests.",
195
+ help="Set the proxy for all network requests",
189
196
  type=str,
190
197
  )
191
198
  with_request_tls_verify = grouped_option(
192
199
  "--request-tls-verify",
193
- help="Configures TLS certificate verification for server requests. Can specify path to CA_BUNDLE for custom certs.",
200
+ help="Configures TLS certificate verification for server requests. Can specify path to CA_BUNDLE for custom certs",
194
201
  type=str,
195
202
  default="true",
196
203
  show_default=True,
@@ -200,14 +207,14 @@ with_request_cert = grouped_option(
200
207
  "--request-cert",
201
208
  help="File path of unencrypted client certificate for authentication. "
202
209
  "The certificate can be bundled with a private key (e.g. PEM) or the private "
203
- "key can be provided with the --request-cert-key argument.",
210
+ "key can be provided with the --request-cert-key argument",
204
211
  type=click.Path(exists=True),
205
212
  default=None,
206
213
  show_default=False,
207
214
  )
208
215
  with_request_cert_key = grouped_option(
209
216
  "--request-cert-key",
210
- help="Specifies the file path of the private key for the client certificate.",
217
+ help="Specify the file path of the private key for the client certificate",
211
218
  type=click.Path(exists=True),
212
219
  default=None,
213
220
  show_default=False,
@@ -215,7 +222,7 @@ with_request_cert_key = grouped_option(
215
222
  )
216
223
  with_hosts_file = grouped_option(
217
224
  "--hosts-file",
218
- help="Path to a file to store the Schemathesis.io auth configuration.",
225
+ help="Path to a file to store the Schemathesis.io auth configuration",
219
226
  type=click.Path(dir_okay=False, writable=True),
220
227
  default=service.DEFAULT_HOSTS_PATH,
221
228
  envvar=service.HOSTS_PATH_ENV_VAR,
@@ -262,7 +269,7 @@ REPORT_TO_SERVICE = ReportToService()
262
269
 
263
270
 
264
271
  @schemathesis.command(
265
- short_help="Execute automated tests based on API specifications.",
272
+ short_help="Execute automated tests based on API specifications",
266
273
  cls=CommandWithGroupedOptions,
267
274
  context_settings={"terminal_width": output.default.get_terminal_width(), **CONTEXT_SETTINGS},
268
275
  )
@@ -273,26 +280,27 @@ REPORT_TO_SERVICE = ReportToService()
273
280
  "--workers",
274
281
  "-w",
275
282
  "workers_num",
276
- help="Sets the number of concurrent workers for testing. Auto-adjusts if 'auto' is specified.",
283
+ help="Number of concurrent workers for testing. Auto-adjusts if 'auto' is specified",
277
284
  type=CustomHelpMessageChoice(
278
285
  ["auto"] + list(map(str, range(MIN_WORKERS, MAX_WORKERS + 1))),
279
- choices_repr=f"[auto|{MIN_WORKERS}-{MAX_WORKERS}]",
286
+ choices_repr=f"[auto, {MIN_WORKERS}-{MAX_WORKERS}]",
280
287
  ),
281
288
  default=str(DEFAULT_WORKERS),
282
289
  show_default=True,
283
290
  callback=callbacks.convert_workers,
291
+ metavar="",
284
292
  )
285
293
  @grouped_option(
286
294
  "--dry-run",
287
295
  "dry_run",
288
296
  is_flag=True,
289
297
  default=False,
290
- help="Simulates test execution without making any actual requests, useful for validating data generation.",
298
+ help="Simulate test execution without making any actual requests, useful for validating data generation",
291
299
  )
292
300
  @grouped_option(
293
301
  "--experimental",
294
302
  "experiments",
295
- help="Enable experimental features.",
303
+ help="Enable experimental features",
296
304
  type=click.Choice(
297
305
  [
298
306
  experimental.OPEN_API_3_1.name,
@@ -304,41 +312,41 @@ REPORT_TO_SERVICE = ReportToService()
304
312
  ),
305
313
  callback=callbacks.convert_experimental,
306
314
  multiple=True,
315
+ metavar="",
307
316
  )
308
317
  @grouped_option(
309
318
  "--fixups",
310
- help="Applies compatibility adjustments like 'fast_api', 'utf8_bom'.",
319
+ help="Apply compatibility adjustments",
311
320
  multiple=True,
312
321
  type=click.Choice(list(ALL_FIXUPS) + ["all"]),
322
+ metavar="",
313
323
  )
314
324
  @group("API validation options")
315
325
  @grouped_option(
316
326
  "--checks",
317
327
  "-c",
318
328
  multiple=True,
319
- help="Specifies the validation checks to apply to API responses. "
320
- "Provide a comma-separated list of checks such as 'not_a_server_error,status_code_conformance', etc. "
321
- f"Default is '{','.join(DEFAULT_CHECKS_NAMES)}'.",
329
+ help="Comma-separated list of checks to run against API responses",
322
330
  type=CHECKS_TYPE,
323
331
  default=DEFAULT_CHECKS_NAMES,
324
332
  callback=callbacks.convert_checks,
325
333
  show_default=True,
334
+ metavar="",
326
335
  )
327
336
  @grouped_option(
328
337
  "--exclude-checks",
329
338
  multiple=True,
330
- help="Specifies the validation checks to skip during testing. "
331
- "Provide a comma-separated list of checks you wish to bypass.",
339
+ help="Comma-separated list of checks to skip during testing",
332
340
  type=EXCLUDE_CHECKS_TYPE,
333
341
  default=[],
334
342
  callback=callbacks.convert_checks,
335
343
  show_default=True,
344
+ metavar="",
336
345
  )
337
346
  @grouped_option(
338
347
  "--max-response-time",
339
- help="Sets a custom time limit for API response times. "
340
- "The test will fail if a response time exceeds this limit. "
341
- "Provide the time in milliseconds.",
348
+ help="Time limit in milliseconds for API response times. "
349
+ "The test will fail if a response time exceeds this limit. ",
342
350
  type=click.IntRange(min=1),
343
351
  )
344
352
  @grouped_option(
@@ -347,33 +355,33 @@ REPORT_TO_SERVICE = ReportToService()
347
355
  "exit_first",
348
356
  is_flag=True,
349
357
  default=False,
350
- help="Terminates the test suite immediately upon the first failure or error encountered.",
358
+ help="Terminate the test suite immediately upon the first failure or error encountered",
351
359
  show_default=True,
352
360
  )
353
361
  @grouped_option(
354
362
  "--max-failures",
355
363
  "max_failures",
356
364
  type=click.IntRange(min=1),
357
- help="Terminates the test suite after reaching a specified number of failures or errors.",
365
+ help="Terminate the test suite after reaching a specified number of failures or errors",
358
366
  show_default=True,
359
367
  )
360
368
  @group("Loader options")
361
369
  @grouped_option(
362
370
  "--app",
363
- help="Specifies the WSGI/ASGI application under test, provided as an importable Python path.",
371
+ help="Specify the WSGI/ASGI application under test, provided as an importable Python path",
364
372
  type=str,
365
373
  callback=callbacks.validate_app,
366
374
  )
367
375
  @grouped_option(
368
376
  "--wait-for-schema",
369
- help="Maximum duration, in seconds, to wait for the API schema to become available. Disabled by default.",
377
+ help="Maximum duration, in seconds, to wait for the API schema to become available. Disabled by default",
370
378
  type=click.FloatRange(1.0),
371
379
  default=None,
372
380
  envvar=WAIT_FOR_SCHEMA_ENV_VAR,
373
381
  )
374
382
  @grouped_option(
375
383
  "--validate-schema",
376
- help="Validates the input API schema. Set to 'true' to enable or 'false' to disable.",
384
+ help="Validate input API schema. Set to 'true' to enable or 'false' to disable",
377
385
  type=bool,
378
386
  default=False,
379
387
  show_default=True,
@@ -382,14 +390,14 @@ REPORT_TO_SERVICE = ReportToService()
382
390
  @grouped_option(
383
391
  "--base-url",
384
392
  "-b",
385
- help="Provides the base URL of the API, required when schema is provided as a file.",
393
+ help="Base URL of the API, required when schema is provided as a file",
386
394
  type=str,
387
395
  callback=callbacks.validate_base_url,
388
396
  envvar=BASE_URL_ENV_VAR,
389
397
  )
390
398
  @grouped_option(
391
399
  "--request-timeout",
392
- help="Sets a timeout limit, in milliseconds, for each network request during tests.",
400
+ help="Timeout limit, in milliseconds, for each network request during tests",
393
401
  type=click.IntRange(1),
394
402
  default=DEFAULT_RESPONSE_TIMEOUT,
395
403
  )
@@ -399,8 +407,8 @@ REPORT_TO_SERVICE = ReportToService()
399
407
  @with_request_cert_key
400
408
  @grouped_option(
401
409
  "--rate-limit",
402
- help="Specifies a rate limit for test requests in '<limit>/<duration>' format. "
403
- "Example - `100/m` for 100 requests per minute.",
410
+ help="Specify a rate limit for test requests in '<limit>/<duration>' format. "
411
+ "Example - `100/m` for 100 requests per minute",
404
412
  type=str,
405
413
  callback=callbacks.validate_rate_limit,
406
414
  )
@@ -408,7 +416,7 @@ REPORT_TO_SERVICE = ReportToService()
408
416
  "--header",
409
417
  "-H",
410
418
  "headers",
411
- help=r"Adds a custom HTTP header to all API requests. Format: 'Header-Name: Value'.",
419
+ help=r"Add a custom HTTP header to all API requests. Format: 'Header-Name: Value'",
412
420
  multiple=True,
413
421
  type=str,
414
422
  callback=callbacks.validate_headers,
@@ -416,7 +424,7 @@ REPORT_TO_SERVICE = ReportToService()
416
424
  @grouped_option(
417
425
  "--auth",
418
426
  "-a",
419
- help="Provides the server authentication details in the 'USER:PASSWORD' format.",
427
+ help="Provide the server authentication details in the 'USER:PASSWORD' format",
420
428
  type=str,
421
429
  callback=callbacks.validate_auth,
422
430
  )
@@ -425,8 +433,9 @@ REPORT_TO_SERVICE = ReportToService()
425
433
  "-A",
426
434
  type=click.Choice(["basic", "digest"], case_sensitive=False),
427
435
  default="basic",
428
- help="Specifies the authentication method. Default is 'basic'.",
436
+ help="Specify the authentication method",
429
437
  show_default=True,
438
+ metavar="",
430
439
  )
431
440
  @group("Filtering options")
432
441
  @with_filters
@@ -444,7 +453,7 @@ REPORT_TO_SERVICE = ReportToService()
444
453
  )
445
454
  @grouped_option(
446
455
  "--exclude-deprecated",
447
- help="Exclude deprecated API operations from testing.",
456
+ help="Exclude deprecated API operations from testing",
448
457
  is_flag=True,
449
458
  is_eager=True,
450
459
  default=False,
@@ -456,7 +465,7 @@ REPORT_TO_SERVICE = ReportToService()
456
465
  "endpoints",
457
466
  type=str,
458
467
  multiple=True,
459
- help=r"[DEPRECATED] API operation path pattern (e.g., users/\d+).",
468
+ help=r"[DEPRECATED] API operation path pattern (e.g., users/\d+)",
460
469
  callback=callbacks.validate_regex,
461
470
  hidden=True,
462
471
  )
@@ -466,7 +475,7 @@ REPORT_TO_SERVICE = ReportToService()
466
475
  "methods",
467
476
  type=str,
468
477
  multiple=True,
469
- help="[DEPRECATED] HTTP method (e.g., GET, POST).",
478
+ help="[DEPRECATED] HTTP method (e.g., GET, POST)",
470
479
  callback=callbacks.validate_regex,
471
480
  hidden=True,
472
481
  )
@@ -476,7 +485,7 @@ REPORT_TO_SERVICE = ReportToService()
476
485
  "tags",
477
486
  type=str,
478
487
  multiple=True,
479
- help="[DEPRECATED] Schema tag pattern.",
488
+ help="[DEPRECATED] Schema tag pattern",
480
489
  callback=callbacks.validate_regex,
481
490
  hidden=True,
482
491
  )
@@ -486,13 +495,13 @@ REPORT_TO_SERVICE = ReportToService()
486
495
  "operation_ids",
487
496
  type=str,
488
497
  multiple=True,
489
- help="[DEPRECATED] OpenAPI operationId pattern.",
498
+ help="[DEPRECATED] OpenAPI operationId pattern",
490
499
  callback=callbacks.validate_regex,
491
500
  hidden=True,
492
501
  )
493
502
  @grouped_option(
494
503
  "--skip-deprecated-operations",
495
- help="[DEPRECATED] Exclude deprecated API operations from testing.",
504
+ help="[DEPRECATED] Exclude deprecated API operations from testing",
496
505
  is_flag=True,
497
506
  is_eager=True,
498
507
  default=False,
@@ -502,45 +511,47 @@ REPORT_TO_SERVICE = ReportToService()
502
511
  @group("Output options")
503
512
  @grouped_option(
504
513
  "--junit-xml",
505
- help="Outputs a JUnit-XML style report at the specified file path.",
514
+ help="Output a JUnit-XML style report at the specified file path",
506
515
  type=click.File("w", encoding="utf-8"),
507
516
  )
508
517
  @grouped_option(
509
518
  "--cassette-path",
510
- help="Saves the test outcomes in a VCR-compatible format.",
519
+ help="Save the test outcomes in a VCR-compatible format",
511
520
  type=click.File("w", encoding="utf-8"),
512
521
  is_eager=True,
513
522
  )
514
523
  @grouped_option(
515
524
  "--cassette-format",
516
- help="Format of the saved cassettes.",
525
+ help="Format of the saved cassettes",
517
526
  type=click.Choice([item.name.lower() for item in cassettes.CassetteFormat]),
518
527
  default=cassettes.CassetteFormat.VCR.name.lower(),
519
528
  callback=callbacks.convert_cassette_format,
529
+ metavar="",
520
530
  )
521
531
  @grouped_option(
522
532
  "--cassette-preserve-exact-body-bytes",
523
- help="Retains exact byte sequence of payloads in cassettes, encoded as base64.",
533
+ help="Retain exact byte sequence of payloads in cassettes, encoded as base64",
524
534
  is_flag=True,
525
535
  callback=callbacks.validate_preserve_exact_body_bytes,
526
536
  )
527
537
  @grouped_option(
528
538
  "--code-sample-style",
529
- help="Selects the code sample style for reproducing failures.",
539
+ help="Code sample style for reproducing failures",
530
540
  type=click.Choice([item.name for item in CodeSampleStyle]),
531
541
  default=CodeSampleStyle.default().name,
532
542
  callback=callbacks.convert_code_sample_style,
543
+ metavar="",
533
544
  )
534
545
  @grouped_option(
535
546
  "--sanitize-output",
536
547
  type=bool,
537
548
  default=True,
538
549
  show_default=True,
539
- help="Enable or disable automatic output sanitization to obscure sensitive data.",
550
+ help="Enable or disable automatic output sanitization to obscure sensitive data",
540
551
  )
541
552
  @grouped_option(
542
553
  "--output-truncate",
543
- help="Specifies whether to truncate schemas and responses in error messages.",
554
+ help="Truncate schemas and responses in error messages",
544
555
  type=str,
545
556
  default="true",
546
557
  show_default=True,
@@ -548,7 +559,7 @@ REPORT_TO_SERVICE = ReportToService()
548
559
  )
549
560
  @grouped_option(
550
561
  "--show-trace",
551
- help="Displays complete traceback information for internal errors.",
562
+ help="Display complete traceback information for internal errors",
552
563
  is_flag=True,
553
564
  is_eager=True,
554
565
  default=False,
@@ -556,18 +567,18 @@ REPORT_TO_SERVICE = ReportToService()
556
567
  )
557
568
  @grouped_option(
558
569
  "--debug-output-file",
559
- help="Saves debugging information in a JSONL format at the specified file path.",
570
+ help="Save debugging information in a JSONL format at the specified file path",
560
571
  type=click.File("w", encoding="utf-8"),
561
572
  )
562
573
  @grouped_option(
563
574
  "--store-network-log",
564
- help="[DEPRECATED] Saves the test outcomes in a VCR-compatible format.",
575
+ help="[DEPRECATED] Save the test outcomes in a VCR-compatible format",
565
576
  type=click.File("w", encoding="utf-8"),
566
577
  hidden=True,
567
578
  )
568
579
  @grouped_option(
569
580
  "--show-errors-tracebacks",
570
- help="[DEPRECATED] Displays complete traceback information for internal errors.",
581
+ help="[DEPRECATED] Display complete traceback information for internal errors",
571
582
  is_flag=True,
572
583
  is_eager=True,
573
584
  default=False,
@@ -579,24 +590,25 @@ REPORT_TO_SERVICE = ReportToService()
579
590
  "--data-generation-method",
580
591
  "-D",
581
592
  "data_generation_methods",
582
- help="Specifies the approach Schemathesis uses to generate test data. "
583
- "Use 'positive' for valid data, 'negative' for invalid data, or 'all' for both. "
584
- "Default is 'positive'.",
593
+ help="Specify the approach Schemathesis uses to generate test data. "
594
+ "Use 'positive' for valid data, 'negative' for invalid data, or 'all' for both",
585
595
  type=DATA_GENERATION_METHOD_TYPE,
586
596
  default=DataGenerationMethod.default().name,
587
597
  callback=callbacks.convert_data_generation_method,
588
598
  show_default=True,
599
+ metavar="",
589
600
  )
590
601
  @grouped_option(
591
602
  "--stateful",
592
- help="Enables or disables stateful testing.",
603
+ help="Enable or disable stateful testing",
593
604
  type=click.Choice([item.name for item in Stateful]),
594
605
  default=Stateful.links.name,
595
606
  callback=callbacks.convert_stateful,
607
+ metavar="",
596
608
  )
597
609
  @grouped_option(
598
610
  "--stateful-recursion-limit",
599
- help="Sets the recursion depth limit for stateful testing.",
611
+ help="Recursion depth limit for stateful testing",
600
612
  default=DEFAULT_STATEFUL_RECURSION_LIMIT,
601
613
  show_default=True,
602
614
  type=click.IntRange(1, 100),
@@ -604,7 +616,7 @@ REPORT_TO_SERVICE = ReportToService()
604
616
  )
605
617
  @grouped_option(
606
618
  "--generation-allow-x00",
607
- help="Determines whether to allow the generation of `\x00` bytes within strings.",
619
+ help="Whether to allow the generation of `\x00` bytes within strings",
608
620
  type=str,
609
621
  default="true",
610
622
  show_default=True,
@@ -612,14 +624,14 @@ REPORT_TO_SERVICE = ReportToService()
612
624
  )
613
625
  @grouped_option(
614
626
  "--generation-codec",
615
- help="Specifies the codec used for generating strings.",
627
+ help="The codec used for generating strings",
616
628
  type=str,
617
629
  default="utf-8",
618
630
  callback=callbacks.validate_generation_codec,
619
631
  )
620
632
  @grouped_option(
621
633
  "--generation-with-security-parameters",
622
- help="Whether to generate security parameters.",
634
+ help="Whether to generate security parameters",
623
635
  type=str,
624
636
  default="true",
625
637
  show_default=True,
@@ -627,7 +639,7 @@ REPORT_TO_SERVICE = ReportToService()
627
639
  )
628
640
  @grouped_option(
629
641
  "--generation-graphql-allow-null",
630
- help="Whether `null` values should be used for optional arguments in GraphQL queries.",
642
+ help="Whether to use `null` values for optional arguments in GraphQL queries",
631
643
  type=str,
632
644
  default="true",
633
645
  show_default=True,
@@ -636,7 +648,7 @@ REPORT_TO_SERVICE = ReportToService()
636
648
  @grouped_option(
637
649
  "--contrib-unique-data",
638
650
  "contrib_unique_data",
639
- help="Forces the generation of unique test cases.",
651
+ help="Force the generation of unique test cases",
640
652
  is_flag=True,
641
653
  default=False,
642
654
  show_default=True,
@@ -644,7 +656,7 @@ REPORT_TO_SERVICE = ReportToService()
644
656
  @grouped_option(
645
657
  "--contrib-openapi-formats-uuid",
646
658
  "contrib_openapi_formats_uuid",
647
- help="Enables support for the 'uuid' string format in OpenAPI.",
659
+ help="Enable support for the 'uuid' string format in OpenAPI",
648
660
  is_flag=True,
649
661
  default=False,
650
662
  show_default=True,
@@ -652,7 +664,7 @@ REPORT_TO_SERVICE = ReportToService()
652
664
  @grouped_option(
653
665
  "--contrib-openapi-fill-missing-examples",
654
666
  "contrib_openapi_fill_missing_examples",
655
- help="Enables generation of random examples for API operations that do not have explicit examples defined.",
667
+ help="Enable generation of random examples for API operations that do not have explicit examples",
656
668
  is_flag=True,
657
669
  default=False,
658
670
  show_default=True,
@@ -662,16 +674,18 @@ REPORT_TO_SERVICE = ReportToService()
662
674
  "-t",
663
675
  "targets",
664
676
  multiple=True,
665
- help="Guides input generation to values more likely to expose bugs via targeted property-based testing.",
677
+ help="Guide input generation to values more likely to expose bugs via targeted property-based testing",
666
678
  type=TARGETS_TYPE,
667
679
  default=DEFAULT_TARGETS_NAMES,
668
680
  show_default=True,
681
+ metavar="",
669
682
  )
670
683
  @group("Open API options")
671
684
  @grouped_option(
672
685
  "--force-schema-version",
673
- help="Forces the schema to be interpreted as a particular OpenAPI version.",
686
+ help="Force the schema to be interpreted as a particular OpenAPI version",
674
687
  type=click.Choice(["20", "30"]),
688
+ metavar="",
675
689
  )
676
690
  @grouped_option(
677
691
  "--set-query",
@@ -708,21 +722,21 @@ REPORT_TO_SERVICE = ReportToService()
708
722
  @group("Hypothesis engine options")
709
723
  @grouped_option(
710
724
  "--hypothesis-database",
711
- help="Configures storage for examples discovered by Hypothesis. "
725
+ help="Storage for examples discovered by Hypothesis. "
712
726
  f"Use 'none' to disable, '{HYPOTHESIS_IN_MEMORY_DATABASE_IDENTIFIER}' for temporary storage, "
713
- f"or specify a file path for persistent storage.",
727
+ f"or specify a file path for persistent storage",
714
728
  type=str,
715
729
  callback=callbacks.validate_hypothesis_database,
716
730
  )
717
731
  @grouped_option(
718
732
  "--hypothesis-deadline",
719
- help="Sets a time limit for each test case generated by Hypothesis, in milliseconds. "
720
- "Exceeding this limit will cause the test to fail.",
733
+ help="Time limit for each test case generated by Hypothesis, in milliseconds. "
734
+ "Exceeding this limit will cause the test to fail",
721
735
  type=OptionalInt(1, 5 * 60 * 1000),
722
736
  )
723
737
  @grouped_option(
724
738
  "--hypothesis-derandomize",
725
- help="Enables deterministic mode in Hypothesis, which eliminates random variation between test runs.",
739
+ help="Enables deterministic mode in Hypothesis, which eliminates random variation between tests",
726
740
  is_flag=True,
727
741
  is_eager=True,
728
742
  default=None,
@@ -730,49 +744,52 @@ REPORT_TO_SERVICE = ReportToService()
730
744
  )
731
745
  @grouped_option(
732
746
  "--hypothesis-max-examples",
733
- help="Sets the cap on the number of examples generated by Hypothesis for each API method/path pair.",
747
+ help="The cap on the number of examples generated by Hypothesis for each API operation",
734
748
  type=click.IntRange(1),
735
749
  )
736
750
  @grouped_option(
737
751
  "--hypothesis-phases",
738
- help="Specifies which testing phases to execute.",
752
+ help="Testing phases to execute",
739
753
  type=CsvEnumChoice(Phase),
754
+ metavar="",
740
755
  )
741
756
  @grouped_option(
742
757
  "--hypothesis-no-phases",
743
- help="Specifies which testing phases to exclude from execution.",
758
+ help="Testing phases to exclude from execution",
744
759
  type=CsvEnumChoice(Phase),
760
+ metavar="",
745
761
  )
746
762
  @grouped_option(
747
763
  "--hypothesis-report-multiple-bugs",
748
- help="If set, only the most easily reproducible exception will be reported when multiple issues are found.",
764
+ help="Report only the most easily reproducible error when multiple issues are found",
749
765
  type=bool,
750
766
  )
751
767
  @grouped_option(
752
768
  "--hypothesis-seed",
753
- help="Sets a seed value for Hypothesis, ensuring reproducibility across test runs.",
769
+ help="Seed value for Hypothesis, ensuring reproducibility across test runs",
754
770
  type=int,
755
771
  )
756
772
  @grouped_option(
757
773
  "--hypothesis-suppress-health-check",
758
- help="Disables specified health checks from Hypothesis like 'data_too_large', 'filter_too_much', etc. "
759
- "Provide a comma-separated list",
774
+ help="A comma-separated list of Hypothesis health checks to disable",
760
775
  type=CsvEnumChoice(HealthCheck),
776
+ metavar="",
761
777
  )
762
778
  @grouped_option(
763
779
  "--hypothesis-verbosity",
764
- help="Controls the verbosity level of Hypothesis output.",
780
+ help="Verbosity level of Hypothesis output",
765
781
  type=click.Choice([item.name for item in Verbosity]),
766
782
  callback=callbacks.convert_verbosity,
783
+ metavar="",
767
784
  )
768
785
  @group("Schemathesis.io options")
769
786
  @grouped_option(
770
787
  "--report",
771
788
  "report_value",
772
- help="""Specifies how the generated report should be handled.
789
+ help="""Specify how the generated report should be handled.
773
790
  If used without an argument, the report data will automatically be uploaded to Schemathesis.io.
774
791
  If a file name is provided, the report will be stored in that file.
775
- The report data, consisting of a tar gz file with multiple JSON files, is subject to change.""",
792
+ The report data, consisting of a tar gz file with multiple JSON files, is subject to change""",
776
793
  is_flag=False,
777
794
  flag_value="",
778
795
  envvar=service.REPORT_ENV_VAR,
@@ -780,20 +797,20 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
780
797
  )
781
798
  @grouped_option(
782
799
  "--schemathesis-io-token",
783
- help="Schemathesis.io authentication token.",
800
+ help="Schemathesis.io authentication token",
784
801
  type=str,
785
802
  envvar=service.TOKEN_ENV_VAR,
786
803
  )
787
804
  @grouped_option(
788
805
  "--schemathesis-io-url",
789
- help="Schemathesis.io base URL.",
806
+ help="Schemathesis.io base URL",
790
807
  default=service.DEFAULT_URL,
791
808
  type=str,
792
809
  envvar=service.URL_ENV_VAR,
793
810
  )
794
811
  @grouped_option(
795
812
  "--schemathesis-io-telemetry",
796
- help="Controls whether you send anonymized CLI usage data to Schemathesis.io along with your report.",
813
+ help="Whether to send anonymized usage data to Schemathesis.io along with your report",
797
814
  type=str,
798
815
  default="true",
799
816
  show_default=True,
@@ -802,9 +819,9 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
802
819
  )
803
820
  @with_hosts_file
804
821
  @group("Global options")
805
- @grouped_option("--verbosity", "-v", help="Increase verbosity of the output.", count=True)
806
- @grouped_option("--no-color", help="Disable ANSI color escape codes.", type=bool, is_flag=True)
807
- @grouped_option("--force-color", help="Explicitly tells to enable ANSI color escape codes.", type=bool, is_flag=True)
822
+ @grouped_option("--verbosity", "-v", help="Increase verbosity of the output", count=True)
823
+ @grouped_option("--no-color", help="Disable ANSI color escape codes", type=bool, is_flag=True)
824
+ @grouped_option("--force-color", help="Explicitly tells to enable ANSI color escape codes", type=bool, is_flag=True)
808
825
  @click.pass_context
809
826
  def run(
810
827
  ctx: click.Context,
@@ -909,9 +926,9 @@ def run(
909
926
  ) -> None:
910
927
  """Run tests against an API using a specified SCHEMA.
911
928
 
912
- [Required] SCHEMA: Path to an OpenAPI (`.json`, `.yml`) or GraphQL SDL file, or a URL pointing to such specifications.
929
+ [Required] SCHEMA: Path to an OpenAPI (`.json`, `.yml`) or GraphQL SDL file, or a URL pointing to such specifications
913
930
 
914
- [Optional] API_NAME: Identifier for uploading test data to Schemathesis.io.
931
+ [Optional] API_NAME: Identifier for uploading test data to Schemathesis.io
915
932
  """
916
933
  _hypothesis_phases: list[hypothesis.Phase] | None = None
917
934
  if hypothesis_phases is not None:
@@ -996,7 +1013,7 @@ def run(
996
1013
  replacement = deprecated_filters[arg_name]
997
1014
  click.secho(
998
1015
  f"Warning: Option `{arg_name}` is deprecated and will be removed in Schemathesis 4.0. "
999
- f"Use `{replacement}` instead.",
1016
+ f"Use `{replacement}` instead",
1000
1017
  fg="yellow",
1001
1018
  )
1002
1019
  _ensure_unique_filter(values, arg_name)
@@ -1781,13 +1798,13 @@ def get_exit_code(event: events.ExecutionEvent) -> int:
1781
1798
 
1782
1799
  @schemathesis.command(short_help="Replay requests from a saved cassette.")
1783
1800
  @click.argument("cassette_path", type=click.Path(exists=True))
1784
- @click.option("--id", "id_", help="ID of interaction to replay.", type=str)
1785
- @click.option("--status", help="Status of interactions to replay.", type=str)
1786
- @click.option("--uri", help="A regexp that filters interactions by their request URI.", type=str)
1787
- @click.option("--method", help="A regexp that filters interactions by their request method.", type=str)
1788
- @click.option("--no-color", help="Disable ANSI color escape codes.", type=bool, is_flag=True)
1789
- @click.option("--force-color", help="Explicitly tells to enable ANSI color escape codes.", type=bool, is_flag=True)
1790
- @click.option("--verbosity", "-v", help="Increase verbosity of the output.", count=True)
1801
+ @click.option("--id", "id_", help="ID of interaction to replay", type=str)
1802
+ @click.option("--status", help="Status of interactions to replay", type=str)
1803
+ @click.option("--uri", help="A regexp that filters interactions by their request URI", type=str)
1804
+ @click.option("--method", help="A regexp that filters interactions by their request method", type=str)
1805
+ @click.option("--no-color", help="Disable ANSI color escape codes", type=bool, is_flag=True)
1806
+ @click.option("--force-color", help="Explicitly tells to enable ANSI color escape codes", type=bool, is_flag=True)
1807
+ @click.option("--verbosity", "-v", help="Increase verbosity of the output", count=True)
1791
1808
  @with_request_tls_verify
1792
1809
  @with_request_proxy
1793
1810
  @with_request_cert
@@ -1855,13 +1872,13 @@ def replay(
1855
1872
  @click.argument("report", type=click.File(mode="rb"))
1856
1873
  @click.option(
1857
1874
  "--schemathesis-io-token",
1858
- help="Schemathesis.io authentication token.",
1875
+ help="Schemathesis.io authentication token",
1859
1876
  type=str,
1860
1877
  envvar=service.TOKEN_ENV_VAR,
1861
1878
  )
1862
1879
  @click.option(
1863
1880
  "--schemathesis-io-url",
1864
- help="Schemathesis.io base URL.",
1881
+ help="Schemathesis.io base URL",
1865
1882
  default=service.DEFAULT_URL,
1866
1883
  type=str,
1867
1884
  envvar=service.URL_ENV_VAR,
@@ -201,12 +201,12 @@ def cover_schema_iter(ctx: CoverageContext, schema: dict | bool) -> Generator[Ge
201
201
  seen.add(value)
202
202
  elif key == "multipleOf":
203
203
  yield from _negative_multiple_of(ctx, schema, value)
204
- elif key == "minLength" and 0 < value < BUFFER_SIZE and "pattern" not in schema:
204
+ elif key == "minLength" and 0 < value < BUFFER_SIZE:
205
205
  with suppress(InvalidArgument):
206
206
  yield NegativeValue(
207
207
  ctx.generate_from_schema({**schema, "minLength": value - 1, "maxLength": value - 1})
208
208
  )
209
- elif key == "maxLength" and value < BUFFER_SIZE and "pattern" not in schema:
209
+ elif key == "maxLength" and value < BUFFER_SIZE:
210
210
  with suppress(InvalidArgument):
211
211
  yield NegativeValue(
212
212
  ctx.generate_from_schema({**schema, "minLength": value + 1, "maxLength": value + 1})
@@ -238,6 +238,8 @@ def _get_properties(schema: dict | bool) -> dict | bool:
238
238
  if isinstance(schema, dict):
239
239
  if "example" in schema:
240
240
  return {"const": schema["example"]}
241
+ if "examples" in schema and schema["examples"]:
242
+ return {"enum": schema["examples"]}
241
243
  if schema.get("type") == "object":
242
244
  return _get_template_schema(schema, "object")
243
245
  return schema
@@ -261,16 +263,21 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
261
263
  # Boundary and near boundary values
262
264
  min_length = schema.get("minLength")
263
265
  max_length = schema.get("maxLength")
264
-
265
- if "example" in schema:
266
- yield PositiveValue(schema["example"])
266
+ example = schema.get("example")
267
+ examples = schema.get("examples")
268
+ if example or examples:
269
+ if example:
270
+ yield PositiveValue(example)
271
+ if examples:
272
+ for example in examples:
273
+ yield PositiveValue(example)
267
274
  elif not min_length and not max_length:
268
275
  # Default positive value
269
276
  yield PositiveValue(ctx.generate_from_schema(schema))
270
277
 
271
278
  seen = set()
272
279
 
273
- if min_length is not None and min_length < BUFFER_SIZE and "pattern" not in schema:
280
+ if min_length is not None and min_length < BUFFER_SIZE:
274
281
  # Exactly the minimum length
275
282
  yield PositiveValue(ctx.generate_from_schema({**schema, "maxLength": min_length}))
276
283
  seen.add(min_length)
@@ -281,7 +288,7 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
281
288
  yield PositiveValue(ctx.generate_from_schema({**schema, "minLength": larger, "maxLength": larger}))
282
289
  seen.add(larger)
283
290
 
284
- if max_length is not None and "pattern" not in schema:
291
+ if max_length is not None:
285
292
  # Exactly the maximum length
286
293
  if max_length < BUFFER_SIZE and max_length not in seen:
287
294
  yield PositiveValue(ctx.generate_from_schema({**schema, "minLength": max_length}))
@@ -318,9 +325,15 @@ def _positive_number(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
318
325
  if exclusive_maximum is not None:
319
326
  maximum = exclusive_maximum - 1
320
327
  multiple_of = schema.get("multipleOf")
321
-
322
- if "example" in schema:
323
- yield PositiveValue(schema["example"])
328
+ example = schema.get("example")
329
+ examples = schema.get("examples")
330
+
331
+ if example or examples:
332
+ if example:
333
+ yield PositiveValue(example)
334
+ if examples:
335
+ for example in examples:
336
+ yield PositiveValue(example)
324
337
  elif not minimum and not maximum:
325
338
  # Default positive value
326
339
  yield PositiveValue(ctx.generate_from_schema(schema))
@@ -367,8 +380,15 @@ def _positive_number(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
367
380
 
368
381
  def _positive_array(ctx: CoverageContext, schema: dict, template: list) -> Generator[GeneratedValue, None, None]:
369
382
  seen = set()
370
- if "example" in schema:
371
- yield PositiveValue(schema["example"])
383
+ example = schema.get("example")
384
+ examples = schema.get("examples")
385
+
386
+ if example or examples:
387
+ if example:
388
+ yield PositiveValue(example)
389
+ if examples:
390
+ for example in examples:
391
+ yield PositiveValue(example)
372
392
  else:
373
393
  yield PositiveValue(template)
374
394
  seen.add(len(template))
@@ -403,8 +423,15 @@ def _positive_array(ctx: CoverageContext, schema: dict, template: list) -> Gener
403
423
 
404
424
 
405
425
  def _positive_object(ctx: CoverageContext, schema: dict, template: dict) -> Generator[GeneratedValue, None, None]:
406
- if "example" in schema:
407
- yield PositiveValue(schema["example"])
426
+ example = schema.get("example")
427
+ examples = schema.get("examples")
428
+
429
+ if example or examples:
430
+ if example:
431
+ yield PositiveValue(example)
432
+ if examples:
433
+ for example in examples:
434
+ yield PositiveValue(example)
408
435
  else:
409
436
  yield PositiveValue(template)
410
437
  # Only required properties
schemathesis/models.py CHANGED
@@ -71,6 +71,14 @@ if TYPE_CHECKING:
71
71
  from .transports.responses import GenericResponse, WSGIResponse
72
72
 
73
73
 
74
+ @dataclass
75
+ class TransitionId:
76
+ name: str
77
+ status_code: str
78
+
79
+ __slots__ = ("name", "status_code")
80
+
81
+
74
82
  @dataclass
75
83
  class CaseSource:
76
84
  """Data sources, used to generate a test case."""
@@ -79,6 +87,7 @@ class CaseSource:
79
87
  response: GenericResponse
80
88
  elapsed: float
81
89
  overrides_all_parameters: bool
90
+ transition_id: TransitionId
82
91
 
83
92
  def partial_deepcopy(self) -> CaseSource:
84
93
  return self.__class__(
@@ -86,6 +95,7 @@ class CaseSource:
86
95
  response=self.response,
87
96
  elapsed=self.elapsed,
88
97
  overrides_all_parameters=self.overrides_all_parameters,
98
+ transition_id=self.transition_id,
89
99
  )
90
100
 
91
101
 
@@ -214,9 +224,20 @@ class Case:
214
224
  def app(self) -> Any:
215
225
  return self.operation.app
216
226
 
217
- def set_source(self, response: GenericResponse, case: Case, elapsed: float, overrides_all_parameters: bool) -> None:
227
+ def set_source(
228
+ self,
229
+ response: GenericResponse,
230
+ case: Case,
231
+ elapsed: float,
232
+ overrides_all_parameters: bool,
233
+ transition_id: TransitionId,
234
+ ) -> None:
218
235
  self.source = CaseSource(
219
- case=case, response=response, elapsed=elapsed, overrides_all_parameters=overrides_all_parameters
236
+ case=case,
237
+ response=response,
238
+ elapsed=elapsed,
239
+ overrides_all_parameters=overrides_all_parameters,
240
+ transition_id=transition_id,
220
241
  )
221
242
 
222
243
  @property
@@ -49,6 +49,8 @@ class Initialized(ExecutionEvent):
49
49
  seed: int | None
50
50
  # The base URL against which the tests are running
51
51
  base_url: str
52
+ # The base path part of every operation
53
+ base_path: str
52
54
  # API schema specification name
53
55
  specification_name: str
54
56
  # Monotonic clock value when the test run started. Used to properly calculate run duration, since this clock
@@ -77,6 +79,7 @@ class Initialized(ExecutionEvent):
77
79
  links_count=schema.links_count if count_links else None,
78
80
  location=schema.location,
79
81
  base_url=schema.get_base_url(),
82
+ base_path=schema.base_path,
80
83
  start_time=start_time or time.monotonic(),
81
84
  started_at=started_at or current_datetime(),
82
85
  specification_name=schema.verbose_name,
@@ -306,13 +306,12 @@ class BaseRunner:
306
306
  if isinstance(stateful_event, stateful_events.SuiteFinished):
307
307
  if stateful_event.failures and status != Status.error:
308
308
  status = Status.failure
309
- for failure in stateful_event.failures:
310
- result.checks.append(failure)
311
309
  elif isinstance(stateful_event, stateful_events.RunStarted):
312
310
  test_start_time = stateful_event.timestamp
313
311
  elif isinstance(stateful_event, stateful_events.RunFinished):
314
312
  test_elapsed_time = stateful_event.timestamp - cast(float, test_start_time)
315
313
  elif isinstance(stateful_event, stateful_events.StepFinished):
314
+ result.checks.extend(stateful_event.checks)
316
315
  on_step_finished(stateful_event)
317
316
  elif isinstance(stateful_event, stateful_events.Errored):
318
317
  status = Status.error
@@ -28,7 +28,7 @@ from ..exceptions import (
28
28
  make_unique_by_key,
29
29
  )
30
30
  from ..generation import DataGenerationMethod
31
- from ..models import Case, Check, Interaction, Request, Response, Status, TestPhase, TestResult
31
+ from ..models import Case, Check, Interaction, Request, Response, Status, TestPhase, TestResult, TransitionId
32
32
  from ..transports import deserialize_payload, serialize_payload
33
33
 
34
34
  if TYPE_CHECKING:
@@ -52,7 +52,9 @@ class SerializedCase:
52
52
  method: str
53
53
  url: str
54
54
  path_template: str
55
+ full_path: str
55
56
  verbose_name: str
57
+ transition_id: TransitionId | None
56
58
  # Transport info
57
59
  verify: bool
58
60
  # Headers coming from sources outside data generation
@@ -78,7 +80,9 @@ class SerializedCase:
78
80
  method=case.method,
79
81
  url=request_data.url,
80
82
  path_template=case.path,
83
+ full_path=case.full_path,
81
84
  verbose_name=case.operation.verbose_name,
85
+ transition_id=case.source.transition_id if case.source is not None else None,
82
86
  verify=verify,
83
87
  extra_headers=request_data.headers,
84
88
  )
@@ -174,7 +178,11 @@ class SerializedCheck:
174
178
 
175
179
 
176
180
  def _get_headers(headers: dict[str, Any] | CaseInsensitiveDict) -> dict[str, str]:
177
- return {key: value[0] for key, value in headers.items() if key not in get_excluded_headers()}
181
+ return {
182
+ key: value[0] if isinstance(value, list) else value
183
+ for key, value in headers.items()
184
+ if key not in get_excluded_headers()
185
+ }
178
186
 
179
187
 
180
188
  @dataclass
@@ -14,7 +14,7 @@ from jsonschema import RefResolver
14
14
 
15
15
  from ...constants import NOT_SET
16
16
  from ...internal.copy import fast_deepcopy
17
- from ...models import APIOperation, Case
17
+ from ...models import APIOperation, Case, TransitionId
18
18
  from ...parameters import ParameterSet
19
19
  from ...stateful import ParsedData, StatefulTest, UnresolvableLink
20
20
  from ...stateful.state_machine import Direction
@@ -226,7 +226,16 @@ class OpenAPILink(Direction):
226
226
  if parameter.name not in overrides.get(parameter.location, []):
227
227
  overrides_all_parameters = False
228
228
  break
229
- case.set_source(context.response, context.case, elapsed, overrides_all_parameters)
229
+ case.set_source(
230
+ context.response,
231
+ context.case,
232
+ elapsed,
233
+ overrides_all_parameters,
234
+ transition_id=TransitionId(
235
+ name=self.name,
236
+ status_code=self.status_code,
237
+ ),
238
+ )
230
239
 
231
240
  def set_parameters(
232
241
  self, case: Case, context: expressions.ExpressionContext
@@ -48,11 +48,20 @@ class OpenAPIParameter(Parameter):
48
48
 
49
49
  @property
50
50
  def is_header(self) -> bool:
51
- raise NotImplementedError
51
+ return self.location in ("header", "cookie")
52
52
 
53
53
  def as_json_schema(self, operation: APIOperation) -> dict[str, Any]:
54
54
  """Convert parameter's definition to JSON Schema."""
55
+ # JSON Schema allows `examples` as an array
56
+ if self.examples_field in self.definition:
57
+ examples = [
58
+ example["value"] for example in self.definition[self.examples_field].values() if "value" in example
59
+ ]
60
+ else:
61
+ examples = None
55
62
  schema = self.from_open_api_to_json_schema(operation, self.definition)
63
+ if examples is not None:
64
+ schema["examples"] = examples
56
65
  return self.transform_keywords(schema)
57
66
 
58
67
  def transform_keywords(self, schema: dict[str, Any]) -> dict[str, Any]:
@@ -118,12 +127,9 @@ class OpenAPI20Parameter(OpenAPIParameter):
118
127
  "enum",
119
128
  "multipleOf",
120
129
  "example",
130
+ "examples",
121
131
  )
122
132
 
123
- @property
124
- def is_header(self) -> bool:
125
- return self.location == "header"
126
-
127
133
 
128
134
  @dataclass(eq=False)
129
135
  class OpenAPI30Parameter(OpenAPIParameter):
@@ -165,12 +171,9 @@ class OpenAPI30Parameter(OpenAPIParameter):
165
171
  "additionalProperties",
166
172
  "format",
167
173
  "example",
174
+ "examples",
168
175
  )
169
176
 
170
- @property
171
- def is_header(self) -> bool:
172
- return self.location in ("header", "cookie")
173
-
174
177
  def from_open_api_to_json_schema(self, operation: APIOperation, open_api_schema: dict[str, Any]) -> dict[str, Any]:
175
178
  open_api_schema = get_parameter_schema(operation, open_api_schema)
176
179
  return super().from_open_api_to_json_schema(operation, open_api_schema)
@@ -219,6 +222,8 @@ class OpenAPI20Body(OpenAPIBody, OpenAPI20Parameter):
219
222
  "allOf",
220
223
  "properties",
221
224
  "additionalProperties",
225
+ "example",
226
+ "examples",
222
227
  )
223
228
  # NOTE. For Open API 2.0 bodies, we still give `x-example` precedence over the schema-level `example` field to keep
224
229
  # the precedence rules consistent.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: schemathesis
3
- Version: 3.35.2
3
+ Version: 3.35.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
@@ -1,7 +1,7 @@
1
1
  schemathesis/__init__.py,sha256=pNaTfaC3NSdediNQuH9QAcuIx3U-MmSydvhS65FZrxw,1984
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=GvwmPNnhOB6jnVwtPZr2R3tfdWMf6Q_xAJyYxEFEUYU,13986
4
+ schemathesis/_hypothesis.py,sha256=bYP1KHElFIqmdlLjHOKHBXpJ1pfUPl9rfBpOt3AKQmA,14012
5
5
  schemathesis/_lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
6
6
  schemathesis/_override.py,sha256=3CbA7P9Q89W3ymaYxiOV5Xpv1yhoBqroLK4YRpYMjX4,1630
7
7
  schemathesis/_rate_limiter.py,sha256=q_XWst5hzuAyXQRiZc4s_bx7-JlPYZM_yKDmeavt3oo,242
@@ -17,7 +17,7 @@ schemathesis/graphql.py,sha256=YkoKWY5K8lxp7H3ikAs-IsoDbiPwJvChG7O8p3DgwtI,229
17
17
  schemathesis/hooks.py,sha256=Uv9rZHqM2bpb_uYBjf4kqsMeu7XdLOHpRWSaN43xIgw,14774
18
18
  schemathesis/lazy.py,sha256=hGwSuWe5tDaGpjZTV4Mj8zqdrHDYHxR22N2p5h2yh1g,18897
19
19
  schemathesis/loaders.py,sha256=OtCD1o0TVmSNAUF7dgHpouoAXtY6w9vEtsRVGv4lE0g,4588
20
- schemathesis/models.py,sha256=ZA-neOIY3Q6-BLvX9B3TLUO6E-coHCkqcz4S8uDoSAM,44600
20
+ schemathesis/models.py,sha256=GEPDi6BQiJpcmCvSQ4L6_AJwaRC_hV5EffXM_pzzMrs,44949
21
21
  schemathesis/parameters.py,sha256=PndmqQRlEYsCt1kWjSShPsFf6vj7X_7FRdz_-A95eNg,2258
22
22
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  schemathesis/sanitization.py,sha256=_qSt04f_XcHrgguyUnowvdfj-b6u409Ubu07i0ivQUQ,9011
@@ -27,7 +27,7 @@ schemathesis/targets.py,sha256=XIGRghvEzbmEJjse9aZgNEj67L3jAbiazm2rxURWgDE,2351
27
27
  schemathesis/throttling.py,sha256=aisUc4MJDGIOGUAs9L2DlWWpdd4KyAFuNVKhYoaUC9M,1719
28
28
  schemathesis/types.py,sha256=Tem2Q_zyMCd0Clp5iGKv6Fu13wdcbxVE8tCVH9WWt7A,1065
29
29
  schemathesis/utils.py,sha256=bYvB3l1iMxiUNHu7_1qhOj5gJf_8QUssL4Uoqgrux9A,4878
30
- schemathesis/cli/__init__.py,sha256=g8tpoxHtO6QTUbgEAMq86RtidqvoRwFlEJ5gVaQJLRg,73464
30
+ schemathesis/cli/__init__.py,sha256=JT7qNr2LmAX1ceinVkMMxOFQ2DKEVpwiShQyy5zOwCo,73269
31
31
  schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,92
32
32
  schemathesis/cli/callbacks.py,sha256=PJs64n6qGrGC5Yv_yl3fGm797cvN6pp2enFLmSljGKs,15127
33
33
  schemathesis/cli/cassettes.py,sha256=KyODNf0r1ieLe3A-CGcU2EEkQYr0fgVut27AOl54MOM,18615
@@ -60,7 +60,7 @@ schemathesis/fixups/utf8_bom.py,sha256=lWT9RNmJG8i-l5AXIpaCT3qCPUwRgzXPW3eoOjmZE
60
60
  schemathesis/generation/__init__.py,sha256=IzldWIswXBjCUaVInvXDoaXIrUbtZIU5cisnWcg2IX8,1609
61
61
  schemathesis/generation/_hypothesis.py,sha256=Qel0mBsZV6tOEspRGfbJKFZevaMgHJjzY1F0Oo1bP_Y,1408
62
62
  schemathesis/generation/_methods.py,sha256=jCK09f4sedDfePrS-6BIiE-CcEE8fJ4ZHxq1BHoTltQ,1101
63
- schemathesis/generation/coverage.py,sha256=yOlPO79d_awOPHbDTly64ND_C_MyYoiALgB7YYqnWpE,20132
63
+ schemathesis/generation/coverage.py,sha256=WKZi_q4V_foejmDZg38N6cj_nfB_ahbh4wxYDmMVbeY,20889
64
64
  schemathesis/internal/__init__.py,sha256=93HcdG3LF0BbQKbCteOsFMa1w6nXl8yTmx87QLNJOik,161
65
65
  schemathesis/internal/copy.py,sha256=DcL56z-d69kKR_5u8mlHvjSL1UTyUKNMAwexrwHFY1s,1031
66
66
  schemathesis/internal/datetime.py,sha256=zPLBL0XXLNfP-KYel3H2m8pnsxjsA_4d-zTOhJg2EPQ,136
@@ -72,11 +72,11 @@ schemathesis/internal/result.py,sha256=d449YvyONjqjDs-A5DAPgtAI96iT753K8sU6_1HLo
72
72
  schemathesis/internal/transformation.py,sha256=M5LA4pFZC4nD_0iGfih1wLF3_q8xJas94Uuaymt-7Cw,690
73
73
  schemathesis/internal/validation.py,sha256=G7i8jIMUpAeOnDsDF_eWYvRZe_yMprRswx0QAtMPyEw,966
74
74
  schemathesis/runner/__init__.py,sha256=-aedUaRBCiTiaooC0OsBbdi4XP8APFOpj6eOzwt5nQ8,21366
75
- schemathesis/runner/events.py,sha256=WEyd55FiQZCPTqWphmRDV4_sDgLvU_UXkqGXCHsF4OI,11627
75
+ schemathesis/runner/events.py,sha256=l9OmbJR1TOpUAh1okiIRWAeFBiJz5JFIX4E1cfYBo-0,11730
76
76
  schemathesis/runner/probes.py,sha256=no5AfO3kse25qvHevjeUfB0Q3C860V2AYzschUW3QMQ,5688
77
- schemathesis/runner/serialization.py,sha256=C8F_2KiszQx16DkWm37viN_AJqLi-MF3YyvkdaFSmCs,20116
77
+ schemathesis/runner/serialization.py,sha256=p7jC8QRFcwU9h9rvc6a-1Wr8bOVQ3O4HyWJYXXvkjNU,20384
78
78
  schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
79
- schemathesis/runner/impl/core.py,sha256=H4sYY59kMXQPeOD4BH3j47Ymvix71FSgyQh36flrQxM,45605
79
+ schemathesis/runner/impl/core.py,sha256=Fc0OZm9uAGyGYWkBcXNm2sL4wITntccZtz592g3z_88,45555
80
80
  schemathesis/runner/impl/solo.py,sha256=N7-pUL6nWGiSRUC4Zqy1T4h99vbeQowP6b6cMnobOow,3042
81
81
  schemathesis/runner/impl/threadpool.py,sha256=JtTn5X7gqpbkO4q8n5kykGEPQCpJ9hXJrvU3KMF1CXA,14948
82
82
  schemathesis/service/__init__.py,sha256=cDVTCFD1G-vvhxZkJUwiToTAEQ-0ByIoqwXvJBCf_V8,472
@@ -109,10 +109,10 @@ schemathesis/specs/openapi/converter.py,sha256=TaYgc5BBHPdkN-n0lqpbeVgLu3eL3L8Wu
109
109
  schemathesis/specs/openapi/definitions.py,sha256=Z186F0gNBSCmPg-Kk7Q-n6XxEZHIOzgUyeqixlC62XE,94058
110
110
  schemathesis/specs/openapi/examples.py,sha256=_6vqwVfGuPaJ9GTqmlk6siiS0pikk5wxelLsFQJlaEc,16283
111
111
  schemathesis/specs/openapi/formats.py,sha256=JmmkQWNAj5XreXb7Edgj4LADAf4m86YulR_Ec8evpJ4,1220
112
- schemathesis/specs/openapi/links.py,sha256=DCOu14VOFqKYYFbQJHWICDpmTBzJfeP2v2FXBwW3vBI,17531
112
+ schemathesis/specs/openapi/links.py,sha256=RvWJZqHfOeoNjhARBX9GSjG6mbQBwhMfB4-iEEQ9_TI,17737
113
113
  schemathesis/specs/openapi/loaders.py,sha256=MxzMoCufll_a_QFjQ9khBcM2dAD3cw8Fn6yCtpX_BzE,25628
114
114
  schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9BsRQwPD87x0g,1017
115
- schemathesis/specs/openapi/parameters.py,sha256=O9uXvS7okEcRmW7MHatEg7cMmc1x8WT57EFnksP9PRI,13649
115
+ schemathesis/specs/openapi/parameters.py,sha256=UkTjSa4PE9nEBTljbRrwTcoKHYN8PFK7hBoR5qD9k6g,13932
116
116
  schemathesis/specs/openapi/references.py,sha256=euxM02kQGMHh4Ss1jWjOY_gyw_HazafKITIsvOEiAvI,9831
117
117
  schemathesis/specs/openapi/schemas.py,sha256=3pZEAU9sB9PT32z3BhJPsSSR0wVpJXL20-z9hMWS52s,53053
118
118
  schemathesis/specs/openapi/security.py,sha256=nEhDB_SvEFldmfpa9uOQywfWN6DtXHKmgtwucJvfN5Q,7096
@@ -147,8 +147,8 @@ schemathesis/transports/auth.py,sha256=yELjkEkfx4g74hNrd0Db9aFf0xDJDRIwhg2vzKOTZ
147
147
  schemathesis/transports/content_types.py,sha256=VrcRQvF5T_TUjrCyrZcYF2LOwKfs3IrLcMtkVSp1ImI,2189
148
148
  schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
149
149
  schemathesis/transports/responses.py,sha256=6-gvVcRK0Ho_lSydUysBNFWoJwZEiEgf6Iv-GWkQGd8,1675
150
- schemathesis-3.35.2.dist-info/METADATA,sha256=cG_kY6D_dbZyZO3hOJCcaMTRu80c_3ugGmJrfCGAsD8,12856
151
- schemathesis-3.35.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
152
- schemathesis-3.35.2.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
153
- schemathesis-3.35.2.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
154
- schemathesis-3.35.2.dist-info/RECORD,,
150
+ schemathesis-3.35.3.dist-info/METADATA,sha256=mvR0yYu9CyG09IvD4Dk8DBQ4vlLXKanpRpqshLdbgSQ,12856
151
+ schemathesis-3.35.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
152
+ schemathesis-3.35.3.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
153
+ schemathesis-3.35.3.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
154
+ schemathesis-3.35.3.dist-info/RECORD,,