Files
mediaproc/modelgen/types.py

173 lines
5.4 KiB
Python

"""
Type Dispatch Tables
Type mappings for each output format.
Used by generators to convert Python types to target framework types.
"""
from typing import Any, Callable, get_args
# =============================================================================
# Django Type Mappings
# =============================================================================
DJANGO_TYPES: dict[Any, str] = {
str: "models.CharField(max_length={max_length}{opts})",
int: "models.IntegerField({opts})",
float: "models.FloatField({opts})",
bool: "models.BooleanField(default={default})",
"UUID": "models.UUIDField({opts})",
"datetime": "models.DateTimeField({opts})",
"dict": "models.JSONField(default=dict, blank=True)",
"list": "models.JSONField(default=list, blank=True)",
"text": "models.TextField(blank=True, default='')",
"bigint": "models.BigIntegerField({opts})",
"enum": "models.CharField(max_length=20, choices={enum_name}.choices{opts})",
}
DJANGO_SPECIAL: dict[str, str] = {
"id": "models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)",
"created_at": "models.DateTimeField(auto_now_add=True)",
"updated_at": "models.DateTimeField(auto_now=True)",
}
# =============================================================================
# Pydantic Type Resolvers
# =============================================================================
def _get_list_inner(type_hint: Any) -> str:
"""Get inner type of List[T] for Pydantic."""
args = get_args(type_hint)
if args and args[0] in (str, int, float, bool):
return {str: "str", int: "int", float: "float", bool: "bool"}[args[0]]
return "str"
PYDANTIC_RESOLVERS: dict[Any, Callable[[Any], str]] = {
str: lambda _: "str",
int: lambda _: "int",
float: lambda _: "float",
bool: lambda _: "bool",
"UUID": lambda _: "UUID",
"datetime": lambda _: "datetime",
"dict": lambda _: "Dict[str, Any]",
"list": lambda base: f"List[{_get_list_inner(base)}]",
"enum": lambda base: base.__name__,
}
# =============================================================================
# TypeScript Type Resolvers
# =============================================================================
def _resolve_ts_list(base: Any) -> str:
"""Resolve TypeScript list type."""
args = get_args(base)
if args:
inner = args[0]
if inner is str:
return "string[]"
elif inner is int or inner is float:
return "number[]"
elif inner is bool:
return "boolean[]"
return "string[]"
TS_RESOLVERS: dict[Any, Callable[[Any], str]] = {
str: lambda _: "string",
int: lambda _: "number",
float: lambda _: "number",
bool: lambda _: "boolean",
"UUID": lambda _: "string",
"datetime": lambda _: "string",
"dict": lambda _: "Record<string, unknown>",
"list": _resolve_ts_list,
"enum": lambda base: base.__name__,
}
# =============================================================================
# Protobuf Type Resolvers
# =============================================================================
def _resolve_proto_list(base: Any) -> str:
"""Resolve Protobuf repeated type."""
args = get_args(base)
if args:
inner = args[0]
if inner is str:
return "repeated string"
elif inner is int:
return "repeated int32"
elif inner is float:
return "repeated float"
elif inner is bool:
return "repeated bool"
return "repeated string"
PROTO_RESOLVERS: dict[Any, Callable[[Any], str]] = {
str: lambda _: "string",
int: lambda _: "int32",
float: lambda _: "float",
bool: lambda _: "bool",
"list": _resolve_proto_list,
}
# =============================================================================
# Prisma Type Mappings
# =============================================================================
PRISMA_TYPES: dict[Any, str] = {
str: "String",
int: "Int",
float: "Float",
bool: "Boolean",
"UUID": "String @default(uuid())",
"datetime": "DateTime",
"dict": "Json",
"list": "Json",
"bigint": "BigInt",
}
PRISMA_SPECIAL: dict[str, str] = {
"id": "String @id @default(uuid())",
"created_at": "DateTime @default(now())",
"updated_at": "DateTime @updatedAt",
}
# =============================================================================
# Graphene Type Resolvers
# =============================================================================
def _resolve_graphene_list(base: Any) -> str:
"""Resolve graphene List type."""
args = get_args(base)
if args:
inner = args[0]
if inner is str:
return "graphene.List(graphene.String)"
elif inner is int:
return "graphene.List(graphene.Int)"
elif inner is float:
return "graphene.List(graphene.Float)"
elif inner is bool:
return "graphene.List(graphene.Boolean)"
return "graphene.List(graphene.String)"
GRAPHENE_RESOLVERS: dict[Any, Callable[[Any], str]] = {
str: lambda _: "graphene.String",
int: lambda _: "graphene.Int",
float: lambda _: "graphene.Float",
bool: lambda _: "graphene.Boolean",
"UUID": lambda _: "graphene.UUID",
"datetime": lambda _: "graphene.DateTime",
"dict": lambda _: "graphene.JSONString",
"list": _resolve_graphene_list,
"enum": lambda base: f"graphene.String", # Enums exposed as strings in GQL
}