schemathesis 4.0.14__py3-none-any.whl → 4.0.16__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.
@@ -26,6 +26,7 @@ from schemathesis.engine import Status, events
26
26
  from schemathesis.engine.phases import PhaseName, PhaseSkipReason
27
27
  from schemathesis.engine.phases.probes import ProbeOutcome
28
28
  from schemathesis.engine.recorder import Interaction, ScenarioRecorder
29
+ from schemathesis.generation.meta import CoveragePhaseData
29
30
  from schemathesis.generation.modes import GenerationMode
30
31
  from schemathesis.schemas import ApiStatistic
31
32
 
@@ -1053,10 +1054,19 @@ class OutputHandler(EventHandler):
1053
1054
 
1054
1055
  warnings = self.config.warnings_for(operation=operation)
1055
1056
 
1057
+ def has_only_missing_auth_case() -> bool:
1058
+ case = list(event.recorder.cases.values())[0].value
1059
+ return bool(
1060
+ case.meta
1061
+ and isinstance(case.meta.phase.data, CoveragePhaseData)
1062
+ and case.meta.phase.data.description == "Missing `Authorization` at header"
1063
+ )
1064
+
1056
1065
  if SchemathesisWarning.MISSING_AUTH in warnings:
1057
- for status_code in (401, 403):
1058
- if statistic.ratio_for(status_code) >= AUTH_ERRORS_THRESHOLD:
1059
- self.warnings.missing_auth.setdefault(status_code, set()).add(event.recorder.label)
1066
+ if not (len(event.recorder.cases) == 1 and has_only_missing_auth_case()):
1067
+ for status_code in (401, 403):
1068
+ if statistic.ratio_for(status_code) >= AUTH_ERRORS_THRESHOLD:
1069
+ self.warnings.missing_auth.setdefault(status_code, set()).add(event.recorder.label)
1060
1070
 
1061
1071
  # Warn if all positive test cases got 4xx in return and no failure was found
1062
1072
  def all_positive_are_rejected(recorder: ScenarioRecorder) -> bool:
@@ -1220,10 +1230,10 @@ class OutputHandler(EventHandler):
1220
1230
  click.echo()
1221
1231
  if self.warnings.missing_auth:
1222
1232
  self._display_warning_block(
1223
- title="Missing authentication",
1233
+ title="Authentication failed",
1224
1234
  operations=self.warnings.missing_auth,
1225
1235
  operation_suffix=" returned authentication errors",
1226
- tips=["💡 Use --auth or -H to provide authentication credentials"],
1236
+ tips=["💡 Ensure valid authentication credentials are set via --auth or -H"],
1227
1237
  )
1228
1238
 
1229
1239
  if self.warnings.missing_test_data:
@@ -233,6 +233,9 @@ class CoverageContext:
233
233
  return cached_draw(st.integers(min_value=schema.get("minimum"), max_value=schema.get("maximum")))
234
234
  if "enum" in schema:
235
235
  return cached_draw(st.sampled_from(schema["enum"]))
236
+ if keys == ["multipleOf", "type"] and schema["type"] in ("integer", "number"):
237
+ step = schema["multipleOf"]
238
+ return cached_draw(st.integers().map(step.__mul__))
236
239
  if "pattern" in schema:
237
240
  pattern = schema["pattern"]
238
241
  try:
@@ -22,6 +22,7 @@ from schemathesis.config import GenerationConfig, ProjectConfig
22
22
  from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types
23
23
  from schemathesis.core.errors import InvalidSchema, SerializationNotPossible
24
24
  from schemathesis.core.marks import Mark
25
+ from schemathesis.core.transforms import deepclone
25
26
  from schemathesis.core.transport import prepare_urlencoded
26
27
  from schemathesis.core.validation import has_invalid_characters, is_latin_1_encodable
27
28
  from schemathesis.generation import GenerationMode, coverage
@@ -397,7 +398,7 @@ class Template:
397
398
  return output
398
399
 
399
400
  def unmodified(self) -> TemplateValue:
400
- kwargs = self._template.copy()
401
+ kwargs = deepclone(self._template)
401
402
  kwargs = self._serialize(kwargs)
402
403
  return TemplateValue(kwargs=kwargs, components=self._components.copy())
403
404
 
@@ -185,9 +185,11 @@ class APIStateMachine(RuleBasedStateMachine):
185
185
  if target is not None:
186
186
  super()._add_result_to_targets((target,), result)
187
187
 
188
- def _add_results_to_targets(self, targets: tuple[str, ...], results: list[StepOutput]) -> None:
188
+ def _add_results_to_targets(self, targets: tuple[str, ...], results: list[StepOutput | None]) -> None:
189
189
  # Hypothesis >6.131.15
190
190
  for result in results:
191
+ if result is None:
192
+ continue
191
193
  target = self._get_target_for_result(result)
192
194
  if target is not None:
193
195
  super()._add_results_to_targets((target,), [result])
