44from pathlib import Path
55from typing import Any
66
7- from pacta .model .types import ArchitectureModel , CodeMapping , Container , Context , Layer , Relation
7+ from pacta .model .types import ArchitectureModel , CodeMapping , Container , ContainerKind , Context , Layer , Relation
8+
9+ _SUPPORTED_VERSIONS = {1 , 2 }
810
911
1012@dataclass (frozen = True , slots = True )
@@ -37,6 +39,11 @@ def load(self, path: Path) -> ArchitectureModel:
3739 version = data .get ("version" , 1 )
3840 if not isinstance (version , int ):
3941 raise ModelLoadError (code = "invalid_version" , message = "'version' must be an integer." )
42+ if version not in _SUPPORTED_VERSIONS :
43+ raise ModelLoadError (
44+ code = "unsupported_version" ,
45+ message = f"Unsupported model version: { version } . Supported: { sorted (_SUPPORTED_VERSIONS )} ." ,
46+ )
4047
4148 metadata : dict [str , Any ] = {}
4249 # carry system into metadata (README has system section)
@@ -51,9 +58,13 @@ def load(self, path: Path) -> ArchitectureModel:
5158 metadata [k ] = v
5259
5360 contexts = self ._parse_contexts (data .get ("contexts" ))
54- containers = self ._parse_containers (data .get ("containers" ))
61+ containers = self ._parse_containers (data .get ("containers" ), version = version )
5562
56- raw_relations = data .get ("relations" ) if data .get ("relations" ) is not None else data .get ("communication" ) or ()
63+ raw_relations = (
64+ data .get ("relations" )
65+ if data .get ("relations" ) is not None
66+ else data .get ("interactions" ) or data .get ("communication" ) or ()
67+ )
5768
5869 relations = self ._parse_relations (raw_relations )
5970
@@ -123,7 +134,7 @@ def _parse_contexts(self, raw: Any) -> dict[str, Context]:
123134 )
124135 return out
125136
126- def _parse_containers (self , raw : Any ) -> dict [str , Container ]:
137+ def _parse_containers (self , raw : Any , * , version : int = 1 ) -> dict [str , Container ]:
127138 if raw is None :
128139 return {}
129140
@@ -147,13 +158,39 @@ def _parse_containers(self, raw: Any) -> dict[str, Container]:
147158 else :
148159 tags_tuple = ()
149160
161+ # v2 fields
162+ kind : ContainerKind | None = None
163+ children : dict [str , Container ] = {}
164+ if version >= 2 :
165+ raw_kind = spec .get ("kind" )
166+ if raw_kind is None :
167+ raise ModelLoadError (
168+ code = "missing_container_kind" ,
169+ message = f"Container '{ cid } ' must have a 'kind' field in v2 schema." ,
170+ )
171+ try :
172+ kind = ContainerKind (str (raw_kind ))
173+ except ValueError :
174+ raise ModelLoadError (
175+ code = "invalid_container_kind" ,
176+ message = (
177+ f"Container '{ cid } ' has invalid kind '{ raw_kind } '. "
178+ f"Must be one of: { ', ' .join (k .value for k in ContainerKind )} ."
179+ ),
180+ )
181+ raw_contains = spec .get ("contains" )
182+ if raw_contains is not None :
183+ children = self ._parse_containers (raw_contains , version = version )
184+
150185 out [cid ] = Container (
151186 id = cid ,
152187 name = spec .get ("name" ),
153188 context = spec .get ("context" ),
154189 description = spec .get ("description" ),
155190 code = code ,
156191 tags = tags_tuple ,
192+ kind = kind ,
193+ children = children ,
157194 )
158195
159196 return out
0 commit comments