Skip to content

Commit df8786a

Browse files
authored
feat(Render): Use enum for renderer types (#91)
1 parent 48eaca0 commit df8786a

7 files changed

Lines changed: 177 additions & 186 deletions

File tree

fastapi_forge/project_io/artifact_builder/fastapi_builder.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from fastapi_forge.logger import logger
66
from fastapi_forge.render import create_jinja_render_manager
77
from fastapi_forge.render.manager import RenderManager
8+
from fastapi_forge.render.renderers.enums import RendererType
89
from fastapi_forge.schemas import (
910
Model,
1011
ProjectSpec,
@@ -15,12 +16,12 @@
1516
from .protocols import ArtifactBuilder
1617
from .utils import insert_relation_fields
1718

18-
TEST_RENDERERS: dict[HTTPMethodEnum, str] = {
19-
HTTPMethodEnum.GET: "test_get",
20-
HTTPMethodEnum.GET_ID: "test_get_id",
21-
HTTPMethodEnum.POST: "test_post",
22-
HTTPMethodEnum.PATCH: "test_patch",
23-
HTTPMethodEnum.DELETE: "test_delete",
19+
TEST_RENDERERS: dict[HTTPMethodEnum, RendererType] = {
20+
HTTPMethodEnum.GET: RendererType.TEST_GET,
21+
HTTPMethodEnum.GET_ID: RendererType.TEST_GET_ID,
22+
HTTPMethodEnum.POST: RendererType.TEST_POST,
23+
HTTPMethodEnum.PATCH: RendererType.TEST_PATCH,
24+
HTTPMethodEnum.DELETE: RendererType.TEST_DELETE,
2425
}
2526

2627

@@ -54,15 +55,15 @@ async def build_artifacts(self) -> None:
5455
tasks.append(self._write_enums())
5556

5657
for model in self.project_spec.models:
57-
tasks.append(self._write_artifact("models", model, "model"))
58+
tasks.append(self._write_artifact("models", model, RendererType.MODEL))
5859

5960
metadata = model.metadata
6061
if metadata.create_dtos:
61-
tasks.append(self._write_artifact("dtos", model, "dto"))
62+
tasks.append(self._write_artifact("dtos", model, RendererType.DTO))
6263
if metadata.create_daos:
63-
tasks.append(self._write_artifact("daos", model, "dao"))
64+
tasks.append(self._write_artifact("daos", model, RendererType.DAO))
6465
if metadata.create_endpoints:
65-
tasks.append(self._write_artifact("routes", model, "router"))
66+
tasks.append(self._write_artifact("routes", model, RendererType.ROUTER))
6667
if metadata.create_tests:
6768
tasks.append(self._write_tests(model))
6869

@@ -79,7 +80,7 @@ async def _create_module_path(self, module: str) -> Path:
7980
return path
8081

8182
async def _write_artifact(
82-
self, module: str, model: Model, renderer_type: str
83+
self, module: str, model: Model, renderer_type: RendererType
8384
) -> None:
8485
path = await self._create_module_path(module)
8586
file_name = f"{camel_to_snake(model.name)}_{module}.py"
@@ -114,6 +115,6 @@ async def _write_tests(self, model: Model) -> None:
114115

115116
async def _write_enums(self) -> None:
116117
path = self.package_dir / "enums.py"
117-
renderer = self.render_manager.get_renderer("enum")
118+
renderer = self.render_manager.get_renderer(RendererType.ENUM)
118119
content = renderer.render(self.project_spec.custom_enums)
119120
await self.io_writer.write_file(path, content)

fastapi_forge/render/manager.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
from .engines import TemplateEngine
2-
from .renderers import Renderer
2+
from .renderers import Renderer, RendererType
33

44

55
class RenderManager:
66
def __init__(
77
self,
88
engine: TemplateEngine,
9-
renderers: dict[str, type[Renderer]],
9+
renderers: dict[RendererType, type[Renderer]],
1010
):
1111
self.engine = engine
1212
self.renderers = renderers
13-
self._renderers: dict[str, Renderer] = {}
13+
self._renderers: dict[RendererType, Renderer] = {}
1414

15-
def get_renderer(self, renderer_type: str) -> Renderer:
15+
def get_renderer(self, renderer_type: RendererType) -> Renderer:
1616
"""Get a renderer instance for the specified type."""
1717
if renderer_type not in self.renderers:
1818
raise ValueError(

fastapi_forge/render/registry.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
from typing import TYPE_CHECKING, Any, ClassVar
22

3+
from .renderers.enums import RendererType
4+
35
if TYPE_CHECKING:
46
from .renderers import Renderer
57

68

79
class RendererRegistry:
8-
_renderers: ClassVar[dict[str, type["Renderer"]]] = {}
10+
_renderers: ClassVar[dict[RendererType, type["Renderer"]]] = {}
911

1012
@classmethod
11-
def register(cls, name: str) -> Any:
13+
def register(cls, renderer_type: RendererType) -> Any:
1214
def decorator(renderer_class: type["Renderer"]) -> type["Renderer"]:
13-
cls._renderers[name] = renderer_class
15+
cls._renderers[renderer_type] = renderer_class
1416
return renderer_class
1517

1618
return decorator
1719

1820
@classmethod
19-
def get_renderers(cls) -> dict[str, type["Renderer"]]:
21+
def get_renderers(cls) -> dict[RendererType, type["Renderer"]]:
2022
return cls._renderers.copy()
Lines changed: 139 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,140 @@
1-
__all__ = [
2-
"DAORenderer",
3-
"DTORenderer",
4-
"EnumRenderer",
5-
"ModelRenderer",
6-
"Renderer",
7-
"RouterRenderer",
8-
"TestDeleteRenderer",
9-
"TestGetIdRenderer",
10-
"TestGetRenderer",
11-
"TestPatchRenderer",
12-
"TestPostRenderer",
13-
]
14-
15-
from .renderers import (
16-
DAORenderer,
17-
DTORenderer,
18-
EnumRenderer,
19-
ModelRenderer,
20-
Renderer,
21-
RouterRenderer,
22-
TestDeleteRenderer,
23-
TestGetIdRenderer,
24-
TestGetRenderer,
25-
TestPatchRenderer,
26-
TestPostRenderer,
1+
from typing import Any
2+
3+
from fastapi_forge.schemas import CustomEnum, Model
4+
5+
from ..engines import TemplateEngine
6+
from ..registry import RendererRegistry
7+
from ..templates import (
8+
DAO_TEMPLATE,
9+
DTO_TEMPLATE,
10+
ENUMS_TEMPLATE,
11+
MODEL_TEMPLATE,
12+
ROUTERS_TEMPLATE,
13+
TEST_DELETE_TEMPLATE,
14+
TEST_GET_ID_TEMPLATE,
15+
TEST_GET_TEMPLATE,
16+
TEST_PATCH_TEMPLATE,
17+
TEST_POST_TEMPLATE,
2718
)
19+
from .enums import RendererType
20+
from .protocols import Renderer
21+
22+
23+
@RendererRegistry.register(RendererType.MODEL)
24+
class ModelRenderer(Renderer):
25+
def __init__(self, engine: TemplateEngine) -> None:
26+
self.engine = engine
27+
28+
def render(self, data: Model, **kwargs: Any) -> str:
29+
return self.engine.render(
30+
MODEL_TEMPLATE,
31+
{"model": data, **kwargs},
32+
)
33+
34+
35+
@RendererRegistry.register(RendererType.ROUTER)
36+
class RouterRenderer(Renderer):
37+
def __init__(self, engine: TemplateEngine) -> None:
38+
self.engine = engine
39+
40+
def render(self, data: Model, **kwargs: Any) -> str:
41+
return self.engine.render(
42+
ROUTERS_TEMPLATE,
43+
{"model": data, **kwargs},
44+
)
45+
46+
47+
@RendererRegistry.register(RendererType.DAO)
48+
class DAORenderer(Renderer):
49+
def __init__(self, engine: TemplateEngine) -> None:
50+
self.engine = engine
51+
52+
def render(self, data: Model, **kwargs: Any) -> str:
53+
return self.engine.render(
54+
DAO_TEMPLATE,
55+
{"model": data, **kwargs},
56+
)
57+
58+
59+
@RendererRegistry.register(RendererType.DTO)
60+
class DTORenderer(Renderer):
61+
def __init__(self, engine: TemplateEngine) -> None:
62+
self.engine = engine
63+
64+
def render(self, data: Model, **kwargs: Any) -> str:
65+
return self.engine.render(
66+
DTO_TEMPLATE,
67+
{"model": data, **kwargs},
68+
)
69+
70+
71+
@RendererRegistry.register(RendererType.TEST_POST)
72+
class TestPostRenderer(Renderer):
73+
def __init__(self, engine: TemplateEngine) -> None:
74+
self.engine = engine
75+
76+
def render(self, data: Model, **kwargs: Any) -> str:
77+
return self.engine.render(
78+
TEST_POST_TEMPLATE,
79+
{"model": data, **kwargs},
80+
)
81+
82+
83+
@RendererRegistry.register(RendererType.TEST_GET)
84+
class TestGetRenderer(Renderer):
85+
def __init__(self, engine: TemplateEngine) -> None:
86+
self.engine = engine
87+
88+
def render(self, data: Model, **kwargs: Any) -> str:
89+
return self.engine.render(
90+
TEST_GET_TEMPLATE,
91+
{"model": data, **kwargs},
92+
)
93+
94+
95+
@RendererRegistry.register(RendererType.TEST_GET_ID)
96+
class TestGetIdRenderer(Renderer):
97+
def __init__(self, engine: TemplateEngine) -> None:
98+
self.engine = engine
99+
100+
def render(self, data: Model, **kwargs: Any) -> str:
101+
return self.engine.render(
102+
TEST_GET_ID_TEMPLATE,
103+
{"model": data, **kwargs},
104+
)
105+
106+
107+
@RendererRegistry.register(RendererType.TEST_PATCH)
108+
class TestPatchRenderer(Renderer):
109+
def __init__(self, engine: TemplateEngine) -> None:
110+
self.engine = engine
111+
112+
def render(self, data: Model, **kwargs: Any) -> str:
113+
return self.engine.render(
114+
TEST_PATCH_TEMPLATE,
115+
{"model": data, **kwargs},
116+
)
117+
118+
119+
@RendererRegistry.register(RendererType.TEST_DELETE)
120+
class TestDeleteRenderer(Renderer):
121+
def __init__(self, engine: TemplateEngine) -> None:
122+
self.engine = engine
123+
124+
def render(self, data: Model, **kwargs: Any) -> str:
125+
return self.engine.render(
126+
TEST_DELETE_TEMPLATE,
127+
{"model": data, **kwargs},
128+
)
129+
130+
131+
@RendererRegistry.register(RendererType.ENUM)
132+
class EnumRenderer(Renderer):
133+
def __init__(self, engine: TemplateEngine) -> None:
134+
self.engine = engine
135+
136+
def render(self, data: list[CustomEnum], **kwargs: Any) -> str:
137+
return self.engine.render(
138+
ENUMS_TEMPLATE,
139+
{"enums": data, **kwargs},
140+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from enum import StrEnum, auto
2+
3+
4+
class RendererType(StrEnum):
5+
MODEL = auto()
6+
ROUTER = auto()
7+
DAO = auto()
8+
DTO = auto()
9+
TEST_POST = auto()
10+
TEST_GET = auto()
11+
TEST_GET_ID = auto()
12+
TEST_PATCH = auto()
13+
TEST_DELETE = auto()
14+
ENUM = auto()

0 commit comments

Comments
 (0)