@@ -195,7 +195,7 @@ class BaseOpenAPISchema(BaseSchema):
195
195
  self.resolver.push_scope(scope)
196
196
  try:
197
197
  for method, definition in path_item.items():
198
- if method not in HTTP_METHODS:
198
+ if method not in HTTP_METHODS or not definition:
199
199
  continue
200
200
  statistic.operations.total += 1
201
201
  is_selected = not should_skip(path, method, definition)
@@ -80,6 +80,10 @@ class RequestsTransport(BaseTransport["requests.Session"]):
80
80
  if cookies is not None:
81
81
  merge_at(data, "cookies", cookies)
82
82
 
83
+ excluded_headers = get_exclude_headers(case)
84
+ for name in excluded_headers:
85
+ data["headers"].pop(name, None)
86
+
83
87
  return data
84
88
 
85
89
  def send(self, case: Case, *, session: requests.Session | None = None, **kwargs: Any) -> Response:
@@ -112,9 +116,6 @@ class RequestsTransport(BaseTransport["requests.Session"]):
112
116
  data.update({key: value for key, value in kwargs.items() if key not in data})
113
117
  data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT)
114
118
 
115
- excluded_headers = get_exclude_headers(case)
116
- for name in excluded_headers:
117
- data["headers"].pop(name, None)
118
119
  current_session_headers: MutableMapping[str, Any] = {}
119
120
  current_session_auth = None
120
121
 
@@ -124,9 +125,11 @@ class RequestsTransport(BaseTransport["requests.Session"]):
124
125
  close_session = True
125
126
  else:
126
127
  current_session_headers = session.headers
127
- if isinstance(session.auth, tuple) and "Authorization" in excluded_headers:
128
- current_session_auth = session.auth
129
- session.auth = None
128
+ if isinstance(session.auth, tuple):
129
+ excluded_headers = get_exclude_headers(case)
130
+ if "Authorization" in excluded_headers:
131
+ current_session_auth = session.auth
132
+ session.auth = None
130
133
  close_session = False
131
134
  session.headers = {}
132
135
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.0.14
3
+ Version: 4.0.16
4
4
  Summary: Property-based testing framework for Open API and GraphQL based apps
5
5
  Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
6
6
  Project-URL: Changelog, https://github.com/schemathesis/schemathesis/blob/master/CHANGELOG.md
@@ -23,7 +23,7 @@ schemathesis/cli/commands/run/handlers/__init__.py,sha256=TPZ3KdGi8m0fjlN0GjA31M
23
23
  schemathesis/cli/commands/run/handlers/base.py,sha256=yDsTtCiztLksfk7cRzg8JlaAVOfS-zwK3tsJMOXAFyc,530
24
24
  schemathesis/cli/commands/run/handlers/cassettes.py,sha256=rRD4byjp4HXCkJS-zx3jSIFOJsPq77ejPpYeyCtsEZs,19461
25
25
  schemathesis/cli/commands/run/handlers/junitxml.py,sha256=ydk6Ofj-Uti6H8EucT4Snp85cmTA5W7uVpKkoHrIDKE,2586
26
- schemathesis/cli/commands/run/handlers/output.py,sha256=zlI0M5PuzduzluzONv3eyuoWWnigPkErPpUtjgHWESE,62476
26
+ schemathesis/cli/commands/run/handlers/output.py,sha256=oS3HP4idz99IxpZcjsqADtEOkuu8wruTcri5c1YIph0,62986
27
27
  schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  schemathesis/cli/ext/fs.py,sha256=3lvoAsEDDdih75ITJJNxemd3nwxX55gGWrI7uDxm0cM,447
29
29
  schemathesis/cli/ext/groups.py,sha256=kQ37t6qeArcKaY2y5VxyK3_KwAkBKCVm58IYV8gewds,2720
@@ -85,19 +85,19 @@ schemathesis/engine/phases/unit/_executor.py,sha256=9MmZoKSBVSPk0LWwN3PZ3iaO9nzp
85
85
  schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
86
86
  schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
87
87
  schemathesis/generation/case.py,sha256=zwAwFQ-Fp7SOxCXYOQyAdwAtNwVJe63PdLpvqackFQY,12296
88
- schemathesis/generation/coverage.py,sha256=kJGX7_YYQsM9rBMtalLlmrSFUIVXn8t4Z61Kpowa3rg,53705
88
+ schemathesis/generation/coverage.py,sha256=jpl1GpAGZXyoO2aZLUZlIE0h_ygdHMnvUK14oBg51k4,53896
89
89
  schemathesis/generation/meta.py,sha256=adkoMuCfzSjHJ9ZDocQn0GnVldSCkLL3eVR5A_jafwM,2552
90
90
  schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
91
91
  schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
92
92
  schemathesis/generation/overrides.py,sha256=OBWqDQPreiliaf2M-oyXppVKHoJkCRzxtwSJx1b6AFw,3759
