👌 Parse link conditions from imported and external needs#1680
👌 Parse link conditions from imported and external needs#1680chrisjsewell merged 2 commits intomasterfrom
Conversation
## Summary `NeedLink.from_string` now parses condition syntax (e.g. `"REQ_001[status==\"open\"]"`) from link strings, so that needs loaded via `needimport` or `needs_external_needs` can carry conditional links — previously only directive option parsing supported this. ## Changes ### Core: `NeedLink` (`sphinx_needs/need_item.py`) - **`from_string`** — now delegates to `from_string_with_warnings`, which performs bracket-depth condition parsing (matching the logic previously only in `_parse_link_with_condition`). - **`from_string_with_warnings`** — new static method returning `tuple[NeedLink, list[str]]`. Infallible best-effort parse with structured warnings for unclosed brackets or trailing text. - **`_parse_address`** — extracted helper for splitting `ID.part` addresses. - **`to_link_string`** — serializes a `NeedLink` back to string *including* the condition. Computes bracket depth as one more than the longest consecutive `]` run in the condition, ensuring safe round-tripping for any condition content. - **`to_filter_string`** — unchanged (no condition, used for filter expressions and JSON output). ### Schema: `_split_link_list` (`sphinx_needs/needs_schema.py`) - **`_parse_link_with_condition`** removed — its 3-line body (delegate to `NeedLink.from_string_with_warnings`) is now inlined into `_flush_current()` inside `_split_link_list`. ### Import prefix fix (`sphinx_needs/utils.py`) - **`import_prefix_link_edit`** — previously compared raw link strings with `id == link`, which broke with conditioned links. Now parses each link via `NeedLink.from_string`, compares `.id`, and reconstructs with `to_link_string()` to preserve conditions through the prefixing process. ### Documentation - **`docs/directives/need.rst`** — note in the "conditional links" section about JSON support via import/external. - **`docs/directives/needimport.rst`** — note cross-referencing `need_conditional_links`. - **`docs/configuration.rst`** — note in the `needs_external_needs` section. ### Tests - **`tests/test_need_item_api.py`** — 23 unit tests across `TestNeedLinkFromString` (11) and `TestNeedLinkToLinkString` (12), covering plain IDs, parts, conditions, bracket escaping, malformed input, and round-trip serialization. - **`tests/test_link_conditions.py`** — integration test extended to verify warnings from imported needs (`needimport` with `needs_test_conditions.json`) and external needs (`needs_external_needs` with `needs_test_external.json`). - **New fixtures**: `needs_test_conditions.json`, `needs_test_external.json` — JSON files with conditioned links for import/external testing.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1680 +/- ##
==========================================
+ Coverage 86.87% 89.03% +2.15%
==========================================
Files 56 71 +15
Lines 6532 10157 +3625
==========================================
+ Hits 5675 9043 +3368
- Misses 857 1114 +257
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Overview
This PR closes a feature gap: conditional link syntax (e.g. Architecture & DesignThe approach is well-structured:
Code QualityStrengths
Observations & Minor Points
Test CoverageVery thorough:
Documentation
Potential Concerns
VerdictThis is a clean, well-tested, well-documented PR that correctly consolidates link condition parsing into the Looks good to merge ✅ |
Summary
NeedLink.from_stringnow parses condition syntax (e.g."REQ_001[status==\"open\"]") from link strings, so that needs loaded vianeedimportorneeds_external_needscan carry conditional links — previously only directive option parsing supported this.Changes
Core:
NeedLink(sphinx_needs/need_item.py)from_string— now delegates tofrom_string_with_warnings, which performs bracket-depth condition parsing (matching the logic previously only in_parse_link_with_condition).from_string_with_warnings— new static method returningtuple[NeedLink, list[str]]. Infallible best-effort parse with structured warnings for unclosed brackets or trailing text._parse_address— extracted helper for splittingID.partaddresses.to_link_string— serializes aNeedLinkback to string including the condition. Computes bracket depth as one more than the longest consecutive]run in the condition, ensuring safe round-tripping for any condition content.to_filter_string— unchanged (no condition, used for filter expressions and JSON output).Schema:
_split_link_list(sphinx_needs/needs_schema.py)_parse_link_with_conditionremoved — its 3-line body (delegate toNeedLink.from_string_with_warnings) is now inlined into_flush_current()inside_split_link_list.Import prefix fix (
sphinx_needs/utils.py)import_prefix_link_edit— previously compared raw link strings withid == link, which broke with conditioned links. Now parses each link viaNeedLink.from_string, compares.id, and reconstructs withto_link_string()to preserve conditions through the prefixing process.Documentation
docs/directives/need.rst— note in the "conditional links" section about JSON support via import/external.docs/directives/needimport.rst— note cross-referencingneed_conditional_links.docs/configuration.rst— note in theneeds_external_needssection.Tests
tests/test_need_item_api.py— 23 unit tests acrossTestNeedLinkFromString(11) andTestNeedLinkToLinkString(12), covering plain IDs, parts, conditions, bracket escaping, malformed input, and round-trip serialization.tests/test_link_conditions.py— integration test extended to verify warnings from imported needs (needimportwithneeds_test_conditions.json) and external needs (needs_external_needswithneeds_test_external.json).needs_test_conditions.json,needs_test_external.json— JSON files with conditioned links for import/external testing.