Skip to content

Conversation

@FragmentedPacket
Copy link
Contributor

@FragmentedPacket FragmentedPacket commented Dec 31, 2025

This allows the user to pass in a single for single HFID values as per the documentation

Fixes #731

Summary by CodeRabbit

  • Bug Fixes

    • Improved HFID/reference normalization: single strings, lists, and UUIDs are now consistently interpreted and stored when creating objects.
  • Tests

    • Added comprehensive unit tests covering single/many cardinality and mixed reference formats to validate normalization behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

…t have to provide HFID directly if single value HFID.
@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

Walkthrough

Adds HFID normalization utilities and applies them during object loading. Introduces import is_valid_uuid and two functions in infrahub_sdk/spec/object.py: normalize_hfid_reference(value: str | list[str]) -> str | list[str] and normalize_hfid_references(values: list[str | list[str]]) -> list[str | list[str]]. create_node was updated to use these normalizers for ONE_REF and MANY_REF relationship values. Adds unit tests TestHfidNormalizationInObjectLoading in tests/unit/sdk/spec/test_object.py validating normalization for string, list, UUID, and mixed HFID inputs (test class duplicated in file).

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: fixing HFID casting for non-UUID strings, which directly addresses the core issue in the PR.
Linked Issues check ✅ Passed The changes implement normalization functions to convert plain strings to HFID list format for both single and many-cardinality relationships, directly addressing issue #731's requirement.
Out of Scope Changes check ✅ Passed All changes focus on HFID normalization in object loading—adding helper functions and updating relationship handling in create_node, plus comprehensive tests. No unrelated changes detected.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68b8112 and fc9b258.

📒 Files selected for processing (1)
  • infrahub_sdk/spec/object.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • infrahub_sdk/spec/object.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Follow async/sync dual pattern for new features in the Python SDK

Files:

  • infrahub_sdk/spec/object.py
🧬 Code graph analysis (1)
infrahub_sdk/spec/object.py (1)
infrahub_sdk/utils.py (1)
  • is_valid_uuid (85-91)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: unit-tests (3.10)
  • GitHub Check: unit-tests (3.12)
  • GitHub Check: unit-tests (3.13)
  • GitHub Check: unit-tests (3.14)
  • GitHub Check: unit-tests (3.11)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
infrahub_sdk/spec/object.py (4)

10-10: LGTM!

The import of is_valid_uuid is appropriate for the new normalization functions. The utility safely handles edge cases by catching ValueError.


37-52: LGTM! Past review feedback addressed.

The return type annotation now correctly reflects the polymorphic behavior (str | list[str]), and the type: ignore comment has been removed. The function properly normalizes HFID references by:

  • Preserving lists as-is for multi-component HFIDs
  • Preserving UUID strings for ID-based lookups
  • Wrapping non-UUID strings in lists for single-component HFIDs

This addresses the issue described in #731 where plain strings were not being cast correctly.


55-60: LGTM!

The batch normalization function correctly applies normalize_hfid_reference to each item in the list, supporting the many-cardinality use case described in the PR objectives.


474-483: LGTM! Correctly implements HFID normalization per PR objectives.

The relationship handling properly applies normalization for both cardinalities:

  • MANY_REF: Each HFID in the list is normalized (non-UUID strings→lists, UUIDs→strings)
  • ONE_REF: Single values are normalized and passed directly to RelatedNode for interpretation

This directly fixes the issue in #731 where plain strings like ["Colocation"] were not being cast correctly. The inline comments clearly document the normalization behavior and downstream interpretation by RelatedNode.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
infrahub_sdk/spec/object.py (1)

37-48: Return type annotation is inconsistent with actual behavior.

The function returns str when the value is a UUID (line 47) but list[str] otherwise. The current annotation -> list[str] is misleading to callers and requires a type: ignore to silence the checker.

🔎 Proposed fix
-def normalize_hfid_reference(value: str | list[str]) -> list[str]:
+def normalize_hfid_reference(value: str | list[str]) -> str | list[str]:
     """Normalize a reference value to HFID format.
 
     If the value is a string and not a valid UUID, wrap it in a list to treat it as a single-component HFID.
     If the value is already a list, return it as-is.
     If the value is a UUID string, return it as-is (will be treated as an ID).
     """
     if isinstance(value, list):
         return value
     if is_valid_uuid(value):
-        return value  # type: ignore[return-value]
+        return value
     return [value]
tests/unit/sdk/spec/test_object.py (1)

