@@ -547,6 +547,7 @@ def process_validate(self) -> None:
547547 self .validate_parent_component ()
548548 self .validate_human_friendly_id ()
549549 self .validate_required_relationships ()
550+ self .validate_inherited_relationships_fields ()
550551
551552 def process_post_validation (self ) -> None :
552553 self .cleanup_inherited_elements ()
@@ -1327,6 +1328,81 @@ def validate_count_against_cardinality(self) -> None:
13271328 f"{ node .kind } : Relationship { rel .name !r} max_count must be 0 or greater than 1 when cardinality is MANY"
13281329 )
13291330
1331+ def validate_inherited_relationships_fields (self ) -> None :
1332+ for name in self .node_names :
1333+ node_schema = self .get (name = name , duplicate = False )
1334+ if not node_schema .inherit_from :
1335+ continue
1336+
1337+ self .validate_node_inherited_relationship_fields (node_schema )
1338+
1339+ def validate_node_inherited_relationship_fields (self , node_schema : NodeSchema ) -> None :
1340+ generics = [self .get (name = node_name , duplicate = False ) for node_name in node_schema .inherit_from ]
1341+ relationship_names = [node .relationship_names for node in generics ]
1342+ related_relationship_names = set ().union (
1343+ * [
1344+ set (relationship_name_a ) & set (relationship_name_b )
1345+ for index , relationship_name_a in enumerate (relationship_names )
1346+ for relationship_name_b in relationship_names [index + 1 :]
1347+ ]
1348+ )
1349+ # Check that the relationship properties match
1350+ # for every generic node in generics list having related relationship names
1351+ for index , generic_a in enumerate (generics ):
1352+ for generic_b in generics [index + 1 :]:
1353+ for relationship_name in related_relationship_names :
1354+ try :
1355+ relationship_a = generic_a .get_relationship (name = relationship_name )
1356+ relationship_b = generic_b .get_relationship (name = relationship_name )
1357+ except ValueError :
1358+ continue
1359+
1360+ matched , _property = self ._check_relationship_properties_match (
1361+ relationship_a = relationship_a , relationship_b = relationship_b
1362+ )
1363+ if not matched :
1364+ raise ValueError (
1365+ f"{ node_schema .kind } inherits from '{ generic_a .kind } ' & '{ generic_b .kind } '"
1366+ f" with different '{ _property } ' on the '{ relationship_name } ' relationship"
1367+ )
1368+
1369+ def _check_relationship_properties_match (
1370+ self , relationship_a : RelationshipSchema , relationship_b : RelationshipSchema
1371+ ) -> tuple [bool , str | None ]:
1372+ compulsorily_matching_properties = (
1373+ "name" ,
1374+ "peer" ,
1375+ "kind" ,
1376+ "identifier" ,
1377+ "cardinality" ,
1378+ "min_count" ,
1379+ "max_count" ,
1380+ "common_parent" ,
1381+ "common_relatives" ,
1382+ "optional" ,
1383+ "branch" ,
1384+ "direction" ,
1385+ "on_delete" ,
1386+ "read_only" ,
1387+ "hierarchical" ,
1388+ "allow_override" ,
1389+ )
1390+ for _property in compulsorily_matching_properties :
1391+ if not hasattr (relationship_a , _property ) or not hasattr (relationship_b , _property ):
1392+ continue
1393+
1394+ equal_delete_actions = (None , RelationshipDeleteBehavior .NO_ACTION )
1395+ if (
1396+ _property == "on_delete"
1397+ and getattr (relationship_a , _property ) in equal_delete_actions
1398+ and getattr (relationship_b , _property ) in equal_delete_actions
1399+ ):
1400+ continue
1401+
1402+ if getattr (relationship_a , _property ) != getattr (relationship_b , _property ):
1403+ return False , _property
1404+ return True , None
1405+
13301406 def process_dropdowns (self ) -> None :
13311407 for name in self .all_names :
13321408 node = self .get (name = name , duplicate = False )
0 commit comments