Skip to content

Commit c0260ff

Browse files
committed
Merge branch 'dev' into vas
2 parents 71a3907 + 858e9d4 commit c0260ff

File tree

7 files changed

+94
-26
lines changed

7 files changed

+94
-26
lines changed

src/schemathesis/cli/output/default.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
11
from __future__ import annotations
2+
23
import base64
34
import os
45
import platform
56
import shutil
67
import textwrap
78
import time
9+
from importlib import metadata
810
from itertools import groupby
911
from queue import Queue
1012
from typing import Any, Generator, cast
1113

1214
import click
13-
from importlib import metadata
1415

1516
from ... import service
1617
from ...code_samples import CodeSampleStyle
1718
from ...constants import (
1819
DISCORD_LINK,
20+
FALSE_VALUES,
1921
FLAKY_FAILURE_MESSAGE,
22+
GITHUB_APP_LINK,
23+
ISSUE_TRACKER_URL,
2024
REPORT_SUGGESTION_ENV_VAR,
2125
SCHEMATHESIS_TEST_CASE_HEADER,
2226
SCHEMATHESIS_VERSION,
23-
FALSE_VALUES,
24-
ISSUE_TRACKER_URL,
25-
GITHUB_APP_LINK,
2627
)
2728
from ...exceptions import RuntimeErrorType, prepare_response_payload
2829
from ...experimental import GLOBAL_EXPERIMENTS
2930
from ...models import Status
3031
from ...runner import events
3132
from ...runner.events import InternalErrorType, SchemaErrorType
3233
from ...runner.serialization import (
34+
SerializedCheck,
3335
SerializedError,
3436
SerializedTestResult,
3537
deduplicate_failures,
36-
SerializedCheck,
3738
)
39+
from ...specs.openapi._vas import logger
3840
from ..context import ExecutionContext, FileReportContext, ServiceReportContext
3941
from ..handlers import EventHandler
40-
from ...specs.openapi._vas import logger
4142

4243
SPINNER_REPETITION_NUMBER = 10
4344

@@ -365,7 +366,8 @@ def _by_unique_code_sample(
365366
check: SerializedCheck, code_sample_style: CodeSampleStyle
366367
) -> str:
367368
request_body = (
368-
base64.b64decode(check.example.body).decode()
369+
# Ignore decoding errors caused by invalid base64
370+
base64.b64decode(check.example.body).decode('utf-8', 'ignore')
369371
if check.example.body is not None
370372
else None
371373
)
@@ -531,7 +533,7 @@ def display_service_unauthorized(hostname: str) -> None:
531533

532534
def display_service_error(event: service.Error, message_prefix: str = "") -> None:
533535
"""Show information about an error during communication with Schemathesis.io."""
534-
from requests import RequestException, HTTPError, Response
536+
from requests import HTTPError, RequestException, Response
535537

536538
if isinstance(event.exception, HTTPError):
537539
response = cast(Response, event.exception.response)

