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
27 changes: 20 additions & 7 deletions backend/infrahub/core/schema/schema_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,17 +793,17 @@ def validate_display_label(self) -> None:
if len(node_schema.display_labels) == 1:
# If the previous display_labels consist of a single attribute convert
# it to an attribute based display label
converted_display_label = node_schema.display_labels[0]
if "__" not in converted_display_label:
# Previously we allowed defining a raw attribute name as a component of a
# display_label, if this is the case we need to append '__value'
converted_display_label = f"{converted_display_label}__value"
update_candidate.display_label = converted_display_label
update_candidate.display_label = _format_display_label_component(
component=node_schema.display_labels[0]
)
else:
# If the previous display label consists of multiple attributes
# convert it to a Jinja2 based display label
update_candidate.display_label = " ".join(
[f"{{{{ {display_label} }}}}" for display_label in node_schema.display_labels]
[
f"{{{{ {_format_display_label_component(component=display_label)} }}}}"
for display_label in node_schema.display_labels
]
)
self.set(name=name, schema=update_candidate)

Expand Down Expand Up @@ -2592,3 +2592,16 @@ def manage_object_template_schemas(self) -> None:
updated_used_by_node = set(chain(template_schema_kinds, set(core_node_schema.used_by)))
core_node_schema.used_by = sorted(updated_used_by_node)
self.set(name=InfrahubKind.NODE, schema=core_node_schema)


def _format_display_label_component(component: str) -> str:
"""Return correct format for display_label.

Previously both the format of 'name' and 'name__value' was
supported this function ensures that the proper 'name__value'
format is used
"""
if "__" in component:
return component

return f"{component}__value"
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from dataclasses import dataclass

import pytest

from infrahub.core.schema import AttributeSchema, NodeSchema, SchemaRoot
from infrahub.core.schema.schema_branch import SchemaBranch


@dataclass
class DisplayLabelTestCase:
name: str
schema_root: SchemaRoot
display_label: str


DISPLAY_LABEL_TEST_CASES: list[DisplayLabelTestCase] = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good pattern. easy to read

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree we have it in a few places and I think we should do more of it. Especially for pytest.params with multiple variables.

DisplayLabelTestCase(
name="single_attribute_label_no_value",
schema_root=SchemaRoot(
nodes=[
NodeSchema(
name="Widget",
namespace="Test",
attributes=[AttributeSchema(name="name", kind="Text"), AttributeSchema(name="status", kind="Text")],
display_labels=["name"],
)
]
),
display_label="name__value",
),
DisplayLabelTestCase(
name="single_attribute_label_with_value",
schema_root=SchemaRoot(
nodes=[
NodeSchema(
name="Widget",
namespace="Test",
attributes=[AttributeSchema(name="name", kind="Text"), AttributeSchema(name="status", kind="Text")],
display_labels=["name__value"],
)
]
),
display_label="name__value",
),
DisplayLabelTestCase(
name="dual_attribute_label_no_value",
schema_root=SchemaRoot(
nodes=[
NodeSchema(
name="Widget",
namespace="Test",
attributes=[AttributeSchema(name="name", kind="Text"), AttributeSchema(name="status", kind="Text")],
display_labels=["name", "status"],
)
]
),
display_label="{{ name__value }} {{ status__value }}",
),
DisplayLabelTestCase(
name="dual_attribute_label_mixed_value",
schema_root=SchemaRoot(
nodes=[
NodeSchema(
name="Widget",
namespace="Test",
attributes=[AttributeSchema(name="name", kind="Text"), AttributeSchema(name="status", kind="Text")],
display_labels=["name__value", "status"],
)
]
),
display_label="{{ name__value }} {{ status__value }}",
),
DisplayLabelTestCase(
name="defined_display_label",
schema_root=SchemaRoot(
nodes=[
NodeSchema(
name="Widget",
namespace="Test",
attributes=[AttributeSchema(name="name", kind="Text"), AttributeSchema(name="status", kind="Text")],
display_labels=["name__value", "status"],
display_label="{{ name__value|upper }}: {{ status__value|lower }}",
)
]
),
display_label="{{ name__value|upper }}: {{ status__value|lower }}",
),
]


@pytest.mark.parametrize(
"test_case",
[pytest.param(tc, id=tc.name) for tc in DISPLAY_LABEL_TEST_CASES],
)
async def test_expected_final_display_label(
test_case: DisplayLabelTestCase,
) -> None:
"""Test that the final computed display label matches the expected value."""
schema_branch = SchemaBranch(cache={}, name="test")
schema_branch.load_schema(schema=test_case.schema_root)
schema_branch.process()
node = schema_branch.get_node(name="TestWidget", duplicate=False)
assert node.display_label == test_case.display_label