Skip to content

♻️ Migrate use of extra_links to Schema-Based Access#1638

Merged
chrisjsewell merged 6 commits intomasterfrom
use-links-schema
Feb 2, 2026
Merged

♻️ Migrate use of extra_links to Schema-Based Access#1638
chrisjsewell merged 6 commits intomasterfrom
use-links-schema

Conversation

@chrisjsewell
Copy link
Member

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,
similar to how fields are used.

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:

for link_type in needs_config.extra_links:
    name = link_type["option"]
    outgoing = link_type["outgoing"]

After:

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

# 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
@chrisjsewell chrisjsewell requested a review from Copilot February 2, 2026 12:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 LinkSchema with LinkDisplayConfig dataclass for rendering properties and added copy and allow_dead_links attributes
  • Renamed extra_links to _extra_links in 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
Copy link

codecov bot commented Feb 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.54%. Comparing base (4e10030) to head (8ff2052).
⚠️ Report is 233 commits behind head on master.

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     
Flag Coverage Δ
pytests 88.54% <100.00%> (+1.66%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@ubmarco ubmarco left a comment

Choose a reason for hiding this comment

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

LGTM

@chrisjsewell chrisjsewell merged commit 2b9d23e into master Feb 2, 2026
21 of 22 checks passed
@chrisjsewell chrisjsewell deleted the use-links-schema branch February 2, 2026 17:36
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.

3 participants