src/schemathesis/models.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import base64
34
import datetime
45
import inspect
56
import textwrap
@@ -9,8 +10,7 @@
910
from enum import Enum
1011
from functools import lru_cache, partial
1112
from itertools import chain, count
12-
from logging import Logger, LogRecord
13-
from math import e
13+
from logging import LogRecord
1414
from typing import (
1515
TYPE_CHECKING,
1616
Any,
@@ -127,6 +127,7 @@ def prepare_request_data(kwargs: dict[str, Any]) -> PreparedRequestData:
127127
if key in get_request_signature().parameters
128128
}
129129
request = requests.Request(**kwargs).prepare()
130+
# logger.debug("in prepare request data ", request.body)
130131
return PreparedRequestData(
131132
method=str(request.method),
132133
url=str(request.url),
@@ -351,15 +352,23 @@ def as_requests_kwargs(
351352

352353
if isinstance(self.body, dict):
353354
# Create a new body without meta-data
354-
new_body = {
355+
body_without_prefixed_field = {
355356
key: value
356357
for key, value in self.body.items()
357358
if not key.startswith(VAS_KEY_PREFIX)
358359
}
359-
self.metadata = {
360-
f"{key[len(VAS_KEY_PREFIX) + 1:]}": value
361-
for key, value in self.body.items()
362-
if key.startswith(VAS_KEY_PREFIX)
360+
if self.metadata == {}:
361+
self.metadata = {
362+
f"{key[len(VAS_KEY_PREFIX) + 1:]}": value
363+
for key, value in self.body.items()
364+
if key.startswith(VAS_KEY_PREFIX)
365+
}
366+
new_body = {
367+
**body_without_prefixed_field,
368+
**{
369+
k: obj["image_name"]
370+
for k, obj in self.metadata.items()
371+
}
363372
}
364373
self.body = new_body
365374

@@ -409,7 +418,8 @@ def as_requests_kwargs(
409418
"deps/schemathesis/src/schemathesis/models.py -> new extra: %s", new_extra
410419
)
411420

412-
additional_headers = extra.pop("headers", None)
421+
additional_headers = new_extra.pop("headers", None)
422+
# additional_headers = extra.pop("headers", None)
413423
if additional_headers:
414424
# Additional headers, needed for the serializer
415425
for key, value in additional_headers.items():
@@ -421,6 +431,7 @@ def as_requests_kwargs(
421431
"headers": final_headers,
422432
"params": self.query,
423433
**new_extra,
434+
# **extra,
424435
}
425436

426437
def call(
@@ -863,6 +874,7 @@ def as_strategy(
863874
) -> st.SearchStrategy:
864875
"""Turn this API operation into a Hypothesis strategy."""
865876

877+
logger.debug("deps/schemathesis/src/schemathesis/models.py: as_strategy -> kwargs: %s", kwargs)
866878
# Cai nay quan trong cuc ki
867879
strategy = self.schema.get_case_strategy(
868880
self,
@@ -1054,12 +1066,17 @@ def from_case(cls, case: Case, session: requests.Session) -> Request:
10541066
base_url = case.get_full_base_url()
10551067
kwargs = case.as_requests_kwargs(base_url)
10561068
request = requests.Request(**kwargs)
1069+
# logger.debug("deps/schemathesis/src/schemathesis/models.py: from_case in Request -> request: %s", request)
10571070
prepared = session.prepare_request(request)
10581071
return cls.from_prepared_request(prepared)
10591072

10601073
@classmethod
10611074
def from_prepared_request(cls, prepared: requests.PreparedRequest) -> Request:
10621075
"""A prepared request version is already stored in `requests.Response`."""
1076+
logger.debug(
1077+
"deps/schemathesis/src/schemathesis/models.py: from_prepared_request in Request -> body: %s",
1078+
prepared.body,
1079+
)
10631080
body = prepared.body
10641081
if isinstance(body, str):
10651082
# can be a string for `application/x-www-form-urlencoded`
@@ -1172,6 +1189,15 @@ def from_requests(
11721189
status: Status,
11731190
checks: list[Check],
11741191
) -> Interaction:
1192+
1193+
logger.debug(
1194+
"deps/schemathesis/src/schemathesis/models.py: from_requests in Interaction -> response.request.body: %s",
1195+
response.request.body,
1196+
)
1197+
logger.debug(
1198+
"deps/schemathesis/src/schemathesis/models.py: from_requests in Interaction -> case.body: %s",
1199+
case.body,
1200+
)
11751201
return cls(
11761202
request=Request.from_prepared_request(response.request),
11771203
response=Response.from_requests(response),
@@ -1198,6 +1224,7 @@ def from_wsgi(
11981224
session = requests.Session()
11991225
session.headers.update(headers)
12001226
return cls(
1227+
case=case,
12011228
request=Request.from_case(case, session),
12021229
response=Response.from_wsgi(response, elapsed),
12031230
status=status,

src/schemathesis/runner/impl/core.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,14 @@
5454
)
5555
from ...runner import events
5656
from ...schemas import BaseSchema
57+
from ...specs.openapi._vas import logger
5758
from ...stateful import Feedback, Stateful
5859
from ...targets import Target, TargetContext
5960
from ...types import RawAuth, RequestCert
6061
from ...utils import capture_hypothesis_output
6162
from ..override import CaseOverride
6263
from ..serialization import SerializedTestResult
63-
from ...specs.openapi._vas import logger
64+
6465
if TYPE_CHECKING:
6566
from ...transports.responses import GenericResponse, WSGIResponse
6667

@@ -791,6 +792,43 @@ def _network_test(
791792
run_targets(targets, context)
792793
status = Status.success
793794
try:
795+
# logger.debug("kwargs in core.py: %s", kwargs)
796+
requests_kwargs = case.as_requests_kwargs(
797+
base_url=case.get_full_base_url(), headers=headers
798+
)
799+
if 'files' in requests_kwargs:
800+
# existing_tuple = requests_kwargs['files'][0]
801+
#logger.debug("existing tuple in kwargs in core.py: %s", existing_tuple)
802+
803+
if case.metadata != {}:
804+
for i, (key, value) in enumerate(requests_kwargs['files']):
805+
# Check if the key is in metadata
806+
if key in case.metadata:
807+
# Check if the current value is a tuple
808+
if isinstance(value, tuple):
809+
# Create a new tuple with the updated image name
810+
new_tuple = (value[0], case.metadata[key]["image_name"], *value[2:])
811+
# Update the list with the new tuple
812+
requests_kwargs['files'][i] = (key, new_tuple)
813+
else:
814+
# If not a tuple, directly update with the new image name
815+
requests_kwargs['files'][i] = (key, case.metadata[key]["image_name"])
816+
#logger.debug("Updated file in kwargs: %s", requests_kwargs['files'][i])
817+
# requests_kwargs['files'][0][1] = case.metadata['image_name']
818+
#logger.debug("files in kwargs in core.py: %s", requests_kwargs['files'][0][1])
819+
#logger.debug("request_kargs in core.py: %s", requests_kwargs)
820+
### Create new request but reserve old content length
821+
old_content_length = response.request.headers.get('Content-Length', '0')
822+
#logger.debug("old request content length in core.py: %s", old_content_length)
823+
request = requests.Request(**requests_kwargs).prepare()
824+
#logger.debug("request content length in core.py: %s", request.headers.get('Content-Length'))
825+
request.headers['Content-Length'] = old_content_length # type: ignore
826+
827+
### Create new request with new content length
828+
# request = requests.Request(**requests_kwargs).prepare()
829+
#logger.debug("new request content length in core.py: %s", request.headers.get('Content-Length'))
830+
response.request = request
831+
#logger.debug("case in core.py: %s", case.body)
794832
run_checks(
795833
case=case,
796834
checks=checks,
@@ -804,11 +842,12 @@ def _network_test(
804842
status = Status.failure
805843
raise
806844
finally:
807-
# if feedback.stateful == Stateful.links:
808-
# logger.debug("stateful")
845+
if feedback.stateful == Stateful.links:
846+
logger.debug("Stateful")
809847
# do something
810848

811849
feedback.add_test_case(case, response)
850+
# logger.debug("feedback in core.py: ", feedback)
812851
if store_interactions:
813852
# Lưu lại interaction
814853
result.store_requests_response(case, response, status, check_results)

src/schemathesis/runner/serialization.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
They all consist of primitive types and don't have references to schemas, app, etc.
44
"""
55
from __future__ import annotations
6-
76
import logging
7+
from ..specs.openapi._vas import logger
88
import re
99
from dataclasses import dataclass, field
1010
from typing import TYPE_CHECKING, Any, cast
@@ -367,6 +367,7 @@ class SerializedInteraction:
367367

368368
@classmethod
369369
def from_interaction(cls, interaction: Interaction) -> SerializedInteraction:
370+
# logger.debug("deps/schemathesis/src/schemathesis/runner/serialization.py: serializing interaction")
370371
return cls(
371372
request=interaction.request,
372373
response=interaction.response,

src/schemathesis/serializers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ class Serializer(Protocol):
8181
"""
8282

8383
def as_requests(self, context: SerializerContext, payload: Any) -> dict[str, Any]:
84-
logger.debug(
85-
"deps/schemathesis/src/schemathesis/serializers.py: Serializing body"
86-
)
8784
raise NotImplementedError
8885

8986
def as_werkzeug(self, context: SerializerContext, payload: Any) -> dict[str, Any]:
@@ -256,6 +253,7 @@ def as_requests(self, context: SerializerContext, value: Any) -> dict[str, Any]:
256253
value = fast_deepcopy(value)
257254
multipart = _prepare_form_data(value)
258255
files, data = context.case.operation.prepare_multipart(multipart)
256+
# logger.debug("deps/schemathesis/src/schemathesis/serializers.py: files: %s", files)
259257
return {"files": files, "data": data}
260258
# Uncommon schema. For example - `{"type": "string"}`
261259
boundary = choose_boundary()

src/schemathesis/specs/openapi/_vas.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44
from functools import partial
55

6+
from dotenv import dotenv_values as get_dotenv_values
67
from hypothesis import strategies as st
78

89
# from faker import Faker
@@ -30,7 +31,9 @@
3031
# from faker_file.providers.zip_file import ZipFileProvider
3132

3233

33-
DEV = False
34+
dotenv_values = get_dotenv_values(".env")
35+
PYTHON_ENV = dotenv_values.get("PYTHON_ENV", None)
36+
DEV = PYTHON_ENV != "PROD"
3437

3538
# FAKER = Faker()
3639

@@ -97,7 +100,6 @@
97100
# "binary": get_file_strategy().map(Binary),
98101
# "byte": get_file_strategy().map(lambda x: b64encode(x).decode()),
99102
}
100-
101103
CURRENT_LEVEL = logging.DEBUG if DEV else logging.INFO
102104
CURRENT_FORMAT = (
103105
"%(asctime)s %(filename)s:%(lineno)d:%(funcName)s %(levelname)s:%(message)s"

src/schemathesis/specs/openapi/schemas.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,6 @@ def get_response_schema(
11151115
scopes, definition = self.resolver.resolve_in_scope(
11161116
fast_deepcopy(definition), scope
11171117
)
1118-
logger.debug("deps/schemathesis/src/schemathesis/specs/openapi/schemas.py: get_response_schema -> ")
11191118
options = iter(definition.get("content", {}).values())
11201119
option = next(options, None)
11211120
# "schema" is an optional key in the `MediaType` object

0 commit comments

Comments
 (0)