Skip to content

Commit

Permalink
codegen to create pydantic classes from dict
Browse files Browse the repository at this point in the history
  • Loading branch information
fvankrieken committed Nov 27, 2024
1 parent d460e16 commit 5578068
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
30 changes: 30 additions & 0 deletions dcpy/utils/codegen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Any
from pydantic import BaseModel, Field

Check warning on line 2 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L1-L2

Added lines #L1 - L2 were not covered by tests

from dcpy.utils.string import to_snake, to_camel

Check warning on line 4 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L4

Added line #L4 was not covered by tests


def pydantic_class_from_dict(class_name: str, obj: dict[str, Any]) -> str:
str = f"class {class_name}(BaseModel):"
subclasses = []

Check warning on line 9 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L7-L9

Added lines #L7 - L9 were not covered by tests

for field in obj:
str += "\n "
val = obj[field]

Check warning on line 13 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L12-L13

Added lines #L12 - L13 were not covered by tests
if isinstance(val, dict):
type_name = to_camel(field)
subclasses.append(pydantic_class_from_dict(type_name, val))

Check warning on line 16 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L15-L16

Added lines #L15 - L16 were not covered by tests
elif isinstance(val, list) and (len(val) > 0):
class_name = to_camel(field)
type_name = f"list[{class_name}]"
subclasses.append(pydantic_class_from_dict(class_name, val[0]))

Check warning on line 20 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L18-L20

Added lines #L18 - L20 were not covered by tests
else:
type_name = type(val).__name__
field_name = to_snake(field)

Check warning on line 23 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L22-L23

Added lines #L22 - L23 were not covered by tests
if field != field_name:
str += f'{field_name}: {type_name} = Field(alias="{field}")'

Check warning on line 25 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L25

Added line #L25 was not covered by tests
else:
str += f"{field_name}: {type_name}"

Check warning on line 27 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L27

Added line #L27 was not covered by tests

subclasses.append(str)
return "\n\n".join(subclasses)

Check warning on line 30 in dcpy/utils/codegen.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/codegen.py#L29-L30

Added lines #L29 - L30 were not covered by tests
11 changes: 10 additions & 1 deletion dcpy/utils/string.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import re


def camel_to_snake(s: str) -> str:
def to_camel(s: str) -> str:
s = re.sub("[^0-9a-zA-Z]+", "_", s)
s = re.sub("_+", "_", s)
return "".join(x.capitalize() for x in s.lower().split("_"))

Check warning on line 7 in dcpy/utils/string.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/string.py#L4-L7

Added lines #L4 - L7 were not covered by tests


def to_snake(s: str) -> str:
s = re.sub("[^0-9a-zA-Z]+", "_", s)

Check warning on line 11 in dcpy/utils/string.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/string.py#L10-L11

Added lines #L10 - L11 were not covered by tests
s = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", s)
s = re.sub("_+", "_", s)
s = s.strip("_")

Check warning on line 14 in dcpy/utils/string.py

View check run for this annotation

Codecov / codecov/patch

dcpy/utils/string.py#L13-L14

Added lines #L13 - L14 were not covered by tests
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s).lower()

0 comments on commit 5578068

Please sign in to comment.