Skip to content

Commit

Permalink
Request binary format support
Browse files Browse the repository at this point in the history
  • Loading branch information
p1c2u committed Oct 31, 2023
1 parent 16e7b1a commit 0cf49c0
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 59 deletions.
37 changes: 19 additions & 18 deletions openapi_core/deserializing/media_types/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,11 @@
from werkzeug.datastructures import ImmutableMultiDict


def binary_loads(value: Union[str, bytes], **parameters: str) -> bytes:
charset = "utf-8"
if "charset" in parameters:
charset = parameters["charset"]
if isinstance(value, str):
return value.encode(charset)
def binary_loads(value: bytes, **parameters: str) -> bytes:
return value


def plain_loads(value: Union[str, bytes], **parameters: str) -> str:
def plain_loads(value: bytes, **parameters: str) -> str:
charset = "utf-8"
if "charset" in parameters:
charset = parameters["charset"]
Expand All @@ -32,30 +27,36 @@ def plain_loads(value: Union[str, bytes], **parameters: str) -> str:
return value


def json_loads(value: Union[str, bytes], **parameters: str) -> Any:
def json_loads(value: bytes, **parameters: str) -> Any:
return loads(value)


def xml_loads(value: Union[str, bytes], **parameters: str) -> Element:
return fromstring(value)
def xml_loads(value: bytes, **parameters: str) -> Element:
charset = "utf-8"
if "charset" in parameters:
charset = parameters["charset"]
return fromstring(value.decode(charset))


def urlencoded_form_loads(value: Any, **parameters: str) -> Mapping[str, Any]:
return ImmutableMultiDict(parse_qsl(value))
def urlencoded_form_loads(
value: bytes, **parameters: str
) -> Mapping[str, Any]:
# only UTF-8 is conforming
return ImmutableMultiDict(parse_qsl(value.decode("utf-8")))


