Skip to content

Commit ef984ce

Browse files
author
Joakim Nordling
authored
Add support for dependencies in routes and support Python 3.12 (#44)
This PR includes: - Support for dependencies in post routes. - Support for Python 3.12. - Updates FastAPI to `^0.111.0`. - Switches from `snapshottest` to `syrupy` (restricted lower Python version boundary to 3.8.1 due to syrupy). - Updates `datamodel-code-generator`. - Updates to pre-commit hooks and a lot of dependencies.
1 parent b6907bd commit ef984ce

14 files changed

Lines changed: 995 additions & 1017 deletions

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
python-version: ["3.8", "3.9", "3.10", "3.11"]
13+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
1414
steps:
1515
- name: Checkout 🔁
1616
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1

.pre-commit-config.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
rev: v4.5.0
5+
rev: v4.6.0
66
hooks:
77
- id: trailing-whitespace
88
- id: end-of-file-fixer
@@ -21,24 +21,25 @@ repos:
2121
args: ["--fix=crlf"]
2222
files: \.bat$
2323
- repo: https://github.com/pycqa/isort
24-
rev: 5.12.0
24+
rev: 5.13.2
2525
hooks:
2626
- id: isort
2727
language_version: python3
2828
- repo: https://github.com/psf/black
29-
rev: 23.11.0
29+
rev: 24.4.2
3030
hooks:
3131
- id: black
3232
language_version: python3
3333
- repo: https://github.com/pre-commit/mirrors-prettier
3434
rev: v3.1.0
3535
hooks:
3636
- id: prettier
37+
exclude: "^openapi_to_fastapi/tests/__snapshots__/"
3738
- repo: https://github.com/pycqa/flake8
38-
rev: 6.1.0
39+
rev: 7.0.0
3940
hooks:
4041
- id: flake8
4142
- repo: https://github.com/twu/skjold
42-
rev: v0.6.1
43+
rev: v0.6.2
4344
hooks:
4445
- id: skjold

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ router = SpecRouter(specs, validators=[MyValidator])
255255

256256
You will need:
257257

258-
- Python 3.8+ (though 3.11+ might have some issues with dependencies)
258+
- Python 3.8.1+ (tested on 3.8 - 3.12)
259259
- [pre-commit](https://pre-commit.com/#install)
260260

261261
Before working on the project, make sure you run:

openapi_to_fastapi/model_generator.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ def generate_model_from_schema(schema: str, format_code: bool = False) -> str:
3131
extra_template_data=None,
3232
target_python_version=PythonVersion.PY_38,
3333
dump_resolve_reference_action=None,
34-
# Validation of OpenAPI 3.1 specs isn't supported right now. Issues:
35-
# https://github.com/koxudaxi/datamodel-code-generator/issues/1649 and
36-
# https://github.com/RonnyPfannschmidt/prance/issues/95
37-
validation=False,
3834
field_constraints=False,
3935
snake_case_field=False,
4036
strip_default_none=False,

openapi_to_fastapi/routes.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import json
22
from dataclasses import dataclass, field
33
from pathlib import Path
4-
from typing import Any, Callable, Dict, List, Optional, Type, Union
4+
from typing import Any, Callable, Dict, List, Optional, Sequence, Type, Union
55

66
import pydantic
7-
from fastapi import APIRouter
7+
from fastapi import APIRouter, params
88
from fastapi.openapi import models as oas
99

1010
from .model_generator import load_models
@@ -35,6 +35,7 @@ class RouteInfo:
3535
tags: Optional[List[str]] = None
3636
summary: Optional[str] = None
3737
deprecated: Optional[bool] = None
38+
dependencies: Optional[Sequence[params.Depends]] = None
3839

3940
request_model: Optional[Type[pydantic.BaseModel]] = None
4041
response_model: Optional[Type[pydantic.BaseModel]] = None
@@ -188,6 +189,7 @@ def post(
188189
response_description: Optional[str] = None,
189190
name_factory: Optional[Callable] = None,
190191
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
192+
dependencies: Optional[Sequence[params.Depends]] = None,
191193
):
192194
"""
193195
Define implementation for a specific POST route
@@ -201,6 +203,7 @@ def post(
201203
:param description: Route description. Got from OpenAPI spec by default
202204
:param response_description: Description of the response
203205
:param responses: Possible responses the route may return. Used in documentation
206+
:param dependencies: Possible dependencies to add to the route.
204207
"""
205208

206209
def _wrapper(fn):
@@ -215,6 +218,7 @@ def _wrapper(fn):
215218
route_info.tags = tags
216219
route_info.name_factory = name_factory
217220
route_info.responses = responses
221+
route_info.dependencies = dependencies
218222

219223
if response_description:
220224
route_info.response_description = response_description
@@ -258,5 +262,6 @@ def to_fastapi_router(self):
258262
responses=route_info.responses,
259263
tags=route_info.tags,
260264
deprecated=route_info.deprecated,
265+
dependencies=route_info.dependencies,
261266
)(handler)
262267
return router
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"detail": [
3+
{
4+
"input": null,
5+
"loc": [
6+
"query",
7+
"vendor"
8+
],
9+
"msg": "Field required",
10+
"type": "missing"
11+
},
12+
{
13+
"input": null,
14+
"loc": [
15+
"header",
16+
"auth-header"
17+
],
18+
"msg": "Field required",
19+
"type": "missing"
20+
}
21+
]
22+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"detail": [
3+
{
4+
"input": "1,1.2",
5+
"loc": [
6+
"body",
7+
"lat"
8+
],
9+
"msg": "Input should be a valid number, unable to parse string as a number",
10+
"type": "float_parsing"
11+
},
12+
{
13+
"ctx": {
14+
"le": 180.0
15+
},
16+
"input": "99999",
17+
"loc": [
18+
"body",
19+
"lon"
20+
],
21+
"msg": "Input should be less than or equal to 180",
22+
"type": "less_than_equal"
23+
}
24+
]
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"detail": [
3+
{
4+
"input": {},
5+
"loc": [
6+
"body",
7+
"lat"
8+
],
9+
"msg": "Field required",
10+
"type": "missing"
11+
},
12+
{
13+
"input": {},
14+
"loc": [
15+
"body",
16+
"lon"
17+
],
18+
"msg": "Field required",
19+
"type": "missing"
20+
}
21+
]
22+
}

openapi_to_fastapi/tests/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
from fastapi import FastAPI
55
from starlette.testclient import TestClient
6+
from syrupy.extensions.json import JSONSnapshotExtension
67

78
from openapi_to_fastapi.routes import SpecRouter
89

@@ -28,3 +29,8 @@ def definitions_client(specs_root):
2829
spec_router = SpecRouter(specs_root / "definitions")
2930
app.include_router(spec_router.to_fastapi_router())
3031
return TestClient(app)
32+
33+
34+
@pytest.fixture
35+
def json_snapshot(snapshot):
36+
return snapshot.use_extension(JSONSnapshotExtension)

openapi_to_fastapi/tests/snapshots/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)