342-358: Consider refactoring duplicated mock pattern to a shared fixture.

The mock_create function and InfrahubNode.save patch are duplicated across all 7 tests. Additionally, the first test uses a different pattern (original_create = client_with_schema_01.create on line 344) compared to others (client_with_schema_01.__class__.create on line 375).

A shared fixture would reduce duplication and ensure consistency:

🔎 Suggested refactor
@pytest.fixture
def mock_client_create(self, client_with_schema_01: InfrahubClient) -> tuple[InfrahubClient, list[dict]]:
    """Fixture to mock client.create and track calls."""
    from unittest.mock import AsyncMock, patch

    create_calls: list[dict] = []
    original_create = client_with_schema_01.create

    async def mock_create(
        kind: str, branch: str | None = None, data: dict | None = None, **kwargs: Any
    ) -> InfrahubNode:
        create_calls.append({"kind": kind, "data": data})
        node = await original_create(kind=kind, branch=branch, data=data, **kwargs)
        return node

    client_with_schema_01.create = mock_create

    with patch("infrahub_sdk.node.InfrahubNode.save", new_callable=AsyncMock):
        yield client_with_schema_01, create_calls

Then each test becomes simpler:

async def test_cardinality_one_string_hfid_normalized(
    self, mock_client_create: tuple[InfrahubClient, list[dict]],
    location_with_cardinality_one_string_hfid: dict
) -> None:
    client, create_calls = mock_client_create
    obj = ObjectFile(location="some/path", content=location_with_cardinality_one_string_hfid)
    await obj.validate_format(client=client)
    await obj.process(client=client)
    
    assert len(create_calls) == 1
    assert create_calls[0]["data"]["primary_tag"] == [["Important"]]

Also applies to: 371-383

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 646e075 and c134441.

📒 Files selected for processing (2)
  • infrahub_sdk/spec/object.py
  • tests/unit/sdk/spec/test_object.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • tests/unit/sdk/spec/test_object.py
  • infrahub_sdk/spec/object.py
tests/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

tests/**/*.py: Use httpx_mock fixture for HTTP mocking in tests instead of making real HTTP requests
Do not add @pytest.mark.asyncio decorator to async test functions (async auto-mode is globally enabled)

Files:

  • tests/unit/sdk/spec/test_object.py
tests/unit/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

Unit tests must be fast, mocked, and have no external dependencies

Files:

  • tests/unit/sdk/spec/test_object.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Follow async/sync dual pattern for new features in the Python SDK

Files:

  • infrahub_sdk/spec/object.py
🧬 Code graph analysis (2)
tests/unit/sdk/spec/test_object.py (1)
infrahub_sdk/spec/object.py (5)
  • ObjectFile (663-691)
  • validate_format (202-221)
  • validate_format (684-688)
  • process (223-236)
  • process (690-691)
infrahub_sdk/spec/object.py (1)
infrahub_sdk/utils.py (1)
  • is_valid_uuid (85-91)
🪛 GitHub Actions: CI
tests/unit/sdk/spec/test_object.py

[error] 346-346: ANN202 Missing return type annotation for private function mock_create


[error] 346-346: ANN003 Missing type annotation for **kwargs


[warning] 346-347: PLC0415 import should be at the top-level of a file


[error] 373-373: ANN202 Missing return type annotation for private function mock_create


[error] 373-373: ANN003 Missing type annotation for **kwargs


[warning] 355-355: PLC0415 import should be at the top-level of a file


[warning] 380-380: PLC0415 import should be at the top-level of a file


[error] 397-397: ANN202 Missing return type annotation for private function mock_create


[error] 397-397: ANN003 Missing type annotation for **kwargs


[warning] 404-404: PLC0415 import should be at the top-level of a file


[error] 422-422: ANN202 Missing return type annotation for private function mock_create


[error] 422-422: ANN003 Missing type annotation for **kwargs


[warning] 429-429: PLC0415 import should be at the top-level of a file


[error] 446-446: ANN202 Missing return type annotation for private function mock_create


[error] 446-446: ANN003 Missing type annotation for **kwargs


[warning] 453-453: PLC0415 import should be at the top-level of a file


[error] 470-470: ANN202 Missing return type annotation for private function mock_create


[error] 470-470: ANN003 Missing type annotation for **kwargs


[warning] 477-477: PLC0415 import should be at the top-level of a file


[error] 495-495: ANN202 Missing return type annotation for private function mock_create


[error] 495-495: ANN003 Missing type annotation for **kwargs


