♻️ Migrate use of extra_links to Schema-Based Access#1638
♻️ Migrate use of extra_links to Schema-Based Access#1638chrisjsewell merged 6 commits intomasterfrom
extra_links to Schema-Based Access#1638Conversation
# PR: Migrate `extra_links` to Schema-Based Access
## Summary
This PR migrates all post-config-resolution uses of `needs_config.extra_links` to use `needs_schema` methods, centralizing link type configuration in the schema system.
## Key Changes
### Schema Enhancements (`needs_schema.py`)
- **Added `LinkDisplayConfig`** dataclass for link rendering configuration:
- `incoming`, `outgoing` (required): Display titles for link directions
- `color`, `style`, `style_part`, `style_start`, `style_end`: Diagram styling with sensible defaults
- **Extended `LinkSchema`** with new attributes:
- `display: LinkDisplayConfig` - Rendering configuration (required)
- `copy: bool` - Whether to copy links to common `links` field
- `allow_dead_links: bool` - Whether to allow dead links without warning
### Configuration Changes (`config.py`, `needs.py`)
- Renamed `extra_links` → `_extra_links` (internal use only, for config resolution phase)
- Schema creation in `needs.py` now populates `LinkDisplayConfig` from link config, using dataclass defaults when values aren't explicitly set
### Updated Modules
Migrated from dict-based `needs_config.extra_links` access to schema methods:
| Module | Change |
|--------|--------|
| `layout.py` | Use `schema.iter_link_fields()` and `link.display.*` |
| `api/need.py` | Use `schema.iter_link_fields()` and `link.copy` |
| `directives/need.py` | Use schema for `allow_dead_links` lookup |
| `directives/needtable.py` | Use `LinkSchema` objects instead of dicts |
| `directives/needflow/_plantuml.py` | Use schema for link types and display config |
| `directives/needflow/_graphviz.py` | Use schema for link types and display config |
| `directives/needgantt.py` | Use schema for link type validation |
| `directives/needsequence.py` | Use schema for link type names |
| `directives/needreport.py` | Convert schema to dict for template compatibility |
| `directives/list2need.py` | Use schema for link type list |
| `roles/need_outgoing.py` | Use schema for `allow_dead_links` check |
| `utils.py` | Use schema for link field iteration |
## Migration Pattern
**Before:**
```python
for link_type in needs_config.extra_links:
name = link_type["option"]
outgoing = link_type["outgoing"]
```
**After:**
```python
for link in needs_schema.iter_link_fields():
name = link.name
outgoing = link.display.outgoing
```
## Benefits
- **Single source of truth**: Link configuration is centralized in the schema after config resolution
- **Type safety**: `LinkSchema` and `LinkDisplayConfig` provide typed access to link properties
- **Cleaner separation**: `_extra_links` is internal for config merging; schema is the public API
- **Consistent defaults**: `LinkDisplayConfig` dataclass defaults are used consistently
There was a problem hiding this comment.
Pull request overview
This PR migrates link type configuration from the dict-based needs_config.extra_links to a schema-based approach, centralizing link configuration in the schema system after config resolution.
Changes:
- Extended
LinkSchemawithLinkDisplayConfigdataclass for rendering properties and addedcopyandallow_dead_linksattributes - Renamed
extra_linksto_extra_linksin config to mark it as internal-only for config resolution - Updated all post-config modules to access link configuration via schema methods instead of config dicts
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/snapshots/test_basic_doc.ambr | Updated snapshot to include new LinkSchema attributes in schema representation |
| sphinx_needs/needs_schema.py | Added LinkDisplayConfig dataclass and extended LinkSchema with display, copy, and allow_dead_links attributes |
| sphinx_needs/needs.py | Updated schema creation to populate LinkDisplayConfig from config and renamed extra_links to _extra_links |
| sphinx_needs/config.py | Renamed extra_links to _extra_links with updated documentation |
| sphinx_needs/layout.py | Migrated to use schema methods for link field access and display properties |
| sphinx_needs/utils.py | Changed to use schema iteration instead of config dict access |
| sphinx_needs/roles/need_outgoing.py | Updated to use schema for allow_dead_links lookup |
| sphinx_needs/directives/needtable.py | Migrated from dict-based to LinkSchema object-based link type handling |
| sphinx_needs/directives/needsequence.py | Updated to iterate link field names via schema |
| sphinx_needs/directives/needreport.py | Converts schema to dict for template compatibility |
| sphinx_needs/directives/needgantt.py | Updated to validate link types using schema |
| sphinx_needs/directives/needflow/_shared.py | Changed parameter from link type dicts to link names |
| sphinx_needs/directives/needflow/_plantuml.py | Migrated to LinkSchema objects and display config access |
| sphinx_needs/directives/needflow/_graphviz.py | Migrated to LinkSchema objects and display config access |
| sphinx_needs/directives/needflow/_directive.py | Updated to join link names from schema iteration |
| sphinx_needs/directives/need.py | Updated update_back_links to accept schema parameter |
| sphinx_needs/directives/list2need.py | Changed to get link types from schema iteration |
| sphinx_needs/api/need.py | Updated _copy_links to use schema instead of config |
Comments suppressed due to low confidence (1)
sphinx_needs/needs_schema.py:1
- The TODO comment should be removed or converted into a tracked issue. Inline TODO comments can become stale and are easy to lose track of.
from __future__ import annotations
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1638 +/- ##
==========================================
+ Coverage 86.87% 88.54% +1.66%
==========================================
Files 56 70 +14
Lines 6532 9975 +3443
==========================================
+ Hits 5675 8832 +3157
- Misses 857 1143 +286
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:
|
This PR migrates all post-config-resolution uses of
needs_config.extra_linksto useneeds_schemamethods, centralizing link type configuration in the schema system,similar to how fields are used.
Key Changes
Schema Enhancements (
needs_schema.py)Added
LinkDisplayConfigdataclass for link rendering configuration:incoming,outgoing(required): Display titles for link directionscolor,style,style_part,style_start,style_end: Diagram styling with sensible defaultsExtended
LinkSchemawith new attributes:display: LinkDisplayConfig- Rendering configuration (required)copy: bool- Whether to copy links to commonlinksfieldallow_dead_links: bool- Whether to allow dead links without warningConfiguration Changes (
config.py,needs.py)extra_links→_extra_links(internal use only, for config resolution phase)needs.pynow populatesLinkDisplayConfigfrom link config, using dataclass defaults when values aren't explicitly setUpdated Modules
Migrated from dict-based
needs_config.extra_linksaccess to schema methods:layout.pyschema.iter_link_fields()andlink.display.*api/need.pyschema.iter_link_fields()andlink.copydirectives/need.pyallow_dead_linkslookupdirectives/needtable.pyLinkSchemaobjects instead of dictsdirectives/needflow/_plantuml.pydirectives/needflow/_graphviz.pydirectives/needgantt.pydirectives/needsequence.pydirectives/needreport.pydirectives/list2need.pyroles/need_outgoing.pyallow_dead_linkscheckutils.pyMigration Pattern
Before:
After:
Benefits
LinkSchemaandLinkDisplayConfigprovide typed access to link properties_extra_linksis internal for config merging; schema is the public APILinkDisplayConfigdataclass defaults are used consistently