Skip to content

Commit 44d552e

Browse files
committed
DataTypeInfo
1 parent 638a2d6 commit 44d552e

4 files changed

Lines changed: 85 additions & 54 deletions

File tree

fastapi_forge/enums.py

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import StrEnum
2-
from typing import Any
2+
from uuid import uuid4
33

44

55
class HTTPMethod(StrEnum):
@@ -20,8 +20,8 @@ class FieldDataType(StrEnum):
2020
JSONB = "JSONB"
2121

2222

23+
# register a DataTypeInfo with a FieldDataType to make it easier to support types
2324
class DataTypeInfo:
24-
2525
def __init__(
2626
self,
2727
pydantic_annotation: str,
@@ -31,7 +31,7 @@ def __init__(
3131
faker_generator: str,
3232
value: str,
3333
test_value: str,
34-
test_func: str,
34+
test_func: str = "",
3535
):
3636
self.pydantic_annotation = pydantic_annotation
3737
self.sqlalchemy_type = sqlalchemy_type
@@ -67,27 +67,92 @@ def all(self) -> list[DataTypeInfo]:
6767
registry.register(
6868
FieldDataType.STRING,
6969
DataTypeInfo(
70-
pydantic_annotation="",
70+
pydantic_annotation="str",
7171
sqlalchemy_type="String",
7272
sqlalchemy_prefix=False,
7373
python_type="str",
7474
faker_generator="text",
7575
value="hello",
76-
test_value='"world"',
76+
test_value="'world'",
7777
test_func="",
7878
),
7979
)
8080

81+
registry.register(
82+
FieldDataType.INTEGER,
83+
DataTypeInfo(
84+
pydantic_annotation="int",
85+
sqlalchemy_type="Integer",
86+
sqlalchemy_prefix=False,
87+
python_type="int",
88+
faker_generator="random_int",
89+
value="1",
90+
test_value="2",
91+
),
92+
)
93+
94+
registry.register(
95+
FieldDataType.FLOAT,
96+
DataTypeInfo(
97+
pydantic_annotation="float",
98+
sqlalchemy_type="Float",
99+
sqlalchemy_prefix=False,
100+
python_type="float",
101+
faker_generator="pyfloat",
102+
value="1.0",
103+
test_value="2.0",
104+
),
105+
)
106+
107+
registry.register(
108+
FieldDataType.BOOLEAN,
109+
DataTypeInfo(
110+
pydantic_annotation="bool",
111+
sqlalchemy_type="Boolean",
112+
sqlalchemy_prefix=False,
113+
python_type="bool",
114+
faker_generator="boolean",
115+
value="True",
116+
test_value="False",
117+
),
118+
)
119+
81120
registry.register(
82121
FieldDataType.DATETIME,
83122
DataTypeInfo(
84-
pydantic_annotation="",
123+
pydantic_annotation="datetime",
85124
sqlalchemy_type="DateTime",
86125
sqlalchemy_prefix=False,
87126
python_type="datetime",
88-
faker_generator="text",
127+
faker_generator="date_time",
89128
value="datetime.now(timezone.utc)",
90129
test_value="datetime.now(timezone.utc)",
91130
test_func=".isoformat()",
92131
),
93132
)
133+
134+
registry.register(
135+
FieldDataType.UUID,
136+
DataTypeInfo(
137+
pydantic_annotation="UUID",
138+
sqlalchemy_type="UUID",
139+
sqlalchemy_prefix=False,
140+
python_type="UUID",
141+
faker_generator="uuid4",
142+
value=str(uuid4()),
143+
test_value=str(uuid4()),
144+
),
145+
)
146+
147+
registry.register(
148+
FieldDataType.JSONB,
149+
DataTypeInfo(
150+
pydantic_annotation="dict[str, Any]",
151+
sqlalchemy_type="JSONB",
152+
sqlalchemy_prefix=True,
153+
python_type="dict",
154+
faker_generator="TODO",
155+
value="{}",
156+
test_value='{"key": "value"}',
157+
),
158+
)

fastapi_forge/jinja.py

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from fastapi_forge.dtos import (
66
Model,
77
ModelField,
8-
ModelFieldMetadata,
98
ModelMetadata,
109
ModelRelationship,
1110
)
@@ -68,7 +67,7 @@ class {{ model.name_cc }}InputDTO(BaseModel):
6867
\"\"\"{{ model.name_cc }} input DTO.\"\"\"
6968
7069
{% for field in model.fields_sorted if not (field.metadata.is_created_at_timestamp or field.metadata.is_updated_at_timestamp or field.primary_key) -%}
71-
{{ field.name }}: {{ type_mapping[field.type] }}{% if field.nullable %} | None{% endif %}
70+
{{ field.name }}: {{ field.type_info.python_type }}{% if field.nullable %} | None{% endif %}
7271
{% endfor %}
7372
7473
@@ -267,11 +266,7 @@ async def test_get_{{ model.name }}_by_id(client: AsyncClient,) -> None:
267266
{%- if not field.primary_key and field.name.endswith('_id') %}
268267
assert response_data["{{ field.name }}"] == str({{ model.name }}.{{ field.name }})
269268
{%- elif not field.primary_key %}
270-
{%- if field.type == "DateTime" %}
271-
assert response_data["{{ field.name }}"] == {{ model.name }}.{{ field.name }}.isoformat()
272-
{%- else %}
273-
assert response_data["{{ field.name }}"] == {{ model.name }}.{{ field.name }}
274-
{%- endif %}
269+
assert response_data["{{ field.name }}"] == {{ model.name }}.{{ field.name }}{{ field.type_info.test_func }}
275270
{%- endif %}
276271
{%- endfor %}
277272
"""
@@ -301,11 +296,7 @@ async def test_patch_{{ model.name }}(client: AsyncClient, daos: AllDAOs,) -> No
301296
{%- if not field.primary_key and field.name.endswith('_id') -%}
302297
"{{ field.name }}": str({{ field.name | replace('_id', '.id') }}),
303298
{% elif not field.primary_key %}
304-
{%- if field.type == "DateTime" %}
305-
"{{ field.name }}": {{ type_to_input_value_mapping[field.type] }}.isoformat(),
306-
{%- else %}
307-
"{{ field.name }}": {{ type_to_input_value_mapping[field.type] }},
308-
{%- endif %}
299+
"{{ field.name }}": {{ field.type_info.test_value }}{{ field.type_info.test_func }},
309300
{%- endif %}
310301
{%- endfor %}
311302
}
@@ -320,11 +311,7 @@ async def test_patch_{{ model.name }}(client: AsyncClient, daos: AllDAOs,) -> No
320311
{%- if not field.primary_key and field.name.endswith('_id') %}
321312
assert db_{{ model.name }}.{{ field.name }} == UUID(input_json["{{ field.name }}"])
322313
{%- elif not field.primary_key %}
323-
{%- if field.type == "DateTime" %}
324-
assert db_{{ model.name }}.{{ field.name }}.isoformat() == input_json["{{ field.name }}"]
325-
{%- else %}
326-
assert db_{{ model.name }}.{{ field.name }} == input_json["{{ field.name }}"]
327-
{%- endif %}
314+
assert db_{{ model.name }}.{{ field.name }}{{ field.type_info.test_func }} == input_json["{{ field.name }}"]
328315
{%- endif %}
329316
{%- endfor %}
330317
@@ -353,26 +340,6 @@ async def test_delete_{{ model.name }}(client: AsyncClient, daos: AllDAOs,) -> N
353340
assert db_{{ model.name }} is None
354341
"""
355342

356-
TYPE_MAPPING = {
357-
"Integer": "int",
358-
"Float": "float",
359-
"String": "str",
360-
"UUID": "UUID",
361-
"DateTime": "datetime",
362-
"JSONB": "dict[str, Any]",
363-
"Boolean": "bool",
364-
}
365-
366-
TYPE_TO_INPUT_VALUE_MAPPING = {
367-
"Integer": "1",
368-
"Float": "1.0",
369-
"String": "'string'",
370-
"UUID": "UUID('00000000-0000-0000-0000-000000000000')",
371-
"DateTime": "datetime.now(timezone.utc)",
372-
"JSONB": '{"json": "value"}',
373-
"Boolean": "True",
374-
}
375-
376343

377344
def _render(model: Model, template_name: str, **kwargs: Any) -> str:
378345
template = env.from_string(template_name)
@@ -490,15 +457,15 @@ def render_model_to_delete_test(model: Model) -> str:
490457
]
491458

492459
render_funcs = [
493-
# render_model_to_model,
494-
# render_model_to_dto,
495-
# render_model_to_dao,
496-
# render_model_to_routers,
460+
render_model_to_model,
461+
render_model_to_dto,
462+
render_model_to_dao,
463+
render_model_to_routers,
497464
render_model_to_post_test,
498-
# render_model_to_get_test,
499-
# render_model_to_get_id_test,
500-
# render_model_to_patch_test,
501-
# render_model_to_delete_test,
465+
render_model_to_get_test,
466+
render_model_to_get_id_test,
467+
render_model_to_patch_test,
468+
render_model_to_delete_test,
502469
]
503470

504471
for fn in render_funcs:

fastapi_forge/jinja_utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ def _gen_field(
66
field: ModelField,
77
target: str | None = None,
88
) -> str:
9-
109
type_info = field.type_info
1110
args = [
1211
f"{'sa.' if type_info.sqlalchemy_prefix else ''}{type_info.sqlalchemy_type}"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)