93
93
  schemathesis/generation/hypothesis/__init__.py,sha256=SVwM-rx07jPZzms0idWYACgUtWAxh49HRuTnaQ__zf0,1549
94
- schemathesis/generation/hypothesis/builder.py,sha256=OUEYPXbjihrZa6Jjya83HslRCX_V7RhqnZuGs69QiZg,34769
94
+ schemathesis/generation/hypothesis/builder.py,sha256=ujPp9ByUfNYdxWyKoJlxE0h8pAVBpmNJwWIi9MnR968,34824
95
95
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
96
96
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
97
97
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
98
98
  schemathesis/generation/hypothesis/strategies.py,sha256=RurE81E06d99YKG48dizy9346ayfNswYTt38zewmGgw,483
99
99
  schemathesis/generation/stateful/__init__.py,sha256=s7jiJEnguIj44IsRyMi8afs-8yjIUuBbzW58bH5CHjs,1042
100
- schemathesis/generation/stateful/state_machine.py,sha256=1cY3AH-f_AbUGfvfK8WMMKkUxAJT9Iw8eZGyRE2Sd44,8740
100
+ schemathesis/generation/stateful/state_machine.py,sha256=3oAGpn46adNJx3sp5ym9e30SyYOjJGiEqenDZ5gWtBY,8803
101
101
  schemathesis/graphql/__init__.py,sha256=_eO6MAPHGgiADVGRntnwtPxmuvk666sAh-FAU4cG9-0,326
102
102
  schemathesis/graphql/checks.py,sha256=IADbxiZjgkBWrC5yzHDtohRABX6zKXk5w_zpWNwdzYo,3186
103
103
  schemathesis/graphql/loaders.py,sha256=2tgG4HIvFmjHLr_KexVXnT8hSBM-dKG_fuXTZgE97So,9445
@@ -134,7 +134,7 @@ schemathesis/specs/openapi/media_types.py,sha256=F5M6TKl0s6Z5X8mZpPsWDEdPBvxclKR
134
134
  schemathesis/specs/openapi/parameters.py,sha256=ifu_QQCMUzsUHQAkvsOvLuokns6CzesssmQ3Nd3zxII,14594
135
135
  schemathesis/specs/openapi/patterns.py,sha256=cBj8W4wn7VLJd4nABaIH5f502-zBDiqljxLgPWUn-50,15609
136
136
  schemathesis/specs/openapi/references.py,sha256=40YcDExPLR2B8EOwt-Csw-5MYFi2xj_DXf91J0Pc9d4,8855
137
- schemathesis/specs/openapi/schemas.py,sha256=knaGUtxcy4CKeOpvTrVgPifnqKh9eSYdXRPhExFKElk,52539
137
+ schemathesis/specs/openapi/schemas.py,sha256=FXD6yLindLNtjiW5D_GllWxfMAigSKjpjl8_GbqJXxE,52557
138
138
  schemathesis/specs/openapi/security.py,sha256=6UWYMhL-dPtkTineqqBFNKca1i4EuoTduw-EOLeE0aQ,7149
139
139
  schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
140
140
  schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
@@ -154,11 +154,11 @@ schemathesis/specs/openapi/stateful/links.py,sha256=h5q40jUbcIk5DS_Tih1cvFJxS_Qx
154
154
  schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
155
155
  schemathesis/transport/asgi.py,sha256=qTClt6oT_xUEWnRHokACN_uqCNNUZrRPT6YG0PjbElY,926
156
156
  schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEzXd0o,4743
157
- schemathesis/transport/requests.py,sha256=rziZTrZCVMAqgy6ldB8iTwhkpAsnjKSgK8hj5Sq3ThE,10656
157
+ schemathesis/transport/requests.py,sha256=46aplzhSmBupegPNMawma-iJWCegWkEd6mzdWLTpgM4,10742
158
158
  schemathesis/transport/serialization.py,sha256=igUXKZ_VJ9gV7P0TUc5PDQBJXl_s0kK9T3ljGWWvo6E,10339
159
159
  schemathesis/transport/wsgi.py,sha256=KoAfvu6RJtzyj24VGB8e-Iaa9smpgXJ3VsM8EgAz2tc,6152
160
- schemathesis-4.0.14.dist-info/METADATA,sha256=z1a4R4d4JKcMhzNP3aNTB-Rdg_K4hJibT2THKGrng5I,8472
161
- schemathesis-4.0.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
- schemathesis-4.0.14.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
163
- schemathesis-4.0.14.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
164
- schemathesis-4.0.14.dist-info/RECORD,,
160
+ schemathesis-4.0.16.dist-info/METADATA,sha256=Cy4KK06pQyWGPssr3PsSFtofmnMdsSgSNNjy3LHoxuw,8472
161
+ schemathesis-4.0.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
+ schemathesis-4.0.16.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
163
+ schemathesis-4.0.16.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
164
+ schemathesis-4.0.16.dist-info/RECORD,,