def data_form_loads(
value: Union[str, bytes], **parameters: str
) -> Mapping[str, Any]:
if isinstance(value, bytes):
value = value.decode("ASCII", errors="surrogateescape")
def data_form_loads(value: bytes, **parameters: str) -> Mapping[str, Any]:
charset = "ASCII"
if "charset" in parameters:
charset = parameters["charset"]
decoded = value.decode(charset, errors="surrogateescape")
boundary = ""
if "boundary" in parameters:
boundary = parameters["boundary"]
parser = Parser()
mimetype = "multipart/form-data"
header = f'Content-Type: {mimetype}; boundary="{boundary}"'
text = "\n\n".join([header, value])
text = "\n\n".join([header, decoded])
parts = parser.parsestr(text, headersonly=False)
return ImmutableMultiDict(
[
Expand Down
2 changes: 1 addition & 1 deletion openapi_core/testing/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def __init__(
view_args: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, Any]] = None,
cookies: Optional[Dict[str, Any]] = None,
data: Optional[str] = None,
data: Optional[bytes] = None,
content_type: str = "application/json",
):
self.host_url = host_url
Expand Down
38 changes: 19 additions & 19 deletions tests/integration/test_petstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ def test_post_birds(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -770,7 +770,7 @@ def test_post_cats(self, spec, spec_dict):
},
"extra": None,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -841,7 +841,7 @@ def test_post_cats_boolean_string(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -915,7 +915,7 @@ def test_post_urlencoded(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = urlencode(data_json)
data = urlencode(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -985,7 +985,7 @@ def test_post_no_one_of_schema(self, spec):
"name": pet_name,
"alias": alias,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -1037,7 +1037,7 @@ def test_post_cats_only_required_body(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -1088,7 +1088,7 @@ def test_post_pets_raises_invalid_mimetype(self, spec):
"name": "Cat",
"tag": "cats",
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -1141,7 +1141,7 @@ def test_post_pets_missing_cookie(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -1184,7 +1184,7 @@ def test_post_pets_missing_header(self, spec, spec_dict):
"healthy": pet_healthy,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
cookies = {
"user": "123",
}
Expand Down Expand Up @@ -1223,7 +1223,7 @@ def test_post_pets_raises_invalid_server_error(self, spec):
"name": "Cat",
"tag": "cats",
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": "12345",
}
Expand Down Expand Up @@ -1509,7 +1509,7 @@ def test_post_tags_extra_body_properties(self, spec):
"name": pet_name,
"alias": alias,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1539,7 +1539,7 @@ def test_post_tags_empty_body(self, spec):
host_url = "http://petstore.swagger.io/v1"
path_pattern = "/v1/tags"
data_json = {}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1569,7 +1569,7 @@ def test_post_tags_wrong_property_type(self, spec):
host_url = "http://petstore.swagger.io/v1"
path_pattern = "/v1/tags"
tag_name = 123
data = json.dumps(tag_name)
data = json.dumps(tag_name).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1602,7 +1602,7 @@ def test_post_tags_additional_properties(self, spec):
data_json = {
"name": pet_name,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1658,7 +1658,7 @@ def test_post_tags_created_now(self, spec):
"created": created,
"name": pet_name,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1715,7 +1715,7 @@ def test_post_tags_created_datetime(self, spec):
"created": created,
"name": pet_name,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1787,7 +1787,7 @@ def test_post_tags_urlencoded(self, spec):
"created": created,
"name": pet_name,
}
data = urlencode(data_json)
data = urlencode(data_json).encode()
content_type = "application/x-www-form-urlencoded"

request = MockRequest(
Expand Down Expand Up @@ -1861,7 +1861,7 @@ def test_post_tags_created_invalid_type(self, spec):
"created": created,
"name": pet_name,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()

request = MockRequest(
host_url,
Expand Down Expand Up @@ -1918,7 +1918,7 @@ def test_delete_tags_with_requestbody(self, spec):
data_json = {
"ids": ids,
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
request = MockRequest(
host_url,
"DELETE",
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/unmarshalling/test_read_only_write_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_write_a_read_only_property(self, request_unmarshaller):
"id": 10,
"name": "Pedro",
}
)
).encode()

request = MockRequest(
host_url="", method="POST", path="/users", data=data
Expand Down Expand Up @@ -77,7 +77,7 @@ def test_write_only_property(self, request_unmarshaller):
"name": "Pedro",
"hidden": False,
}
)
).encode()

request = MockRequest(
host_url="", method="POST", path="/users", data=data
Expand All @@ -98,7 +98,7 @@ def test_read_a_write_only_property(self, response_unmarshaller):
"name": "Pedro",
"hidden": True,
}
)
).encode()

request = MockRequest(host_url="", method="POST", path="/users")
response = MockResponse(data)
Expand Down
10 changes: 5 additions & 5 deletions tests/integration/unmarshalling/test_request_unmarshaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def test_missing_body(self, request_unmarshaller):
)

def test_invalid_content_type(self, request_unmarshaller):
data = "csv,data"
data = b"csv,data"
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -231,7 +231,7 @@ def test_invalid_complex_parameter(self, request_unmarshaller, spec_dict):
"healthy": True,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -296,7 +296,7 @@ def test_post_pets(self, request_unmarshaller, spec_dict):
"healthy": True,
},
}
data = json.dumps(data_json)
data = json.dumps(data_json).encode()
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -338,7 +338,7 @@ def test_post_pets(self, request_unmarshaller, spec_dict):
assert result.body.address.city == pet_city

def test_post_pets_plain_no_schema(self, request_unmarshaller):
data = "plain text"
data = b"plain text"
headers = {
"api-key": self.api_key_encoded,
}
Expand Down Expand Up @@ -368,7 +368,7 @@ def test_post_pets_plain_no_schema(self, request_unmarshaller):
},
)
assert result.security == {}
assert result.body == data
assert result.body == data.decode()

def test_get_pet_unauthorized(self, request_unmarshaller):
request = MockRequest(
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/validation/test_request_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def test_security_not_found(self, request_validator):
)

def test_media_type_not_found(self, request_validator):
data = "csv,data"
data = b"csv,data"
headers = {
"api-key": self.api_key_encoded,
}
Expand Down
Loading

0 comments on commit 0cf49c0

Please sign in to comment.