From 83f3de6f9e4fd8d753ba8f1595aa78672d4891af Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 12:30:48 +0100 Subject: [PATCH 1/8] Basic tests to set expectations --- .../test_node_uniqueness.py | 87 ++++++++++++++++++ .../schema_manager/test_manager_schema.py | 91 +++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py b/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py index b4204a07e8..57ece1e862 100644 --- a/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py +++ b/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py @@ -1,8 +1,11 @@ import pytest +from infrahub.core import registry from infrahub.core.branch import Branch from infrahub.core.node import Node from infrahub.core.node.constraints.attribute_uniqueness import NodeAttributeUniquenessConstraint +from infrahub.core.node.constraints.grouped_uniqueness import NodeGroupedUniquenessConstraint +from infrahub.core.schema import SchemaRoot from infrahub.database import InfrahubDatabase from infrahub.exceptions import ValidationError @@ -29,3 +32,87 @@ async def test_node_validate_constraint_node_uniqueness_success( await alfred.new(db=db, name="Alfred", height=160) await constraint.check(alfred) + + +async def test_hierarchical_uniqueness_constraint(db, default_branch): + schema = { + "generics": [ + { + "attributes": [{"kind": "Text", "name": "name"}], + "description": "Generic hierarchical location", + "hierarchical": True, + "human_friendly_id": ["name__value"], + "label": "Location", + "name": "Generic", + "namespace": "Location", + } + ], + "nodes": [ + { + "children": "LocationCountry", + "description": "A continent on planet earth", + "display_labels": ["name__value"], + "generate_profile": False, + "human_friendly_id": ["name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Continent", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "", + "uniqueness_constraints": [["name__value"]], + }, + { + "children": "LocationSite", + "description": "A country within a continent", + "display_labels": ["name__value"], + "generate_profile": False, + "human_friendly_id": ["parent__name__value", "name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Country", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "LocationContinent", + "uniqueness_constraints": [["parent", "name__value"]], + }, + { + "attributes": [{"kind": "Text", "name": "city", "optional": True}], + "children": "", + "description": "A site within a country", + "display_labels": ["name__value"], + "human_friendly_id": ["parent__name__value", "name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Site", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "LocationCountry", + "uniqueness_constraints": [["parent", "name__value"]], + }, + ], + } + + registry.schema.register_schema(schema=SchemaRoot(**schema), branch=default_branch.name) + constraint = NodeGroupedUniquenessConstraint(db=db, branch=default_branch) + + eu = await Node.init(db=db, schema="LocationContinent", branch=default_branch) + await eu.new(db=db, name="Europe") + await eu.save(db=db) + fr = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + await fr.new(db=db, name="France", parent=eu) + await fr.save(db=db) + uk = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + await uk.new(db=db, name="United Kingdom", parent=eu) + await fr.save(db=db) + + th2 = await Node.init(db=db, schema="LocationSite", branch=default_branch) + await th2.new(db=db, name="Telehouse 2", city="Paris", parent=fr) + await th2.save(db=db) + + ld6 = await Node.init(db=db, schema="LocationSite", branch=default_branch) + await ld6.new(db=db, name="Equinix LD6", city="London", parent=uk) + await ld6.save(db=db) + await constraint.check(ld6) + + ld6 = await Node.init(db=db, schema="LocationSite", branch=default_branch) + await ld6.new(db=db, name="Equinix LD6", city="London", parent=uk) + with pytest.raises(ValidationError, match=r"Violates uniqueness constraint 'parent-name' at parent"): + await constraint.check(ld6) diff --git a/backend/tests/unit/core/schema_manager/test_manager_schema.py b/backend/tests/unit/core/schema_manager/test_manager_schema.py index c720e959eb..70c929ee85 100644 --- a/backend/tests/unit/core/schema_manager/test_manager_schema.py +++ b/backend/tests/unit/core/schema_manager/test_manager_schema.py @@ -17,6 +17,7 @@ RelationshipKind, SchemaPathType, ) +from infrahub.core.node import Node from infrahub.core.schema import ( AttributeSchema, GenericSchema, @@ -2793,3 +2794,93 @@ async def test_process_deprecations(organization_schema): assert test_criticality.get_attribute(name="description").optional assert test_criticality.get_relationship(name="first").optional assert not test_criticality.get_relationship(name="second").optional + + +async def test_hierarchical_validate_parent_children(db, default_branch): + schema = { + "generics": [ + { + "attributes": [{"kind": "Text", "name": "name"}], + "description": "Generic hierarchical location", + "hierarchical": True, + "human_friendly_id": ["name__value"], + "label": "Location", + "name": "Generic", + "namespace": "Location", + } + ], + "nodes": [ + { + "children": "LocationCountry", + "description": "A continent on planet earth", + "display_labels": ["name__value"], + "generate_profile": False, + "human_friendly_id": ["name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Continent", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "", + "uniqueness_constraints": [["name__value"]], + }, + { + "children": "LocationSite", + "description": "A country within a continent", + "display_labels": ["name__value"], + "generate_profile": False, + "human_friendly_id": ["parent__name__value", "name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Country", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "LocationContinent", + "uniqueness_constraints": [["parent", "name__value"]], + }, + { + "attributes": [{"kind": "Text", "name": "city", "optional": True}], + "children": "", + "description": "A site within a country", + "display_labels": ["name__value"], + "human_friendly_id": ["parent__name__value", "name__value"], + "inherit_from": ["LocationGeneric"], + "name": "Site", + "namespace": "Location", + "order_by": ["name__value"], + "parent": "LocationCountry", + "uniqueness_constraints": [["parent", "name__value"]], + }, + ], + } + + registry.schema.register_schema(schema=SchemaRoot(**schema), branch=default_branch.name) + + schema_branch = registry.schema.get_schema_branch(name=default_branch.name) + + with pytest.raises(ValueError, match=r"Unable to find the relationship"): + continent_schema = schema_branch.get(name="LocationContinent", duplicate=False) + continent_schema.get_relationship(name="parent") + + assert continent_schema.uniqueness_constraints == [["name__value"]] + assert continent_schema.human_friendly_id == ["name__value"] + + with pytest.raises(ValueError, match=r"Unable to find the relationship"): + site_schema = schema_branch.get(name="LocationSite", duplicate=False) + site_schema.get_relationship(name="children") + + assert site_schema.uniqueness_constraints == [["parent", "name__value"]] + assert site_schema.human_friendly_id == ["parent__name__value", "name__value"] + + eu: Node = await Node.init(db=db, schema="LocationContinent", branch=default_branch) + await eu.new(db=db, name="Europe") + await eu.save(db=db) + + fr: Node = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + await fr.new(db=db, name="France", parent=eu) + await fr.save(db=db) + + uk: Node = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + with pytest.raises(ValidationError, match=r"parent is mandatory"): + await uk.new(db=db, name="United Kingdom") + + await uk.new(db=db, name="United Kingdom", parent=eu) + await uk.save(db=db) From aa08a5cec3f1d91f4fb2117d545d858c15f2f0fa Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 12:31:06 +0100 Subject: [PATCH 2/8] Fix typo --- backend/infrahub/core/schema/schema_branch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/infrahub/core/schema/schema_branch.py b/backend/infrahub/core/schema/schema_branch.py index fa4f6ecc78..860bc39af1 100644 --- a/backend/infrahub/core/schema/schema_branch.py +++ b/backend/infrahub/core/schema/schema_branch.py @@ -633,7 +633,7 @@ def validate_schema_path( and not ( schema_attribute_path.relationship_schema.name == "ip_namespace" and isinstance(node_schema, NodeSchema) - and (node_schema.is_ip_address() or node_schema.is_ip_prefix) + and (node_schema.is_ip_address() or node_schema.is_ip_prefix()) ) ): raise ValueError( From ab4c53f9360f9e19faa147093dbb8101d28cff1f Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 12:31:46 +0100 Subject: [PATCH 3/8] Add hierarchical relationships before validations --- backend/infrahub/core/schema/schema_branch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/infrahub/core/schema/schema_branch.py b/backend/infrahub/core/schema/schema_branch.py index 860bc39af1..1779ea5555 100644 --- a/backend/infrahub/core/schema/schema_branch.py +++ b/backend/infrahub/core/schema/schema_branch.py @@ -492,6 +492,8 @@ def process_pre_validation(self) -> None: self.process_branch_support() self.manage_profile_schemas() self.manage_profile_relationships() + self.add_hierarchy_generic() + self.add_hierarchy_node() def process_validate(self) -> None: self.validate_names() @@ -512,8 +514,6 @@ def process_validate(self) -> None: def process_post_validation(self) -> None: self.cleanup_inherited_elements() self.add_groups() - self.add_hierarchy_generic() - self.add_hierarchy_node() self.generate_weight() self.process_labels() self.process_dropdowns() From 9f7fd71da3a943bac3c694313b443e156453f363 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 12:38:32 +0100 Subject: [PATCH 4/8] Make `parent` mandatory in some cases The `parent` relationship becomes mandatory if the node depends on another one which is not itself or a generic of itself. This allows, for instance, to not require a continent to have a parent while enforcing a country to have a parent continent. The parent won't be required if a node can depends on one of its own. For instance, an IP prefix can have a parent prefix, which is still optional as an prefix can live on its own. --- backend/infrahub/core/schema/schema_branch.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/backend/infrahub/core/schema/schema_branch.py b/backend/infrahub/core/schema/schema_branch.py index 1779ea5555..8e3699cbc3 100644 --- a/backend/infrahub/core/schema/schema_branch.py +++ b/backend/infrahub/core/schema/schema_branch.py @@ -1522,18 +1522,22 @@ def _get_hierarchy_child_rel(self, peer: str, hierarchical: str, read_only: bool read_only=read_only, ) - def _get_hierarchy_parent_rel(self, peer: str, hierarchical: str, read_only: bool) -> RelationshipSchema: + def _get_hierarchy_parent_rel( + self, peer: str, hierarchical: str, read_only: bool, optional: str + ) -> RelationshipSchema: return RelationshipSchema( name="parent", identifier="parent__child", peer=peer, kind=RelationshipKind.HIERARCHY, cardinality=RelationshipCardinality.ONE, + min_count=0 if optional else 1, max_count=1, branch=BranchSupportType.AWARE, direction=RelationshipDirection.OUTBOUND, hierarchical=hierarchical, read_only=read_only, + optional=optional, ) def add_hierarchy_generic(self) -> None: @@ -1548,7 +1552,9 @@ def add_hierarchy_generic(self) -> None: if "parent" not in generic.relationship_names: generic.relationships.append( - self._get_hierarchy_parent_rel(peer=generic_name, hierarchical=generic_name, read_only=read_only) + self._get_hierarchy_parent_rel( + peer=generic_name, hierarchical=generic_name, read_only=read_only, optional=True + ) ) if "children" not in generic.relationship_names: generic.relationships.append( @@ -1571,7 +1577,10 @@ def add_hierarchy_node(self) -> None: if "parent" not in node.relationship_names: node.relationships.append( self._get_hierarchy_parent_rel( - peer=node.parent, hierarchical=node.hierarchy, read_only=read_only + peer=node.parent, + hierarchical=node.hierarchy, + read_only=read_only, + optional=node.parent in [node_name] + self.generic_names, ) ) else: From a7a2cdff4961428fd6fcfcc1472d6dec067b233a Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 14:17:50 +0100 Subject: [PATCH 5/8] Fix integration testing data --- backend/tests/test_data/dataset01.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/tests/test_data/dataset01.py b/backend/tests/test_data/dataset01.py index f13f2f7fe7..55d04fc22a 100644 --- a/backend/tests/test_data/dataset01.py +++ b/backend/tests/test_data/dataset01.py @@ -95,8 +95,14 @@ async def load_data(db: InfrahubDatabase, nbr_devices: int = 0) -> None: # roles_dict = {} log.info("Creating Site") + continent = await Node.init(db=db, schema="LocationContinent") + await continent.new(db=db, name="Africa") + await continent.save(db=db) + country = await Node.init(db=db, schema="LocationCountry") + await country.new(db=db, name="Kingdom of Wakanda", parent=continent) + await country.save(db=db) site_hq = await Node.init(db=db, schema="LocationSite") - await site_hq.new(db=db, name="HQ") + await site_hq.new(db=db, name="HQ", parent=country) await site_hq.save(db=db) active_status = "active" From 1c03e52496de11390f1471908f76e85d128650b1 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Fri, 24 Jan 2025 16:42:40 +0100 Subject: [PATCH 6/8] Use existing fixtures for tests --- .../test_node_uniqueness.py | 87 +++++-------------- .../schema_manager/test_manager_schema.py | 83 +++--------------- 2 files changed, 35 insertions(+), 135 deletions(-) diff --git a/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py b/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py index 57ece1e862..d4fa84220a 100644 --- a/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py +++ b/backend/tests/unit/core/constraint_validators/test_node_uniqueness.py @@ -34,85 +34,40 @@ async def test_node_validate_constraint_node_uniqueness_success( await constraint.check(alfred) -async def test_hierarchical_uniqueness_constraint(db, default_branch): - schema = { - "generics": [ - { - "attributes": [{"kind": "Text", "name": "name"}], - "description": "Generic hierarchical location", - "hierarchical": True, - "human_friendly_id": ["name__value"], - "label": "Location", - "name": "Generic", - "namespace": "Location", - } - ], - "nodes": [ - { - "children": "LocationCountry", - "description": "A continent on planet earth", - "display_labels": ["name__value"], - "generate_profile": False, - "human_friendly_id": ["name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Continent", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "", - "uniqueness_constraints": [["name__value"]], - }, - { - "children": "LocationSite", - "description": "A country within a continent", - "display_labels": ["name__value"], - "generate_profile": False, - "human_friendly_id": ["parent__name__value", "name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Country", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "LocationContinent", - "uniqueness_constraints": [["parent", "name__value"]], - }, - { - "attributes": [{"kind": "Text", "name": "city", "optional": True}], - "children": "", - "description": "A site within a country", - "display_labels": ["name__value"], - "human_friendly_id": ["parent__name__value", "name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Site", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "LocationCountry", - "uniqueness_constraints": [["parent", "name__value"]], - }, - ], - } - - registry.schema.register_schema(schema=SchemaRoot(**schema), branch=default_branch.name) +async def test_hierarchical_uniqueness_constraint( + db: InfrahubDatabase, default_branch: Branch, hierarchical_location_schema_simple_unregistered: SchemaRoot +): + site_schema = hierarchical_location_schema_simple_unregistered.get(name="LocationSite") + site_schema.human_friendly_id = ["parent__name__value", "name__value"] + site_schema.uniqueness_constraints = [["parent", "name__value"]] + + rack_schema = hierarchical_location_schema_simple_unregistered.get(name="LocationRack") + rack_schema.human_friendly_id = ["parent__name__value", "name__value"] + rack_schema.uniqueness_constraints = [["parent", "name__value"]] + + registry.schema.register_schema(schema=hierarchical_location_schema_simple_unregistered, branch=default_branch.name) constraint = NodeGroupedUniquenessConstraint(db=db, branch=default_branch) - eu = await Node.init(db=db, schema="LocationContinent", branch=default_branch) + eu = await Node.init(db=db, schema="LocationRegion", branch=default_branch) await eu.new(db=db, name="Europe") await eu.save(db=db) - fr = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + fr = await Node.init(db=db, schema="LocationSite", branch=default_branch) await fr.new(db=db, name="France", parent=eu) await fr.save(db=db) - uk = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + uk = await Node.init(db=db, schema="LocationSite", branch=default_branch) await uk.new(db=db, name="United Kingdom", parent=eu) await fr.save(db=db) - th2 = await Node.init(db=db, schema="LocationSite", branch=default_branch) - await th2.new(db=db, name="Telehouse 2", city="Paris", parent=fr) + th2 = await Node.init(db=db, schema="LocationRack", branch=default_branch) + await th2.new(db=db, name="th2-par", parent=fr) await th2.save(db=db) - ld6 = await Node.init(db=db, schema="LocationSite", branch=default_branch) - await ld6.new(db=db, name="Equinix LD6", city="London", parent=uk) + ld6 = await Node.init(db=db, schema="LocationRack", branch=default_branch) + await ld6.new(db=db, name="ld6-ldn", parent=uk) await ld6.save(db=db) await constraint.check(ld6) - ld6 = await Node.init(db=db, schema="LocationSite", branch=default_branch) - await ld6.new(db=db, name="Equinix LD6", city="London", parent=uk) + ld6 = await Node.init(db=db, schema="LocationRack", branch=default_branch) + await ld6.new(db=db, name="ld6-ldn", parent=uk) with pytest.raises(ValidationError, match=r"Violates uniqueness constraint 'parent-name' at parent"): await constraint.check(ld6) diff --git a/backend/tests/unit/core/schema_manager/test_manager_schema.py b/backend/tests/unit/core/schema_manager/test_manager_schema.py index 70c929ee85..2e7b758b37 100644 --- a/backend/tests/unit/core/schema_manager/test_manager_schema.py +++ b/backend/tests/unit/core/schema_manager/test_manager_schema.py @@ -2796,89 +2796,34 @@ async def test_process_deprecations(organization_schema): assert not test_criticality.get_relationship(name="second").optional -async def test_hierarchical_validate_parent_children(db, default_branch): - schema = { - "generics": [ - { - "attributes": [{"kind": "Text", "name": "name"}], - "description": "Generic hierarchical location", - "hierarchical": True, - "human_friendly_id": ["name__value"], - "label": "Location", - "name": "Generic", - "namespace": "Location", - } - ], - "nodes": [ - { - "children": "LocationCountry", - "description": "A continent on planet earth", - "display_labels": ["name__value"], - "generate_profile": False, - "human_friendly_id": ["name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Continent", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "", - "uniqueness_constraints": [["name__value"]], - }, - { - "children": "LocationSite", - "description": "A country within a continent", - "display_labels": ["name__value"], - "generate_profile": False, - "human_friendly_id": ["parent__name__value", "name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Country", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "LocationContinent", - "uniqueness_constraints": [["parent", "name__value"]], - }, - { - "attributes": [{"kind": "Text", "name": "city", "optional": True}], - "children": "", - "description": "A site within a country", - "display_labels": ["name__value"], - "human_friendly_id": ["parent__name__value", "name__value"], - "inherit_from": ["LocationGeneric"], - "name": "Site", - "namespace": "Location", - "order_by": ["name__value"], - "parent": "LocationCountry", - "uniqueness_constraints": [["parent", "name__value"]], - }, - ], - } +async def test_hierarchical_validate_parent_children( + db: InfrahubDatabase, default_branch: Branch, hierarchical_location_schema_simple_unregistered: SchemaRoot +): + site_schema = hierarchical_location_schema_simple_unregistered.get(name="LocationSite") + site_schema.human_friendly_id = ["parent__name__value", "name__value"] + site_schema.uniqueness_constraints = [["parent", "name__value"]] - registry.schema.register_schema(schema=SchemaRoot(**schema), branch=default_branch.name) + registry.schema.register_schema(schema=hierarchical_location_schema_simple_unregistered, branch=default_branch.name) schema_branch = registry.schema.get_schema_branch(name=default_branch.name) with pytest.raises(ValueError, match=r"Unable to find the relationship"): - continent_schema = schema_branch.get(name="LocationContinent", duplicate=False) - continent_schema.get_relationship(name="parent") - - assert continent_schema.uniqueness_constraints == [["name__value"]] - assert continent_schema.human_friendly_id == ["name__value"] + region_schema = schema_branch.get(name="LocationRegion", duplicate=False) + region_schema.get_relationship(name="parent") with pytest.raises(ValueError, match=r"Unable to find the relationship"): - site_schema = schema_branch.get(name="LocationSite", duplicate=False) - site_schema.get_relationship(name="children") - - assert site_schema.uniqueness_constraints == [["parent", "name__value"]] - assert site_schema.human_friendly_id == ["parent__name__value", "name__value"] + rack_schema = schema_branch.get(name="LocationRack", duplicate=False) + rack_schema.get_relationship(name="children") - eu: Node = await Node.init(db=db, schema="LocationContinent", branch=default_branch) + eu: Node = await Node.init(db=db, schema="LocationRegion", branch=default_branch) await eu.new(db=db, name="Europe") await eu.save(db=db) - fr: Node = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + fr: Node = await Node.init(db=db, schema="LocationSite", branch=default_branch) await fr.new(db=db, name="France", parent=eu) await fr.save(db=db) - uk: Node = await Node.init(db=db, schema="LocationCountry", branch=default_branch) + uk: Node = await Node.init(db=db, schema="LocationSite", branch=default_branch) with pytest.raises(ValidationError, match=r"parent is mandatory"): await uk.new(db=db, name="United Kingdom") From 725abf9be242cd742decca36ceffe2bcdef4cc1e Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 27 Jan 2025 10:53:46 +0100 Subject: [PATCH 7/8] Add changelog record --- changelog/3682.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3682.fixed.md diff --git a/changelog/3682.fixed.md b/changelog/3682.fixed.md new file mode 100644 index 0000000000..e4e57d996c --- /dev/null +++ b/changelog/3682.fixed.md @@ -0,0 +1 @@ +Automatically mark hierarchical nodes `parent` relationship as optional if the parent is of the same kind or mandatory if the parent is of a different kind \ No newline at end of file From 3105d801d4c37af3602a1d520b667e68b7fcf82c Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 27 Jan 2025 13:25:57 +0100 Subject: [PATCH 8/8] Fix types --- backend/infrahub/core/schema/schema_branch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/infrahub/core/schema/schema_branch.py b/backend/infrahub/core/schema/schema_branch.py index 8e3699cbc3..bf5e9a0b5a 100644 --- a/backend/infrahub/core/schema/schema_branch.py +++ b/backend/infrahub/core/schema/schema_branch.py @@ -1509,7 +1509,7 @@ def add_groups(self) -> None: if changed: self.set(name=node_name, schema=schema) - def _get_hierarchy_child_rel(self, peer: str, hierarchical: str, read_only: bool) -> RelationshipSchema: + def _get_hierarchy_child_rel(self, peer: str, hierarchical: str | None, read_only: bool) -> RelationshipSchema: return RelationshipSchema( name="children", identifier="parent__child", @@ -1523,7 +1523,7 @@ def _get_hierarchy_child_rel(self, peer: str, hierarchical: str, read_only: bool ) def _get_hierarchy_parent_rel( - self, peer: str, hierarchical: str, read_only: bool, optional: str + self, peer: str, hierarchical: str | None, read_only: bool, optional: bool ) -> RelationshipSchema: return RelationshipSchema( name="parent",