bedrock.generators.code_generators.model.model_class

 1from typing import Optional
 2
 3from bedrock._helpers.string import camelCase_to_snake_case, as_plural
 4from bedrock.generators.code_generators.model.helpers import resolve_model_name_from_path_hint
 5from bedrock.generators.code_generators.common.imports import import_models
 6
 7
 8def make_model_class(model_name: str, attributes: list[tuple[str, str]], project_name: str, path_hint: str,
 9                     table_name: str, app_path: str) -> tuple[str, dict]:
10    if path_hint:
11        lines = [f"@filter_path_hint(\"{path_hint}\")"]
12    else:
13        lines = []
14    _table_name = table_name if table_name else f"{project_name}_{camelCase_to_snake_case(model_name).lower()}"
15    lines.extend([
16        f"class {model_name}(Base, ModelHelper):  # pragma: unit",
17        f"    __tablename__ = \"{_table_name}\"",
18        ""
19    ])
20    foreign_key, relationship, reverse_back_populate = make_foreign_key_attributes(model_name, path_hint, app_path)
21    if foreign_key:
22        lines.append(f"    {foreign_key}")
23    for attribute in attributes:
24        lines.append(f"    {attribute[0]} = Column({attribute[1]})")
25    if relationship:
26        lines.append("")
27        lines.append(f"    {relationship}")
28
29    return "\n".join(lines), reverse_back_populate
30
31
32def make_foreign_key_attributes(model_name: str, path_hint: str, app_path: str) -> \
33        tuple[Optional[str], Optional[str], dict]:
34    if not path_hint:
35        return None, None, {}
36    hinted_model_name = resolve_model_name_from_path_hint(path_hint)
37    hinted_model = import_models(app_path).get(hinted_model_name)
38    if not hinted_model:
39        return None, None, {}
40    hinted_model_table_name = hinted_model.__tablename__
41    relationship_attribute = camelCase_to_snake_case(hinted_model_name)
42    foreign_key_attribute = f"{relationship_attribute}_uuid"
43    back_populated_attribute = as_plural(camelCase_to_snake_case(model_name))
44
45    relationship = f'{relationship_attribute} = relationship("{hinted_model_name}", lazy="joined", back_populates="{back_populated_attribute}")'
46    relationship_comment = f"TODO: In {hinted_model_name}, please check that {back_populated_attribute} is correctly linking back to {relationship_attribute}"
47    reverse_back_populate = f"{back_populated_attribute} = relationship(\"{model_name}\", lazy=\"joined\")"
48    return (
49        f'{foreign_key_attribute} = Column(UUID(as_uuid=True), ForeignKey("{hinted_model_table_name}.uuid", ondelete="cascade"), nullable=False)',
50        f'{relationship}  # {relationship_comment}',
51        {"line": reverse_back_populate, "model": hinted_model_name} if hinted_model_name else {}
52    )
def make_model_class( model_name: str, attributes: list[tuple[str, str]], project_name: str, path_hint: str, table_name: str, app_path: str) -> tuple[str, dict]:
 9def make_model_class(model_name: str, attributes: list[tuple[str, str]], project_name: str, path_hint: str,
10                     table_name: str, app_path: str) -> tuple[str, dict]:
11    if path_hint:
12        lines = [f"@filter_path_hint(\"{path_hint}\")"]
13    else:
14        lines = []
15    _table_name = table_name if table_name else f"{project_name}_{camelCase_to_snake_case(model_name).lower()}"
16    lines.extend([
17        f"class {model_name}(Base, ModelHelper):  # pragma: unit",
18        f"    __tablename__ = \"{_table_name}\"",
19        ""
20    ])
21    foreign_key, relationship, reverse_back_populate = make_foreign_key_attributes(model_name, path_hint, app_path)
22    if foreign_key:
23        lines.append(f"    {foreign_key}")
24    for attribute in attributes:
25        lines.append(f"    {attribute[0]} = Column({attribute[1]})")
26    if relationship:
27        lines.append("")
28        lines.append(f"    {relationship}")
29
30    return "\n".join(lines), reverse_back_populate
def make_foreign_key_attributes( model_name: str, path_hint: str, app_path: str) -> tuple[typing.Optional[str], typing.Optional[str], dict]:
33def make_foreign_key_attributes(model_name: str, path_hint: str, app_path: str) -> \
34        tuple[Optional[str], Optional[str], dict]:
35    if not path_hint:
36        return None, None, {}
37    hinted_model_name = resolve_model_name_from_path_hint(path_hint)
38    hinted_model = import_models(app_path).get(hinted_model_name)
39    if not hinted_model:
40        return None, None, {}
41    hinted_model_table_name = hinted_model.__tablename__
42    relationship_attribute = camelCase_to_snake_case(hinted_model_name)
43    foreign_key_attribute = f"{relationship_attribute}_uuid"
44    back_populated_attribute = as_plural(camelCase_to_snake_case(model_name))
45
46    relationship = f'{relationship_attribute} = relationship("{hinted_model_name}", lazy="joined", back_populates="{back_populated_attribute}")'
47    relationship_comment = f"TODO: In {hinted_model_name}, please check that {back_populated_attribute} is correctly linking back to {relationship_attribute}"
48    reverse_back_populate = f"{back_populated_attribute} = relationship(\"{model_name}\", lazy=\"joined\")"
49    return (
50        f'{foreign_key_attribute} = Column(UUID(as_uuid=True), ForeignKey("{hinted_model_table_name}.uuid", ondelete="cascade"), nullable=False)',
51        f'{relationship}  # {relationship_comment}',
52        {"line": reverse_back_populate, "model": hinted_model_name} if hinted_model_name else {}
53    )