[warning] 502-502: PLC0415 import should be at the top-level of a file

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (8)
infrahub_sdk/spec/object.py (3)

10-10: LGTM!

Import of is_valid_uuid is correctly added to support UUID validation in the normalization functions.


51-56: LGTM!

The function correctly applies normalization to each element in the list.


470-476: LGTM!

The normalization logic is correctly integrated into the relationship handling. The inline comments clearly explain the behavior: string HFIDs are normalized to list format while UUIDs remain as strings.

tests/unit/sdk/spec/test_object.py (5)

268-278: LGTM!

The test class and fixtures are well-structured with clear docstrings explaining each scenario.


279-333: Good test fixture coverage.

The fixtures comprehensively cover cardinality-one and cardinality-many scenarios with strings, lists, UUIDs, and mixed inputs.


388-411: LGTM!

The UUID test correctly verifies that UUIDs are passed through without being wrapped in a list, which aligns with the intended behavior of treating UUIDs as IDs rather than HFIDs.


461-484: LGTM!

Good edge case coverage: the mixed HFID test validates that string HFIDs get wrapped while list HFIDs (multi-component) remain unchanged.


486-512: LGTM!

The cardinality-many UUID test correctly validates that UUIDs remain as strings in the list, matching the normalization behavior.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 31, 2025

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: fc9b258
Status: ✅  Deploy successful!
Preview URL: https://74623cf7.infrahub-sdk-python.pages.dev
Branch Preview URL: https://may-202512-object-load-many.infrahub-sdk-python.pages.dev

View logs

@codecov
Copy link

codecov bot commented Dec 31, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##           stable     #732      +/-   ##
==========================================
+ Coverage   76.84%   76.86%   +0.02%     
==========================================
  Files         113      113              
  Lines        9767     9776       +9     
  Branches     1497     1499       +2     
==========================================
+ Hits         7505     7514       +9     
  Misses       1757     1757              
  Partials      505      505              
