schemathesis 4.0.0a9__py3-none-any.whl → 4.0.0a10__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.
@@ -23,7 +23,7 @@ class JunitXMLHandler(EventHandler):
23
23
  label = event.recorder.label
24
24
  test_case = self.get_or_create_test_case(label)
25
25
  test_case.elapsed_sec += event.elapsed_time
26
- if event.status == Status.FAILURE:
26
+ if event.status == Status.FAILURE and label in ctx.statistic.failures:
27
27
  add_failure(test_case, ctx.statistic.failures[label].values(), ctx)
28
28
  elif event.status == Status.SKIP and event.skip_reason is not None:
29
29
  test_case.add_skipped_info(output=event.skip_reason)
@@ -4,6 +4,7 @@ import enum
4
4
  from dataclasses import dataclass
5
5
 
6
6
  SCHEMATHESIS_TEST_CASE_HEADER = "X-Schemathesis-TestCaseId"
7
+ INTERNAL_BUFFER_SIZE = 32 * 1024
7
8
 
8
9
 
9
10
  class NotSet: ...
@@ -16,7 +16,7 @@ from hypothesis_jsonschema import from_schema
16
16
  from hypothesis_jsonschema._canonicalise import canonicalish
17
17
  from hypothesis_jsonschema._from_schema import STRING_FORMATS as BUILT_IN_STRING_FORMATS
18
18
 
19
- from schemathesis.core import NOT_SET
19
+ from schemathesis.core import INTERNAL_BUFFER_SIZE, NOT_SET
20
20
  from schemathesis.core.compat import RefResolutionError
21
21
  from schemathesis.core.transforms import deepclone
22
22
  from schemathesis.core.validation import has_invalid_characters, is_latin_1_encodable
@@ -36,7 +36,6 @@ def json_recursive_strategy(strategy: st.SearchStrategy) -> st.SearchStrategy:
36
36
  return st.lists(strategy, max_size=3) | st.dictionaries(st.text(), strategy, max_size=3)
37
37
 
38
38
 
39
- BUFFER_SIZE = 8 * 1024
40
39
  NEGATIVE_MODE_MAX_LENGTH_WITH_PATTERN = 100
41
40
  NEGATIVE_MODE_MAX_ITEMS = 15
42
41
  FLOAT_STRATEGY: st.SearchStrategy = st.floats(allow_nan=False, allow_infinity=False).map(_replace_zero_with_nonzero)
@@ -161,7 +160,7 @@ class CoverageContext:
161
160
  def generate_from_schema(self, schema: dict | bool) -> Any:
162
161
  if isinstance(schema, bool):
163
162
  return 0
164
- keys = sorted([k for k in schema if not k.startswith("x-") and k not in ["description", "example"]])
163
+ keys = sorted([k for k in schema if not k.startswith("x-") and k not in ["description", "example", "examples"]])
165
164
  if keys == ["type"] and isinstance(schema["type"], str) and schema["type"] in STRATEGIES_FOR_TYPE:
166
165
  return cached_draw(STRATEGIES_FOR_TYPE[schema["type"]])
167
166
  if keys == ["format", "type"]:
@@ -393,7 +392,7 @@ def cover_schema_iter(
393
392
  if k not in seen:
394
393
  yield value_
395
394
  seen.add(k)
396
- elif key == "minLength" and 0 < value < BUFFER_SIZE:
395
+ elif key == "minLength" and 0 < value < INTERNAL_BUFFER_SIZE:
397
396
  if value == 1:
398
397
  # In this case, the only possible negative string is an empty one
399
398
  # The `pattern` value may require an non-empty one and the generation will fail
@@ -427,7 +426,7 @@ def cover_schema_iter(
427
426
  value, description="String smaller than minLength", location=ctx.current_path
428
427
  )
429
428
  seen.add(k)
430
- elif key == "maxLength" and value < BUFFER_SIZE:
429
+ elif key == "maxLength" and value < INTERNAL_BUFFER_SIZE:
431
430
  try:
432
431
  min_length = max_length = value + 1
433
432
  new_schema = {**schema, "minLength": min_length, "maxLength": max_length}
@@ -461,7 +460,7 @@ def cover_schema_iter(
461
460
  elif key == "required":
462
461
  template = template or ctx.generate_from_schema(_get_template_schema(schema, "object"))
463
462
  yield from _negative_required(ctx, template, value)
464
- elif key == "maxItems" and isinstance(value, int) and value < BUFFER_SIZE:
463
+ elif key == "maxItems" and isinstance(value, int) and value < INTERNAL_BUFFER_SIZE:
465
464
  if value > NEGATIVE_MODE_MAX_ITEMS:
466
465
  # It could be extremely slow to generate large arrays
467
466
  # Generate values up to the limit and reuse them to construct the final array
@@ -471,7 +470,18 @@ def cover_schema_iter(
471
470
  "maxItems": NEGATIVE_MODE_MAX_ITEMS,
472
471
  "type": "array",
473
472
  }
474
- array_value = ctx.generate_from_schema(new_schema)
473
+ if "items" in schema and isinstance(schema["items"], dict):
474
+ # The schema may have another large array nested, therefore generate covering cases
475
+ # and use them to build an array for the current schema
476
+ negative = [case.value for case in cover_schema_iter(ctx, schema["items"])]
477
+ positive = [case.value for case in cover_schema_iter(ctx.with_positive(), schema["items"])]
478
+ # Interleave positive & negative values
479
+ array_value = [value for pair in zip(positive, negative) for value in pair][
480
+ :NEGATIVE_MODE_MAX_ITEMS
481
+ ]
482
+ else:
483
+ array_value = ctx.generate_from_schema(new_schema)
484
+
475
485
  # Extend the array to be of length value + 1 by repeating its own elements
476
486
  diff = value + 1 - len(array_value)
477
487
  if diff > 0:
@@ -606,7 +616,7 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
606
616
 
607
617
  seen = set()
608
618
 
609
- if min_length is not None and min_length < BUFFER_SIZE:
619
+ if min_length is not None and min_length < INTERNAL_BUFFER_SIZE:
610
620
  # Exactly the minimum length
611
621
  yield PositiveValue(
612
622
  ctx.generate_from_schema({**schema, "maxLength": min_length}), description="Minimum length string"
@@ -615,7 +625,7 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
615
625
 
616
626
  # One character more than minimum if possible
617
627
  larger = min_length + 1
618
- if larger < BUFFER_SIZE and larger not in seen and (not max_length or larger <= max_length):
628
+ if larger < INTERNAL_BUFFER_SIZE and larger not in seen and (not max_length or larger <= max_length):
619
629
  yield PositiveValue(
620
630
  ctx.generate_from_schema({**schema, "minLength": larger, "maxLength": larger}),
621
631
  description="Near-boundary length string",
@@ -624,7 +634,7 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
624
634
 
625
635
  if max_length is not None:
626
636
  # Exactly the maximum length
627
- if max_length < BUFFER_SIZE and max_length not in seen:
637
+ if max_length < INTERNAL_BUFFER_SIZE and max_length not in seen:
628
638
  yield PositiveValue(
629
639
  ctx.generate_from_schema({**schema, "minLength": max_length}), description="Maximum length string"
630
640
  )
@@ -633,7 +643,7 @@ def _positive_string(ctx: CoverageContext, schema: dict) -> Generator[GeneratedV
633
643
  # One character less than maximum if possible
634
644
  smaller = max_length - 1
635
645
  if (
636
- smaller < BUFFER_SIZE
646
+ smaller < INTERNAL_BUFFER_SIZE
637
647
  and smaller not in seen
638
648
  and (smaller > 0 and (min_length is None or smaller >= min_length))
639
649
  ):
@@ -765,7 +775,7 @@ def _positive_array(ctx: CoverageContext, schema: dict, template: list) -> Gener
765
775
  yield PositiveValue(value, description="Near-boundary items array")
766
776
 
767
777
  if max_items is not None:
768
- if max_items < BUFFER_SIZE and max_items not in seen:
778
+ if max_items < INTERNAL_BUFFER_SIZE and max_items not in seen:
769
779
  value = ctx.generate_from_schema({**schema, "minItems": max_items})
770
780
  key = _to_hashable_key(value)
771
781
  if key not in seen:
@@ -775,7 +785,7 @@ def _positive_array(ctx: CoverageContext, schema: dict, template: list) -> Gener
775
785
  # One item smaller than maximum if possible
776
786
  smaller = max_items - 1
777
787
  if (
778
- smaller < BUFFER_SIZE
788
+ smaller < INTERNAL_BUFFER_SIZE
779
789
  and smaller > 0
780
790
  and smaller not in seen
781
791
  and (min_items is None or smaller >= min_items)
@@ -5,11 +5,14 @@ DEFAULT_DEADLINE = 15000
5
5
 
6
6
 
7
7
  def setup() -> None:
8
+ from hypothesis import core as root_core
9
+ from hypothesis.internal.conjecture import engine
8
10
  from hypothesis.internal.entropy import deterministic_PRNG
9
11
  from hypothesis.internal.reflection import is_first_param_referenced_in_function
10
- from hypothesis.strategies._internal import core
12
+ from hypothesis.strategies._internal import collections, core
11
13
  from hypothesis_jsonschema import _from_schema, _resolve
12
14
 
15
+ from schemathesis.core import INTERNAL_BUFFER_SIZE
13
16
  from schemathesis.core.transforms import deepclone
14
17
 
15
18
  # Forcefully initializes Hypothesis' global PRNG to avoid races that initialize it
@@ -28,3 +31,6 @@ def setup() -> None:
28
31
  core.is_first_param_referenced_in_function = _is_first_param_referenced_in_function # type: ignore
29
32
  _resolve.deepcopy = deepclone # type: ignore
30
33
  _from_schema.deepcopy = deepclone # type: ignore
34
+ root_core.BUFFER_SIZE = INTERNAL_BUFFER_SIZE # type: ignore
35
+ engine.BUFFER_SIZE = INTERNAL_BUFFER_SIZE
36
+ collections.BUFFER_SIZE = INTERNAL_BUFFER_SIZE # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.0.0a9
3
+ Version: 4.0.0a10
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
@@ -25,7 +25,7 @@ schemathesis/cli/commands/run/validation.py,sha256=cpGG5hFc4lHVemXrQXRvrlNlqBmMq
25
25
  schemathesis/cli/commands/run/handlers/__init__.py,sha256=TPZ3KdGi8m0fjlN0GjA31MAXXn1qI7uU4FtiDwroXZI,1915
26
26
  schemathesis/cli/commands/run/handlers/base.py,sha256=yDsTtCiztLksfk7cRzg8JlaAVOfS-zwK3tsJMOXAFyc,530
27
27
  schemathesis/cli/commands/run/handlers/cassettes.py,sha256=SVk13xPhsQduCpgvvBwzEMDNTju-SHQCW90xTQ6iL1U,18525
28
- schemathesis/cli/commands/run/handlers/junitxml.py,sha256=c24UiwXqRCnv2eWQWEaNXLOghMI9JtGoZ9RTJY4ao6M,2350
28
+ schemathesis/cli/commands/run/handlers/junitxml.py,sha256=OhBS8JY4DXQGsQ0JjaHp19QDBR2hye30a-XulVzs-rg,2386
29
29
  schemathesis/cli/commands/run/handlers/output.py,sha256=n25QDGvYMXPKRPHBDckkDVwkkieY3Gq4HHSG0h3paTA,58800
30
30
  schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  schemathesis/cli/ext/fs.py,sha256=OA3mRzra4rq3NyDTcBvlRh0WJrh4ByN-QQ8loI04m88,408
@@ -34,7 +34,7 @@ schemathesis/cli/ext/options.py,sha256=gBjfYPoiSoxCymWq41x0oKcQ2frv1fQnweETVpYiI
34
34
  schemathesis/contrib/__init__.py,sha256=wxpX86xrEGRAS3f7eugQfKVbnqV6ZfOqFBS_DmWxOok,120
35
35
  schemathesis/contrib/openapi/__init__.py,sha256=-7mBZ9RQj0EGzzmC-HKiT5ZslwHcoWFqCVpRG0GHO_o,162
36
36
  schemathesis/contrib/openapi/fill_missing_examples.py,sha256=BfBpuy3vCKbE_uILqPXnm7kxEDopAr5tNQwP5E9xX8A,585
37
- schemathesis/core/__init__.py,sha256=4SLVPpUZgZYABL6QPVRtanMemibKxTQEYcp4LFu4Jco,1761
37
+ schemathesis/core/__init__.py,sha256=s1Td4mecrTr31BjBSdnxPSWPPGQERkAAAEPZBBK_9AE,1794
38
38
  schemathesis/core/compat.py,sha256=Lflo6z-nQ6S4uKZINc4Fr90pd3LTN6cIG9HJJmmaHeY,754
39
39
  schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,130
40
40
  schemathesis/core/curl.py,sha256=yuaCe_zHLGwUjEeloQi6W3tOA3cGdnHDNI17-5jia0o,1723
@@ -74,12 +74,12 @@ schemathesis/engine/phases/unit/_pool.py,sha256=9OgmFd-ov1AAvcZGquK40PXkGLp7f2qC
74
74
  schemathesis/experimental/__init__.py,sha256=jYY3Mq6okqTRTMudPzcaT0JVjzJW5IN_ZVJdGU0stBs,2011
75
75
  schemathesis/generation/__init__.py,sha256=sWTRPTh-qDNkSfpM9rYI3v8zskH8_wFKUuPRg18fZI8,1627
76
76
  schemathesis/generation/case.py,sha256=Rt5MCUtPVYVQzNyjUx8magocPJpHV1svyuqQSTwUE-I,7306
77
- schemathesis/generation/coverage.py,sha256=YQHmC_wVQ9WBuThNr62LFort9WqHM1DHUtexk-ALSV8,45471
77
+ schemathesis/generation/coverage.py,sha256=0iQZfm6yECy_nXatU3dCDCFI4lZW-IsiGZAiljptGUE,46362
78
78
  schemathesis/generation/meta.py,sha256=36h6m4E7jzLGa8TCvl7eBl_xUWLiRul3qxzexl5cB58,2515
79
79
  schemathesis/generation/modes.py,sha256=t_EvKr2aOXYMsEfdMu4lLF4KCGcX1LVVyvzTkcpJqhk,663
80
80
  schemathesis/generation/overrides.py,sha256=FhqcFoliEvgW6MZyFPYemfLgzKt3Miy8Cud7OMOCb7g,3045
81
81
  schemathesis/generation/targets.py,sha256=_rN2qgxTE2EfvygiN-Fy3WmDnRH0ERohdx3sKRDaYhU,2120
82
- schemathesis/generation/hypothesis/__init__.py,sha256=Rl7QwvMBMJI7pBqTydplX6bXC420n0EGQHVm-vZgaYQ,1204
82
+ schemathesis/generation/hypothesis/__init__.py,sha256=SVwM-rx07jPZzms0idWYACgUtWAxh49HRuTnaQ__zf0,1549
83
83
  schemathesis/generation/hypothesis/builder.py,sha256=QDfZRpFjQ0KYFPgu2BVSlxop0TQL7fQc201jOMR4rSQ,30472
84
84
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
85
85
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
@@ -146,8 +146,8 @@ schemathesis/transport/prepare.py,sha256=qQ6zXBw5NN2AIM0bzLAc5Ryc3dmMb0R6xN14lnR
146
146
  schemathesis/transport/requests.py,sha256=j5wI1Uo_PnVuP1eV8l6ddsXosyxAPQ1mLSyWEZmTI9I,8747
147
147
  schemathesis/transport/serialization.py,sha256=jIMra1LqRGav0OX3Hx7mvORt38ll4cd2DKit2D58FN0,10531
148
148
  schemathesis/transport/wsgi.py,sha256=RWSuUXPrl91GxAy8a4jyNNozOWVMRBxKx_tljlWA_Lo,5697
149
- schemathesis-4.0.0a9.dist-info/METADATA,sha256=xL00zLDR06C2Jth4cyLvr-lrNBb5mDkognESM0xvJfI,10427
150
- schemathesis-4.0.0a9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
- schemathesis-4.0.0a9.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
- schemathesis-4.0.0a9.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
153
- schemathesis-4.0.0a9.dist-info/RECORD,,
149
+ schemathesis-4.0.0a10.dist-info/METADATA,sha256=goxBn_HTzqqh7sSkqXpopuF5lT2tMxNJNcwyso9QtEQ,10428
150
+ schemathesis-4.0.0a10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
+ schemathesis-4.0.0a10.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
+ schemathesis-4.0.0a10.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
153
+ schemathesis-4.0.0a10.dist-info/RECORD,,