Created
March 4, 2020 05:15
-
-
Save yampelo/d3df4324759d7d7b84a30c58fdb6eae8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import inspect | |
import sys | |
from datetime import datetime | |
from enum import EnumMeta | |
from typing import Any, Dict, List, Tuple, Union, _GenericAlias, get_type_hints | |
from pydantic import BaseModel | |
# Import your pydnatic models here | |
models = inspect.getmembers( | |
sys.modules[__name__], | |
lambda i: inspect.isclass(i) and issubclass(i, BaseModel) and i != BaseModel, | |
) | |
TYPE_MAP: Dict[str, str] = { | |
bool: "boolean", | |
str: "string", | |
int: "number", | |
float: "number", | |
datetime: "Date", | |
Any: "any", | |
List: "Array<any>", | |
Tuple: "[any]", | |
Union: "any", | |
} | |
SUBSCRIPT_FORMAT_MAP: Dict[str, str] = { | |
"List": "Array<{}>", | |
"Optional": "{} | null", | |
"Tuple": "[{}]", | |
"Union": "{}", | |
} | |
InterfaceAttributes = Dict[str, str] | |
ParsedInterfaces = Dict[str, InterfaceAttributes] | |
interfaces: ParsedInterfaces = {} | |
enums: Dict[str, Dict[str, str]] = {} | |
def parse_type_hint(type_hint): | |
if not isinstance(type_hint, _GenericAlias): | |
if type_hint not in TYPE_MAP: | |
parse_class(type_hint) | |
return TYPE_MAP.get(type_hint, str(type_hint.__name__)) | |
if type_hint.__origin__ == Union: | |
return parse_union(type_hint) | |
if type_hint.__origin__ == list: | |
return f"Array<{parse_type_hint(type_hint.__args__[0])}>" | |
def parse_union(union: Union): | |
arg1, arg2 = union.__args__ | |
if arg2 == type(None): | |
return f"{parse_type_hint(arg1)} | null" | |
else: | |
return f"{parse_type_hint(arg1)} | {parse_type_hint(arg2)}" | |
def parse_class(model: BaseModel): | |
attrs: InterfaceAttributes = {} | |
for annotation, value in get_type_hints(model).items(): | |
if value in TYPE_MAP: | |
attrs[annotation] = TYPE_MAP[value] | |
elif value.__class__ == EnumMeta and value.__name__ not in enums: | |
enums[value.__name__] = {k.name: k.value for k in value} | |
attrs[annotation] = f"{value.__name__}" | |
elif isinstance(value, _GenericAlias): | |
attrs[annotation] = parse_type_hint(value) | |
else: | |
attrs[annotation] = str(value.__name__) | |
interfaces[model.__name__] = attrs | |
for m in models: | |
parse_class(m[1]) | |
for enum in enums: | |
s = f"export enum {enum} {{\n" | |
for attribute_name, attribute_type in enums[enum].items(): | |
s += f' {attribute_name} = "{attribute_type}",\n' | |
s += "}" | |
print(s) | |
for interface in interfaces: | |
s = f"export interface {interface.replace('Base', '')} {{\n" | |
for attribute_name, attribute_type in interfaces[interface].items(): | |
s += f" {attribute_name}: {attribute_type.replace('Base', '')};\n" | |
s += "}" | |
print(s) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This will covert pydnatic models into typescript interfaces and enums. For example:
becomes