schemathesis 3.34.0__py3-none-any.whl → 3.34.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass
4
4
  from http.cookies import SimpleCookie
5
5
  from typing import TYPE_CHECKING, Any, Dict, Generator, NoReturn, cast
6
- from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
6
+ from urllib.parse import parse_qs, urlparse
7
7
 
8
8
  from ... import failures
9
9
  from ...exceptions import (
@@ -150,15 +150,17 @@ def response_headers_conformance(response: GenericResponse, case: Case) -> bool
150
150
  for name, definition in defined_headers.items():
151
151
  value = response.headers.get(name)
152
152
  if value is not None:
153
- parameter_definition = {"in": "header", **definition}
154
- parameter: OpenAPI20Parameter | OpenAPI30Parameter
155
- if isinstance(case.operation.schema, OpenApi30):
156
- parameter = OpenAPI30Parameter(parameter_definition)
157
- else:
158
- parameter = OpenAPI20Parameter(parameter_definition)
159
- schema = parameter.as_json_schema(case.operation)
160
- coerced = _coerce_header_value(value, schema)
161
153
  with case.operation.schema._validating_response(scopes) as resolver:
154
+ if "$ref" in definition:
155
+ _, definition = resolver.resolve(definition["$ref"])
156
+ parameter_definition = {"in": "header", **definition}
157
+ parameter: OpenAPI20Parameter | OpenAPI30Parameter
158
+ if isinstance(case.operation.schema, OpenApi30):
159
+ parameter = OpenAPI30Parameter(parameter_definition)
160
+ else:
161
+ parameter = OpenAPI20Parameter(parameter_definition)
162
+ schema = parameter.as_json_schema(case.operation)
163
+ coerced = _coerce_header_value(value, schema)
162
164
  try:
163
165
  jsonschema.validate(
164
166
  coerced,
@@ -332,8 +334,6 @@ def ensure_resource_availability(response: GenericResponse, original: Case) -> b
332
334
 
333
335
  def ignored_auth(response: GenericResponse, case: Case) -> bool | None:
334
336
  """Check if an operation declares authentication as a requirement but does not actually enforce it."""
335
- from requests import Session
336
-
337
337
  from .schemas import BaseOpenAPISchema
338
338
 
339
339
  if not isinstance(case.operation.schema, BaseOpenAPISchema):
@@ -344,14 +344,15 @@ def ignored_auth(response: GenericResponse, case: Case) -> bool | None:
344
344
  if security_parameters and 200 <= response.status_code < 300:
345
345
  if _contains_auth(response.request, security_parameters):
346
346
  # If there is auth in the request, then drop it and retry the call
347
- request = _remove_auth_from_request(response.request, security_parameters)
348
- response.request = request
349
- new_response = Session().send(request)
350
- if new_response.ok:
347
+ _remove_auth_from_case(case, security_parameters)
348
+ new_response = case.operation.schema.transport.send(case)
349
+ if 200 <= new_response.status_code < 300:
351
350
  # Mutate the response object in place on the best effort basis
352
- for attribute in new_response.__attrs__:
353
- setattr(response, attribute, getattr(new_response, attribute))
354
- _remove_auth_from_case(case, security_parameters)
351
+ if hasattr(response, "__attrs__"):
352
+ for attribute in new_response.__attrs__:
353
+ setattr(response, attribute, getattr(new_response, attribute))
354
+ else:
355
+ response.__dict__.update(new_response.__dict__)
355
356
  _raise_auth_error(new_response, case.operation.verbose_name)
356
357
  else:
357
358
  # Successful response when there is no auth
@@ -415,40 +416,6 @@ def _contains_auth(request: PreparedRequest, security_parameters: list[SecurityP
415
416
  return False
416
417
 
417
418
 
418
- def _remove_auth_from_request(
419
- request: PreparedRequest, security_parameters: list[SecurityParameter]
420
- ) -> PreparedRequest:
421
- """Remove security parameters from a request."""
422
- from requests.cookies import get_cookie_header
423
-
424
- request = request.copy()
425
- parsed = urlparse(request.url)
426
- query = parse_qs(parsed.query) # type: ignore
427
- should_replace_url = False
428
-
429
- for parameter in security_parameters:
430
- name = parameter["name"]
431
- if parameter["in"] == "header":
432
- request.headers.pop(name, None)
433
- if parameter["in"] == "query":
434
- query.pop(name, None)
435
- should_replace_url = True
436
- if parameter["in"] == "cookie":
437
- del request._cookies[name] # type: ignore
438
-
439
- if should_replace_url:
440
- components = [parsed.scheme, parsed.netloc, parsed.path, parsed.params, urlencode(query), parsed.fragment]
441
- url = cast(str, urlunparse(components)) # type: ignore
442
- request.url = url
443
- # Re-generate the `Cookie` header if needed
444
- raw_cookie = request.headers.pop("Cookie", None)
445
- if raw_cookie is not None:
446
- new_cookie_header = get_cookie_header(request._cookies, request) # type: ignore
447
- if new_cookie_header:
448
- request.headers["Cookie"] = new_cookie_header
449
- return request
450
-
451
-
452
419
  def _remove_auth_from_case(case: Case, security_parameters: list[SecurityParameter]) -> None:
453
420
  """Remove security parameters from a generated case.
454
421
 
@@ -192,6 +192,7 @@ class RequestsTransport:
192
192
  context=failures.RequestTimeout(message=message, timeout=timeout),
193
193
  ) from None
194
194
  response.verify = verify # type: ignore[attr-defined]
195
+ response._session = session # type: ignore[attr-defined]
195
196
  if close_session:
196
197
  session.close()
197
198
  return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schemathesis
3
- Version: 3.34.0
3
+ Version: 3.34.2
4
4
  Summary: Property-based testing framework for Open API and GraphQL based apps
5
5
  Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
6
6
  Project-URL: Changelog, https://schemathesis.readthedocs.io/en/stable/changelog.html
@@ -100,7 +100,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
100
100
  schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
101
101
  schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
102
102
  schemathesis/specs/openapi/_hypothesis.py,sha256=XtC-rYiH-GHvWykdSSzPFVK7jHNNL7NtibjSEeIZDQw,24122
103
- schemathesis/specs/openapi/checks.py,sha256=K4Eu9e85Tue54_xGp9dp5P8CuuDAcDlqJAM4iRVzXA0,21090
103
+ schemathesis/specs/openapi/checks.py,sha256=LiwoL5W_qK40j-JFSc9hfM8IGSszMBUWe71YZJ5FBzw,19931
104
104
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
105
105
  schemathesis/specs/openapi/converter.py,sha256=TaYgc5BBHPdkN-n0lqpbeVgLu3eL3L8Wu3y_Vo3TJaQ,2800
106
106
  schemathesis/specs/openapi/definitions.py,sha256=Z186F0gNBSCmPg-Kk7Q-n6XxEZHIOzgUyeqixlC62XE,94058
@@ -139,13 +139,13 @@ schemathesis/stateful/sink.py,sha256=xjsqJYH5WETKh5pDGlchYyjT3HcjzHEotUjvo1p0JsE
139
139
  schemathesis/stateful/state_machine.py,sha256=u7PkwCjxTZZcePC7GPiOUuu4uhqUees3UuorD_0Sx_c,12938
140
140
  schemathesis/stateful/statistic.py,sha256=xPLiCw61ofNXQicqcK_sZyLHiqiGcgQARpwd8AiRubM,487
141
141
  schemathesis/stateful/validation.py,sha256=JtqnRzl11ZbVR8Lcr0xBJKoOXzx8VUfRz92jOnB2Smg,3605
142
- schemathesis/transports/__init__.py,sha256=tIJm79N_pBHM5ccvez4Z4mW-VrG1LfN8yq7B0v9YDGk,12832
142
+ schemathesis/transports/__init__.py,sha256=L60_GCzJiX9jFYKVft4aeZb8EmyV6e72k8K73y2zvmE,12898
143
143
  schemathesis/transports/auth.py,sha256=yELjkEkfx4g74hNrd0Db9aFf0xDJDRIwhg2vzKOTZGg,1138
144
144
  schemathesis/transports/content_types.py,sha256=VrcRQvF5T_TUjrCyrZcYF2LOwKfs3IrLcMtkVSp1ImI,2189
145
145
  schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
146
146
  schemathesis/transports/responses.py,sha256=6-gvVcRK0Ho_lSydUysBNFWoJwZEiEgf6Iv-GWkQGd8,1675
147
- schemathesis-3.34.0.dist-info/METADATA,sha256=J6cG2yfIh_VOAI7UbhuD_TEKHla0zgqghCjawG6nwLw,18373
148
- schemathesis-3.34.0.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
149
- schemathesis-3.34.0.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
150
- schemathesis-3.34.0.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
151
- schemathesis-3.34.0.dist-info/RECORD,,
147
+ schemathesis-3.34.2.dist-info/METADATA,sha256=_1OPHWfBbVS9tUFtPcJJzu5L278bmaNBTfmgpafdmN0,18373
148
+ schemathesis-3.34.2.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
149
+ schemathesis-3.34.2.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
150
+ schemathesis-3.34.2.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
151
+ schemathesis-3.34.2.dist-info/RECORD,,