Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/452.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Re-enable specifying a cardinality-one relationship using a RelatedNode when creating an InfrahubNode
23 changes: 21 additions & 2 deletions infrahub_sdk/node/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,11 +501,21 @@

return cls(client=client, schema=schema, branch=branch, data=cls._strip_alias(data))

def _init_relationships(self, data: dict | None = None) -> None:
def _init_relationships(self, data: dict | RelatedNode | None = None) -> None:
for rel_schema in self._schema.relationships:
rel_data = data.get(rel_schema.name, None) if isinstance(data, dict) else None

if rel_schema.cardinality == "one":
if isinstance(rel_data, RelatedNode):
peer_id_data: dict[str, Any] = {}
if rel_data.id:
peer_id_data["id"] = rel_data.id
if rel_data.hfid:
peer_id_data["hfid"] = rel_data.hfid
if peer_id_data:
rel_data = peer_id_data
else:
rel_data = None

Check warning on line 518 in infrahub_sdk/node/node.py

View check run for this annotation

Codecov / codecov/patch

infrahub_sdk/node/node.py#L518

Added line #L518 was not covered by tests
self._relationship_cardinality_one_data[rel_schema.name] = RelatedNode(
name=rel_schema.name, branch=self._branch, client=self._client, schema=rel_schema, data=rel_data
)
Expand Down Expand Up @@ -1079,10 +1089,19 @@
rel_data = data.get(rel_schema.name, None) if isinstance(data, dict) else None

if rel_schema.cardinality == "one":
if isinstance(rel_data, RelatedNodeSync):
peer_id_data: dict[str, Any] = {}
if rel_data.id:
peer_id_data["id"] = rel_data.id
if rel_data.hfid:
peer_id_data["hfid"] = rel_data.hfid
if peer_id_data:
rel_data = peer_id_data
else:
rel_data = None

Check warning on line 1101 in infrahub_sdk/node/node.py

View check run for this annotation

Codecov / codecov/patch

infrahub_sdk/node/node.py#L1101

Added line #L1101 was not covered by tests
self._relationship_cardinality_one_data[rel_schema.name] = RelatedNodeSync(
name=rel_schema.name, branch=self._branch, client=self._client, schema=rel_schema, data=rel_data
)

else:
self._relationship_cardinality_many_data[rel_schema.name] = RelationshipManagerSync(
name=rel_schema.name,
Expand Down
21 changes: 21 additions & 0 deletions tests/integration/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ async def test_node_create_with_relationships(
assert node_after.name.value == node.name.value
assert node_after.manufacturer.peer.id == manufacturer_mercedes.id

async def test_node_create_with_relationships_using_related_node(
self,
default_branch: str,
client: InfrahubClient,
initial_schema: None,
manufacturer_mercedes,
car_golf,
person_joe,
):
related_node = car_golf.owner
node = await client.create(
kind=TESTING_CAR, name="Tiguan", color="Black", manufacturer=manufacturer_mercedes, owner=related_node
)
await node.save(allow_upsert=True)
assert node.id is not None

node_after = await client.get(kind=TESTING_CAR, id=node.id, prefetch_relationships=True)
assert node_after.name.value == node.name.value
assert node_after.manufacturer.peer.id == manufacturer_mercedes.id
assert node_after.owner.peer.id == person_joe.id

async def test_node_update_with_original_data(
self,
default_branch: str,
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/sdk/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
parse_human_friendly_id,
)
from infrahub_sdk.node.constants import SAFE_VALUE
from infrahub_sdk.node.related_node import RelatedNode, RelatedNodeSync
from infrahub_sdk.schema import GenericSchema, NodeSchemaAPI

if TYPE_CHECKING:
Expand Down Expand Up @@ -194,6 +195,50 @@ async def test_init_node_data_user_with_relationships(client, location_schema: N
assert "get_kind" in keys


@pytest.mark.parametrize("client_type", client_types)
@pytest.mark.parametrize("rel_data", [{"id": "pppppppp"}, {"hfid": ["pppp", "pppp"]}])
async def test_init_node_data_user_with_relationships_using_related_node(
client, location_schema: NodeSchemaAPI, client_type, rel_data
):
rel_schema = location_schema.get_relationship(name="primary_tag")
if client_type == "standard":
primary_tag = RelatedNode(name="primary_tag", branch="main", client=client, schema=rel_schema, data=rel_data)
else:
primary_tag = RelatedNodeSync(
name="primary_tag", branch="main", client=client, schema=rel_schema, data=rel_data
)

data = {
"name": {"value": "JFK1"},
"description": {"value": "JFK Airport"},
"type": {"value": "SITE"},
"primary_tag": primary_tag,
"tags": [{"id": "aaaaaa"}, {"id": "bbbb"}],
}
if client_type == "standard":
node = InfrahubNode(client=client, schema=location_schema, data=data)
else:
node = InfrahubNodeSync(client=client, schema=location_schema, data=data)

assert node.name.value == "JFK1"
assert node.name.is_protected is None
assert node.description.value == "JFK Airport"
assert node.type.value == "SITE"

assert isinstance(node.tags, RelationshipManagerBase)
assert len(node.tags.peers) == 2
assert isinstance(node.tags.peers[0], RelatedNodeBase)
assert isinstance(node.primary_tag, RelatedNodeBase)
assert node.primary_tag.id == rel_data.get("id")
assert node.primary_tag.hfid == rel_data.get("hfid")

keys = dir(node)
assert "name" in keys
assert "type" in keys
assert "tags" in keys
assert "get_kind" in keys


@pytest.mark.parametrize("property_test", property_tests)
@pytest.mark.parametrize("client_type", client_types)
async def test_init_node_data_graphql(
Expand Down