Flag Coverage Δ
integration-tests 34.65% <84.61%> (+0.06%) ⬆️
python-3.10 51.25% <92.30%> (+0.43%) ⬆️
python-3.11 51.23% <92.30%> (+0.41%) ⬆️
python-3.12 ?
python-3.13 51.23% <92.30%> (+0.43%) ⬆️
python-3.14 52.89% <92.30%> (+0.45%) ⬆️
python-filler-3.12 23.86% <0.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/spec/object.py 85.24% <100.00%> (+0.44%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/unit/sdk/spec/test_object.py (2)

335-362: Refactor: Inconsistent mock pattern across tests.

The first test (lines 335-362) uses:

original_create = client_with_schema_01.create
# ... later ...
return await original_create(kind=kind, branch=branch, data=data, **kwargs)

While the remaining tests (lines 364-530) use:

original_create = client_with_schema_01.__class__.create
# ... later ...
return await original_create(client_with_schema_01, kind=kind, branch=branch, data=data, **kwargs)

Both approaches work, but the inconsistency reduces code clarity. Consider standardizing on one pattern throughout the test class.

🔎 Recommended approach

Use the first pattern (instance method) consistently, as it's simpler and doesn't require passing self explicitly:

original_create = client_with_schema_01.create
return await original_create(kind=kind, branch=branch, data=data, **kwargs)

Also applies to: 364-530


335-530: Refactor: Extract common mock setup to reduce duplication.

Each test method repeats nearly identical mock_create setup code. Consider extracting this into a helper fixture or method to improve maintainability.

🔎 Suggested refactoring approach

Add a fixture or helper method to capture create calls:

@pytest.fixture
def create_call_tracker(self, client_with_schema_01: InfrahubClient):
    """Fixture that tracks calls to client.create."""
    create_calls: list[dict[str, Any]] = []
    original_create = client_with_schema_01.create
    
    async def mock_create(
        kind: str,
        branch: str | None = None,
        data: dict | None = None,
        **kwargs: Any,  # noqa: ANN401
    ) -> InfrahubNode:
        create_calls.append({"kind": kind, "data": data})
        return await original_create(kind=kind, branch=branch, data=data, **kwargs)
    
    client_with_schema_01.create = mock_create
    return create_calls

Then simplify each test to:

async def test_cardinality_one_string_hfid_normalized(
    self, 
    client_with_schema_01: InfrahubClient, 
    location_with_cardinality_one_string_hfid: dict,
    create_call_tracker: list[dict[str, Any]]
) -> None:
    obj = ObjectFile(location="some/path", content=location_with_cardinality_one_string_hfid)
    await obj.validate_format(client=client_with_schema_01)
    
    with patch("infrahub_sdk.node.InfrahubNode.save", new_callable=AsyncMock):
        await obj.process(client=client_with_schema_01)
    
    assert len(create_call_tracker) == 1
    assert create_call_tracker[0]["data"]["primary_tag"] == [["Important"]]

This eliminates ~15 lines of duplicated code per test.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c134441 and b409d99.

📒 Files selected for processing (1)
  • tests/unit/sdk/spec/test_object.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • tests/unit/sdk/spec/test_object.py
tests/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

tests/**/*.py: Use httpx_mock fixture for HTTP mocking in tests instead of making real HTTP requests
Do not add @pytest.mark.asyncio decorator to async test functions (async auto-mode is globally enabled)

Files:

  • tests/unit/sdk/spec/test_object.py
tests/unit/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

Unit tests must be fast, mocked, and have no external dependencies

Files:

  • tests/unit/sdk/spec/test_object.py
🧠 Learnings (4)
📚 Learning: 2025-12-10T17:13:37.990Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: tests/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:37.990Z
Learning: Configure pytest with async auto-mode enabled

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:08.136Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:08.136Z
Learning: Applies to infrahub_sdk/client.py : Always provide both async and sync versions of client implementations in InfrahubClient

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:21.977Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: infrahub_sdk/ctl/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:21.977Z
Learning: Applies to infrahub_sdk/ctl/**/*.py : Do not instantiate InfrahubClient directly; always use initialize_client() or initialize_client_sync() helper functions

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:29.593Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: infrahub_sdk/pytest_plugin/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:29.593Z
Learning: Applies to infrahub_sdk/pytest_plugin/**/infrahub_sdk/pytest_plugin/items/*.py : Inherit from `InfrahubItem` base class when creating new test item classes in `infrahub_sdk/pytest_plugin/items/`

Applied to files:

  • tests/unit/sdk/spec/test_object.py
🧬 Code graph analysis (1)
tests/unit/sdk/spec/test_object.py (1)
infrahub_sdk/spec/object.py (5)
  • ObjectFile (663-691)
  • validate_format (202-221)
  • validate_format (684-688)
  • process (223-236)
  • process (690-691)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: unit-tests (3.13)
  • GitHub Check: unit-tests (3.14)
  • GitHub Check: unit-tests (3.11)
  • GitHub Check: unit-tests (3.12)
  • GitHub Check: unit-tests (3.10)
  • GitHub Check: integration-tests-latest-infrahub
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
tests/unit/sdk/spec/test_object.py (2)

3-4: LGTM: Past review comments addressed.

The imports have been correctly moved to the top level, and InfrahubNode has been added to the TYPE_CHECKING block. This resolves the previous linting warnings (PLC0415, ANN003, ANN202).

Also applies to: 13-13


270-333: LGTM: Comprehensive fixture coverage.

The test fixtures provide thorough coverage of HFID normalization scenarios across different cardinalities and input formats (strings, lists, UUIDs, mixed).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/unit/sdk/spec/test_object.py (1)

335-532: Standardize the mock_create implementation pattern.

The first test (lines 343-353) stores original_create before replacing client.create, then calls the stored reference. The remaining tests (lines 374-382, 402-410, etc.) access the original via client_with_schema_01.__class__.create without storing it first. While both approaches work, this inconsistency may confuse future maintainers.

🔎 Suggested approach: Use the __class__.create pattern consistently

Update the first test to match the pattern used in other tests:

     async def test_cardinality_one_string_hfid_normalized(
         self, client_with_schema_01: InfrahubClient, location_with_cardinality_one_string_hfid: dict
     ) -> None:
         """String HFID for cardinality-one should be wrapped in a list."""
         obj = ObjectFile(location="some/path", content=location_with_cardinality_one_string_hfid)
         await obj.validate_format(client=client_with_schema_01)
 
         # Track calls to client.create
         create_calls: list[dict[str, Any]] = []
-        original_create = client_with_schema_01.create
 
         async def mock_create(
             kind: str,
             branch: str | None = None,
             data: dict | None = None,
             **kwargs: Any,  # noqa: ANN401
         ) -> InfrahubNode:
             create_calls.append({"kind": kind, "data": data})
-            return await original_create(kind=kind, branch=branch, data=data, **kwargs)
+            original_create = client_with_schema_01.__class__.create
+            return await original_create(client_with_schema_01, kind=kind, branch=branch, data=data, **kwargs)
 
         client_with_schema_01.create = mock_create
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b409d99 and a5852e9.

📒 Files selected for processing (2)
  • infrahub_sdk/spec/object.py
  • tests/unit/sdk/spec/test_object.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • infrahub_sdk/spec/object.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • tests/unit/sdk/spec/test_object.py
tests/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

tests/**/*.py: Use httpx_mock fixture for HTTP mocking in tests instead of making real HTTP requests
Do not add @pytest.mark.asyncio decorator to async test functions (async auto-mode is globally enabled)

Files:

  • tests/unit/sdk/spec/test_object.py
tests/unit/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

Unit tests must be fast, mocked, and have no external dependencies

Files:

  • tests/unit/sdk/spec/test_object.py
🧠 Learnings (4)
📚 Learning: 2025-12-10T17:13:37.990Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: tests/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:37.990Z
Learning: Configure pytest with async auto-mode enabled

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:08.136Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:08.136Z
Learning: Applies to infrahub_sdk/client.py : Always provide both async and sync versions of client implementations in InfrahubClient

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:21.977Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: infrahub_sdk/ctl/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:21.977Z
Learning: Applies to infrahub_sdk/ctl/**/*.py : Do not instantiate InfrahubClient directly; always use initialize_client() or initialize_client_sync() helper functions

Applied to files:

  • tests/unit/sdk/spec/test_object.py
📚 Learning: 2025-12-10T17:13:29.593Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: infrahub_sdk/pytest_plugin/AGENTS.md:0-0
Timestamp: 2025-12-10T17:13:29.593Z
Learning: Applies to infrahub_sdk/pytest_plugin/**/infrahub_sdk/pytest_plugin/items/*.py : Inherit from `InfrahubItem` base class when creating new test item classes in `infrahub_sdk/pytest_plugin/items/`

Applied to files:

  • tests/unit/sdk/spec/test_object.py
🧬 Code graph analysis (1)
tests/unit/sdk/spec/test_object.py (4)
infrahub_sdk/node/node.py (1)
  • InfrahubNode (483-1269)
infrahub_sdk/client.py (1)
  • InfrahubClient (318-1744)
infrahub_sdk/spec/object.py (5)
  • ObjectFile (665-693)
  • validate_format (202-221)
  • validate_format (686-690)
  • process (223-236)
  • process (692-693)
infrahub_sdk/schema/main.py (1)
  • kind (279-280)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: unit-tests (3.10)
  • GitHub Check: unit-tests (3.14)
  • GitHub Check: unit-tests (3.11)
  • GitHub Check: unit-tests (3.13)
  • GitHub Check: unit-tests (3.12)
  • GitHub Check: integration-tests-latest-infrahub
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
tests/unit/sdk/spec/test_object.py (1)

3-4: LGTM! Imports properly organized.

The imports have been moved to the top level and type annotations support added, addressing the previous CI failures.

Also applies to: 13-13

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5852e9 and 68b8112.

📒 Files selected for processing (1)
  • infrahub_sdk/spec/object.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • infrahub_sdk/spec/object.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Follow async/sync dual pattern for new features in the Python SDK

Files:

  • infrahub_sdk/spec/object.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: unit-tests (3.10)
  • GitHub Check: unit-tests (3.11)
  • GitHub Check: unit-tests (3.14)
  • GitHub Check: unit-tests (3.12)
  • GitHub Check: integration-tests-latest-infrahub
  • GitHub Check: unit-tests (3.13)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
infrahub_sdk/spec/object.py (2)

51-56: LGTM with a note on type dependencies.

The function correctly normalizes a list of references by applying normalize_hfid_reference to each item. The return type list[str | list[str]] accurately reflects the polymorphic nature of the normalized values (strings for UUIDs, lists for HFIDs).

Once the return type of normalize_hfid_reference is corrected to str | list[str], this function will be fully type-safe without any suppressions.


470-479: Well-structured HFID normalization for relationship values.

The updated logic correctly handles both cardinality cases:

  • MANY_REF: Normalizes each reference in the list, converting non-UUID strings to HFID format
  • ONE_REF: Normalizes the single reference value, preserving UUIDs as strings and wrapping non-UUID strings

The inline comments clearly explain how RelatedNode interprets the different formats. This implementation addresses the bug described in issue #731 where plain strings weren't being cast into the expected HFID format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: HFID for cardinality many relationships string not being cast to HFID format (list)

2 participants