1818import networkx as nx
1919from jinja2 import Environment , PackageLoader
2020
21- from pyatlan .model .typedef import EntityDef , EnumDef , TypeDefResponse
22- from pyatlan .model .utils import to_snake_case
21+ from pyatlan .model .typedef import EntityDef , EnumDef , RelationshipDef , TypeDefResponse
22+ from pyatlan .model .utils import to_python_class_name , to_snake_case
2323
2424REFERENCEABLE = "Referenceable"
2525TYPE_DEF_FILE = Path (os .getenv ("TMPDIR" , "/tmp" )) / "typedefs.json"
8080# across Python versions (e.g: 3.8 and 3.9).
8181PARENT = Path (__file__ ).resolve ().parent
8282ASSETS_DIR = PARENT .parent / "model" / "assets"
83+ ASSETS_RELATIONS_DIR = PARENT .parent / "model" / "assets" / "relations"
8384CORE_ASSETS_DIR = PARENT .parent / "model" / "assets" / "core"
8485MODEL_DIR = PARENT .parent / "model"
8586DOCS_DIR = PARENT .parent / "documentation"
@@ -450,6 +451,29 @@ def create_modules(cls):
450451 cls ._CORE_ASSETS .add (related_asset .super_class )
451452
452453
454+ class RelationshipDefInfo :
455+ module_name : str
456+ relationship_def_infos : List ["RelationshipDefInfo" ] = []
457+
458+ def __init__ (self , name : str , relationship_def : RelationshipDef ):
459+ self .module_name = to_snake_case (name )
460+ self .relationship_def = relationship_def
461+
462+ @classmethod
463+ def create (cls , relationship_defs : List [RelationshipDef ]):
464+ for rel_def in relationship_defs :
465+ # Only pick `atlas_core` enums, not user-created ones.
466+ if rel_def .attribute_defs :
467+ cls .relationship_def_infos .append (
468+ RelationshipDefInfo (
469+ name = to_snake_case (rel_def .name ), relationship_def = rel_def
470+ )
471+ )
472+ # if rel_def.name == "UserDefRelationship":
473+ # import ipdb; ipdb.set_trace()
474+ # print(to_python_class_name(rel_def.name))
475+
476+
453477class AttributeType (Enum ):
454478 PRIMITIVE = "PRIMITIVE"
455479 ENUM = "ENUM"
@@ -664,6 +688,7 @@ def __init__(self) -> None:
664688 )
665689 self .environment .filters ["to_snake_case" ] = to_snake_case
666690 self .environment .filters ["get_type" ] = get_type
691+ self .environment .filters ["to_cls_name" ] = to_python_class_name
667692 self .environment .filters ["get_search_type" ] = get_search_type
668693 self .environment .filters ["get_mapped_type" ] = get_mapped_type
669694 self .environment .filters ["get_class_var_for_attr" ] = get_class_var_for_attr
@@ -719,6 +744,21 @@ def render_module(self, asset_info: AssetInfo, enum_defs: List["EnumDefInfo"]):
719744 with (ASSETS_DIR / f"{ asset_info .module_name } .py" ).open ("w" ) as script :
720745 script .write (content )
721746
747+ def render_custom_relationship_module (
748+ self , relationship_def_info : RelationshipDefInfo
749+ ):
750+ template = self .environment .get_template ("custom_relationship.jinja2" )
751+ content = template .render (
752+ {
753+ "relationship_info" : relationship_info .relationship_def ,
754+ "templates_path" : TEMPLATES_DIR .absolute ().as_posix (),
755+ }
756+ )
757+ with (ASSETS_RELATIONS_DIR / f"{ relationship_def_info .module_name } .py" ).open (
758+ "w"
759+ ) as script :
760+ script .write (content )
761+
722762 def render_core_module (self , asset_info : AssetInfo , enum_defs : List ["EnumDefInfo" ]):
723763 template = self .environment .get_template ("module.jinja2" )
724764 content = template .render (
@@ -769,6 +809,22 @@ def render_mypy_init(self, assets: List[AssetInfo]):
769809 with init_path .open ("w" ) as script :
770810 script .write (content )
771811
812+ def render_relations_init (self , relation_def_infos : List [RelationshipDefInfo ]):
813+ template = self .environment .get_template ("relations_init.jinja2" )
814+ content = template .render ({"relation_def_infos" : relation_def_infos })
815+
816+ init_path = ASSETS_RELATIONS_DIR / "__init__.py"
817+ with init_path .open ("w" ) as script :
818+ script .write (content )
819+
820+ def render_relations_mypy_init (self , relation_def_infos : List [RelationshipDefInfo ]):
821+ template = self .environment .get_template ("relations_mypy_init.jinja2" )
822+ content = template .render ({"relation_def_infos" : relation_def_infos })
823+
824+ init_path = ASSETS_RELATIONS_DIR / "__init__.pyi"
825+ with init_path .open ("w" ) as script :
826+ script .write (content )
827+
772828 def render_structs (self , struct_defs ):
773829 template = self .environment .get_template ("structs.jinja2" )
774830 content = template .render ({"struct_defs" : struct_defs })
@@ -933,8 +989,10 @@ def filter_attributes_of_custom_entity_type():
933989 filter_attributes_of_custom_entity_type ()
934990 AssetInfo .sub_type_names_to_ignore = type_defs .custom_entity_def_names
935991 AssetInfo .set_entity_defs (type_defs .reserved_entity_defs )
992+ RelationshipDefInfo .create (type_defs .relationship_defs )
936993 AssetInfo .update_all_circular_dependencies ()
937994 AssetInfo .create_modules ()
995+
938996 for file in (ASSETS_DIR ).glob ("*.py" ):
939997 file .unlink ()
940998 for file in (CORE_ASSETS_DIR ).glob ("*.py" ):
@@ -944,14 +1002,28 @@ def filter_attributes_of_custom_entity_type():
9441002 file .unlink ()
9451003 generator = Generator ()
9461004 EnumDefInfo .create (type_defs .enum_defs )
1005+
9471006 for asset_info in ModuleInfo .assets .values ():
9481007 if asset_info .is_core_asset or asset_info .name in asset_info ._CORE_ASSETS :
9491008 generator .render_core_module (asset_info , EnumDefInfo .enum_def_info )
9501009 else :
9511010 generator .render_module (asset_info , EnumDefInfo .enum_def_info )
1011+
1012+ for file in (ASSETS_RELATIONS_DIR ).glob ("*.py" ):
1013+ # Remove all files in the core assets
1014+ # directory except `relationship_attributes.py`
1015+ if file .name == "relationship_attributes.py" :
1016+ continue
1017+ file .unlink ()
1018+
1019+ for relationship_info in RelationshipDefInfo .relationship_def_infos :
1020+ generator .render_custom_relationship_module (relationship_info )
1021+
9521022 generator .render_init (ModuleInfo .assets .values ()) # type: ignore
9531023 generator .render_core_init (ModuleInfo .assets .values ()) # type: ignore
9541024 generator .render_mypy_init (ModuleInfo .assets .values ()) # type: ignore
1025+ generator .render_relations_init (RelationshipDefInfo .relationship_def_infos ) # type: ignore
1026+ generator .render_relations_mypy_init (RelationshipDefInfo .relationship_def_infos ) # type: ignore
9551027 generator .render_structs (type_defs .struct_defs )
9561028 generator .render_enums (EnumDefInfo .enum_def_info )
9571029 generator .render_docs_struct_snippets (type_defs .struct_defs )
0 commit comments