Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Tinche committed Dec 19, 2023
1 parent d85d6cb commit b16d245
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 19 deletions.
17 changes: 9 additions & 8 deletions src/uapi/_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from .openapi import (
AnySchema,
ApiKeySecurityScheme,
ArraySchema,
IntegerSchema,
MediaType,
MediaTypeName,
OneOfSchema,
Expand Down Expand Up @@ -142,11 +144,10 @@ def build_operation(
# It's a dict.
v_type = req_type.__args__[1] # type: ignore[attr-defined]

add_prop: Reference | Schema = (
builder.get_schema_for_type(v_type)
if has(v_type)
else builder.PYTHON_PRIMITIVES_TO_OPENAPI[v_type]
)
add_prop = builder.get_schema_for_type(v_type)

if isinstance(add_prop, ArraySchema):
raise Exception("Arrayschema not supported.")

request_bodies[loader.content_type or "*/*"] = MediaType(
Schema(Schema.Type.OBJECT, additionalProperties=add_prop)
Expand All @@ -162,13 +163,13 @@ def build_operation(
)
else:
if is_union_type(arg_type):
refs: list[Reference | Schema] = []
refs: list[Reference | Schema | IntegerSchema] = []
for union_member in arg_type.__args__:
if union_member is NoneType:
refs.append(Schema(Schema.Type.NULL))
elif union_member in builder.PYTHON_PRIMITIVES_TO_OPENAPI:
refs.append(builder.get_schema_for_type(union_member))
param_schema: OneOfSchema | Schema = OneOfSchema(refs)
refs.append(builder.PYTHON_PRIMITIVES_TO_OPENAPI[union_member])
param_schema: OneOfSchema | Schema | IntegerSchema = OneOfSchema(refs)
else:
param_schema = builder.PYTHON_PRIMITIVES_TO_OPENAPI.get(
arg_param.annotation, builder.PYTHON_PRIMITIVES_TO_OPENAPI[str]
Expand Down
18 changes: 12 additions & 6 deletions src/uapi/attrschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
from attrs import NOTHING, fields, has
from cattrs._compat import is_generic, is_literal, is_union_type

from .openapi import AnySchema, OneOfSchema, Reference, Schema, SchemaBuilder
from .openapi import (
AnySchema,
ArraySchema,
OneOfSchema,
Reference,
Schema,
SchemaBuilder,
)


def _make_generic_mapping(type: type) -> dict:
Expand Down Expand Up @@ -43,16 +50,15 @@ def build_attrs_schema(type: Any, builder: SchemaBuilder) -> Schema:
elif getattr(a_type, "__origin__", None) is dict:
val_arg = a_type.__args__[1]

if has(val_arg):
add_prop: Reference | Schema = builder.get_schema_for_type(val_arg)
else:
add_prop = builder.PYTHON_PRIMITIVES_TO_OPENAPI[val_arg]
add_prop = builder.get_schema_for_type(val_arg)
if isinstance(add_prop, ArraySchema):
raise Exception("Arrays in additional properties not supported.")

schema = Schema(Schema.Type.OBJECT, additionalProperties=add_prop)
elif is_literal(a_type):
schema = Schema(Schema.Type.STRING, enum=list(a_type.__args__))
elif is_union_type(a_type):
refs: list[Reference | Schema] = []
refs: list[Reference | AnySchema] = []
for arg in a_type.__args__:
if has(arg):
refs.append(builder.get_schema_for_type(arg))
Expand Down
16 changes: 11 additions & 5 deletions src/uapi/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Type(Enum):
type: Type
properties: dict[str, AnySchema | Reference] | None = None
format: str | None = None
additionalProperties: bool | Schema | Reference = False
additionalProperties: bool | Schema | IntegerSchema | Reference = False
enum: list[str] | None = None
required: list[str] = Factory(list)

Expand Down Expand Up @@ -164,7 +164,7 @@ class Path:
class SchemaBuilder:
"""A helper builder for defining OpenAPI/JSON schemas."""

PYTHON_PRIMITIVES_TO_OPENAPI: ClassVar = {
PYTHON_PRIMITIVES_TO_OPENAPI: ClassVar[dict[type, Schema | IntegerSchema]] = {
str: Schema(Schema.Type.STRING),
int: IntegerSchema(),
bool: Schema(Schema.Type.BOOLEAN),
Expand Down Expand Up @@ -194,7 +194,9 @@ def build_schema_from_rules(self, type: Any) -> AnySchema:
self._build_queue.remove(type)
return r

def get_schema_for_type(self, type: Any) -> Reference | Schema | ArraySchema:
def get_schema_for_type(
self, type: Any
) -> Reference | Schema | IntegerSchema | ArraySchema:
# First check inline types.
if type in self.PYTHON_PRIMITIVES_TO_OPENAPI:
return self.PYTHON_PRIMITIVES_TO_OPENAPI[type]
Expand Down Expand Up @@ -286,13 +288,17 @@ def _structure_schema_or_ref(val, _) -> Schema | IntegerSchema | Reference:
),
)
converter.register_structure_hook(
bool | Schema | Reference,
bool | Schema | IntegerSchema | Reference,
lambda v, _: v
if isinstance(v, bool)
else (
converter.structure(v, Reference)
if "$ref" in v
else converter.structure(v, Schema)
else (
converter.structure(v, IntegerSchema)
if v["type"] == "integer"
else converter.structure(v, Schema)
)
),
)
converter.register_structure_hook(
Expand Down

0 comments on commit b16d245

Please sign in to comment.