11from abc import ABC
22from collections .abc import MutableMapping
33
4+ from attrs import Attribute
5+ from modflow_devtools .dfn import Dfn , Var
46from xattree import xattree
57
8+ from flopy4 .mf6 .spec import fields_dict
9+
610COMPONENTS = {}
711"""MF6 component registry."""
812
@@ -13,6 +17,9 @@ class Component(ABC, MutableMapping):
1317 def __attrs_init_subclass__ (cls ):
1418 COMPONENTS [cls .__name__ .lower ()] = cls
1519
20+ def __attrs_post_init__ (self ):
21+ self ._dfn = self ._get_dfn ()
22+
1623 def __getitem__ (self , key ):
1724 return self .children [key ] # type: ignore
1825
@@ -28,7 +35,46 @@ def __iter__(self):
2835 def __len__ (self ):
2936 return len (self .children ) # type: ignore
3037
38+ @property
39+ def dfn (self ) -> Dfn :
40+ """Return the component's definition."""
41+ return self ._dfn
42+
43+ def _get_dfn (self ) -> Dfn :
44+ def _to_dfn_spec (attribute : Attribute ) -> Var :
45+ return Var (
46+ name = attribute .name ,
47+ type = attribute .type ,
48+ shape = attribute .metadata .get ("dims" , None ),
49+ block = attribute .metadata .get ("block" , None ),
50+ default = attribute .default ,
51+ children = {k : _to_dfn_spec (v ) for k , v in fields_dict (attribute .type )} # type: ignore
52+ if attribute .metadata .get ("kind" , None ) == "child" # type: ignore
53+ else None , # type: ignore
54+ )
55+
56+ fields = {k : _to_dfn_spec (v ) for k , v in fields_dict (self .__class__ ).items ()}
57+ blocks : dict [str , dict [str , Var ]] = {}
58+ for k , v in fields .items ():
59+ if (block := v .get ("block" , None )) is not None :
60+ blocks .setdefault (block , {})[k ] = v
61+ else :
62+ blocks [k ] = v
63+ return Dfn (
64+ name = self .name , # type: ignore
65+ advanced = getattr (self , "advanced_package" , False ),
66+ multi = getattr (self , "multi_package" , False ),
67+ ref = getattr (self , "sub_package" , None ),
68+ sln = getattr (self , "solution_package" , None ),
69+ ** blocks ,
70+ )
71+
72+ def load (self ) -> None :
73+ # TODO: load
74+ for child in self .children .values (): # type: ignore
75+ child .load ()
76+
3177 def write (self ) -> None :
32- # TODO: write with jinja to file
78+ # TODO: write
3379 for child in self .children .values (): # type: ignore
3480 child .write ()
0 commit comments