Skip to content

Commit

Permalink
perf: Minor performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Stranger6667 committed May 17, 2024
1 parent d12b70e commit 54a705f
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 14 deletions.
7 changes: 5 additions & 2 deletions src/schemathesis/specs/openapi/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ def get_links(self, operation: APIOperation) -> dict[str, dict[str, Any]]:
return result

def get_tags(self, operation: APIOperation) -> list[str] | None:
return operation.definition.resolved.get("tags")
return operation.definition.raw.get("tags")

def validate_response(self, operation: APIOperation, response: GenericResponse) -> bool | None:
responses = {str(key): value for key, value in operation.definition.raw.get("responses", {}).items()}
Expand Down Expand Up @@ -1100,7 +1100,10 @@ def _get_parameter_serializer(self, definitions: list[dict[str, Any]]) -> Callab
return serialization.serialize_openapi3_parameters(definitions)

def get_request_payload_content_types(self, operation: APIOperation) -> list[str]:
return list(operation.definition.resolved["requestBody"]["content"].keys())
request_body = operation.definition.raw["requestBody"]
while "$ref" in request_body:
_, request_body = self.resolver.resolve(request_body["$ref"])
return list(request_body["content"].keys())

def prepare_multipart(
self, form_data: FormData, operation: APIOperation
Expand Down
10 changes: 5 additions & 5 deletions src/schemathesis/specs/openapi/stateful/links.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Callable, Dict, List
from typing import TYPE_CHECKING, Callable, Dict, List, Iterator

import hypothesis.strategies as st
from requests.structures import CaseInsensitiveDict
Expand Down Expand Up @@ -30,7 +30,7 @@ def apply(
connections: APIOperationConnections,
) -> None:
"""Gather all connections based on Open API links definitions."""
all_status_codes = list(operation.definition.resolved["responses"])
all_status_codes = operation.definition.raw["responses"].keys()
for status_code, link in get_all_links(operation):
target_operation = link.get_target_operation()
strategy = bundles[operation.path][operation.method.upper()].filter(
Expand All @@ -47,7 +47,7 @@ def _convert_strategy(
return strategy.map(lambda out: (out, link))


def make_response_filter(status_code: str, all_status_codes: list[str]) -> FilterFunction:
def make_response_filter(status_code: str, all_status_codes: Iterator[str]) -> FilterFunction:
"""Create a filter for stored responses.
This filter will decide whether some response is suitable to use as a source for requesting some API operation.
Expand Down Expand Up @@ -76,11 +76,11 @@ def compare(result: StepResult) -> bool:
return compare


def default_status_code(status_codes: list[str]) -> FilterFunction:
def default_status_code(status_codes: Iterator[str]) -> FilterFunction:
"""Create a filter that matches all "default" responses.
In Open API, the "default" response is the one that is used if no other options were matched.
Therefore we need to match only responses that were not matched by other listed status codes.
Therefore, we need to match only responses that were not matched by other listed status codes.
"""
expanded_status_codes = {
status_code for value in status_codes if value != "default" for status_code in expand_status_code(value)
Expand Down
2 changes: 2 additions & 0 deletions src/schemathesis/transports/content_types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from functools import lru_cache
from typing import Tuple, Generator


Expand Down Expand Up @@ -30,6 +31,7 @@ def parse_header(line: str) -> Tuple[str, dict]:
return key, pdict


@lru_cache()
def parse_content_type(content_type: str) -> Tuple[str, str]:
"""Parse Content Type and return main type and subtype."""
try:
Expand Down
33 changes: 26 additions & 7 deletions test/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,44 @@ def schema_with_payload(empty_open_api_3_schema):
},
"responses": {"200": {"description": "OK"}},
},
"put": {
"requestBody": {"$ref": "#/components/requestBodies/Sample"},
"responses": {"200": {"description": "OK"}},
},
"patch": {
"requestBody": {"$ref": "#/components/requestBodies/Ref"},
"responses": {"200": {"description": "OK"}},
},
},
}
return schemathesis.from_dict(empty_open_api_3_schema)
empty_open_api_3_schema["components"] = {
"requestBodies": {
"Sample": {
"required": True,
"content": {"text/plain": {"schema": {"type": "object"}}},
},
"Ref": {"$ref": "#/components/requestBodies/Sample"},
}
}
return schemathesis.from_dict(empty_open_api_3_schema, validate_schema=True)


def test_make_case_explicit_media_type(schema_with_payload):
# When there is only one possible media type
# And the `media_type` argument is passed to `make_case` explicitly
case = schema_with_payload["/data"]["POST"].make_case(body="<foo></foo>", media_type="text/xml")
# Then this explicit media type should be in `case`
assert case.media_type == "text/xml"
for method in ("POST", "PUT", "PATCH"):
case = schema_with_payload["/data"][method].make_case(body="<foo></foo>", media_type="text/xml")
# Then this explicit media type should be in `case`
assert case.media_type == "text/xml"


def test_make_case_automatic_media_type(schema_with_payload):
# When there is only one possible media type
# And the `media_type` argument is not passed to `make_case`
case = schema_with_payload["/data"]["POST"].make_case(body="foo")
# Then it should be chosen automatically
assert case.media_type == "text/plain"
for method in ("POST", "PUT", "PATCH"):
case = schema_with_payload["/data"][method].make_case(body="foo")
# Then it should be chosen automatically
assert case.media_type == "text/plain"


def test_make_case_missing_media_type(empty_open_api_3_schema):
Expand Down

0 comments on commit 54a705f

Please sign in to comment.