Skip to content

Commit 581a247

Browse files
author
Anders Brams
committed
feat: separate type aliases for route methods
1 parent eda5385 commit 581a247

5 files changed

Lines changed: 44 additions & 362 deletions

File tree

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.13
1+
3.12

openapi_python/generator/render.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,10 @@ def _fallback_method_block(
233233

234234

235235
def _render_types(spec: NormalizedSpec) -> str:
236+
aliases = (*_route_aliases(spec), *_order_aliases(spec.aliases))
236237
blocks = (
237238
[_format_enum(item) for item in spec.enums]
238-
+ [_format_alias(alias) for alias in _order_aliases(spec.aliases)]
239+
+ [_format_alias(alias) for alias in aliases]
239240
+ [_format_typeddict(item) for item in _order_typeddicts(spec.typed_dicts)]
240241
)
241242
return _render_template(
@@ -244,14 +245,39 @@ def _render_types(spec: NormalizedSpec) -> str:
244245
)
245246

246247

248+
def _literal_annotation(values: set[str]) -> str:
249+
return f"Literal[{', '.join(repr(value) for value in sorted(values))}]"
250+
251+
252+
def _route_aliases(spec: NormalizedSpec) -> tuple[TypeAliasDef, ...]:
253+
routes_by_method: dict[str, set[str]] = {}
254+
for op in spec.operations:
255+
routes_by_method.setdefault(op.method.upper(), set()).add(op.route_literal)
256+
257+
aliases = [
258+
TypeAliasDef(
259+
name=f"{method}_RouteLiteral", annotation=_literal_annotation(routes)
260+
)
261+
for method, routes in sorted(routes_by_method.items())
262+
]
263+
264+
if aliases:
265+
aliases.append(
266+
TypeAliasDef(
267+
name="RouteLiteral",
268+
annotation=" | ".join(alias.name for alias in aliases),
269+
)
270+
)
271+
else:
272+
aliases.append(TypeAliasDef(name="RouteLiteral", annotation="str"))
273+
return tuple(aliases)
274+
275+
247276
def _render_transport(spec: NormalizedSpec, *, transport_mode: str) -> str:
248277
return _render_template(
249278
"transport.py.j2",
250-
route_literals=[op.route_literal for op in spec.operations],
251279
typing_imports=(
252-
"TYPE_CHECKING, Literal, Protocol"
253-
if transport_mode == "default"
254-
else "Literal, Protocol"
280+
"TYPE_CHECKING, Protocol" if transport_mode == "default" else "Protocol"
255281
),
256282
include_default_transport=transport_mode == "default",
257283
)

openapi_python/generator/templates/transport.py.j2

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,13 @@ from __future__ import annotations
33
from collections.abc import Mapping
44
from typing import {{ typing_imports }}
55

6+
from .types import RouteLiteral as RouteLiteral
7+
68
{% if include_default_transport %}
79
if TYPE_CHECKING:
810
import httpx
911

1012
{% endif %}
11-
RouteLiteral = Literal[
12-
{% for route_literal in route_literals %}
13-
{{ route_literal|repr }},
14-
{% endfor %}
15-
]
16-
1713

1814
class Transport(Protocol):
1915
def request(

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ description = "Autogenerated and fully typed OpenAPI Python clients with a devel
2323
authors = [{ name = "Anders Brams", email = "anders@brams.dk" }]
2424

2525
readme = "README.md"
26-
requires-python = ">=3.9"
26+
requires-python = ">=3.12"
2727
dependencies = ["jinja2>=3.1.0"]
2828

2929
[project.optional-dependencies]

0 commit comments

Comments
 (0)