Skip to content

Commit

Permalink
feat: support other content-type
Browse files Browse the repository at this point in the history
Signed-off-by: Keming <kemingy94@gmail.com>
  • Loading branch information
kemingy committed Jan 19, 2025
1 parent 379b352 commit 26574aa
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,4 @@ cython_debug/

.ruff_cache/
*.json
*.html
22 changes: 18 additions & 4 deletions defspec/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from typing_extensions import Self


DEFAULT_CONTENT_TYPE = "application/json"


class OpenAPIInfo(msgspec.Struct, kw_only=True):
title: str = "OpenAPI"
description: str = "OpenAPI generated by defspec"
Expand All @@ -35,10 +38,13 @@ class JSONSchema(msgspec.Struct, kw_only=True, omit_defaults=True):
content: dict[str, dict] = msgspec.field(default_factory=dict)

@classmethod
def with_json_schema(cls, schema: dict[str, dict]) -> Self:
def with_schema_content_type(
cls, schema: dict[str, dict], content_type: Optional[str] = None
) -> Self:
instance = cls()
content_type = content_type or DEFAULT_CONTENT_TYPE
if schema.get("type", "") != "null":
instance.content["application/json"] = {"schema": schema}
instance.content[content_type] = {"schema": schema}
return instance


Expand Down Expand Up @@ -114,7 +120,9 @@ def register_route(
method: HTTP_METHODS,
summary: Optional[str] = None,
request_type: Optional[Type] = None,
request_content_type: Optional[str] = None,
response_type: Optional[Type] = None,
response_content_type: Optional[str] = None,
query_type: Optional[Type] = None,
header_type: Optional[Type] = None,
cookie_type: Optional[Type] = None,
Expand Down Expand Up @@ -142,8 +150,14 @@ def register_route(
self.paths[path][method] = OpenAPIRoute(
summary=summary or f"{method} from {path.replace('/', ' ')}",
operation_id=f"{method}_{path.replace('/', '_')}",
request_body=OpenAPIRequestBody.with_json_schema(request_schema),
responses={"200": OpenAPIResponse.with_json_schema(response_schema)},
request_body=OpenAPIRequestBody.with_schema_content_type(
request_schema, request_content_type
),
responses={
"200": OpenAPIResponse.with_schema_content_type(
response_schema, response_content_type
)
},
deprecated=deprecated,
)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ ignore = ["E501"]
[tool.ruff.lint.isort]
known-first-party = ["defspec"]
[tool.ruff.lint.pylint]
max-args = 10
max-args = 12
16 changes: 15 additions & 1 deletion tests/test_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ def openapi_spec(request):
header_type=parameter.header,
cookie_type=parameter.cookie,
)
openapi.register_route(
path="/test/msgpack",
method="post",
request_content_type="application/msgpack",
response_content_type="application/msgpack",
request_type=parameter.request,
response_type=parameter.response,
)
openapi.register_route(
path="/",
method="get",
Expand All @@ -187,7 +195,7 @@ def openapi_spec(request):

def test_openapi_spec(openapi_spec):
spec = openapi_spec.to_dict()
assert list(spec["paths"].keys()) == ["/test", "/"]
assert list(spec["paths"].keys()) == ["/test", "/test/msgpack", "/"]
assert list(spec["paths"]["/test"].keys()) == ["post"]
assert list(spec["paths"]["/"].keys()) == ["get"]

Expand All @@ -214,3 +222,9 @@ def test_openapi_spec(openapi_spec):
assert header["schema"]["$ref"].startswith("#/$defs/Header")
assert header["description"] == "Set your API key here."
assert cookie["schema"]["$ref"].startswith("#/$defs/Cookie")

msgpack = spec["paths"]["/test/msgpack"]["post"]
request = msgpack["requestBody"]["content"]["application/msgpack"]["schema"]
assert request["$ref"].startswith("#/$defs/RequestBody")
response = msgpack["responses"]["200"]["content"]["application/msgpack"]["schema"]
assert response["$ref"].startswith("#/$defs/Response")

0 comments on commit 26574aa

Please # to comment.