feat(profiles): rename ProfileDescriptor/DescriptorProfile to ProfileSpec/Profile (26.5.0)#44
Merged
Merged
Conversation
17-task plan covering the mountainash-settings half of the profile/spec rename design. Generated by superpowers:writing-plans from docs/superpowers/specs/2026-05-13-profile-spec-rename-design.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New mountainash_settings.profiles.lookup module exposes lookup_class_var(cls, name), which walks __mro__ and returns the first matching attribute. Used internally by Profile for __spec__ and __adapter__ lookup; documented as supported public API from 26.5.0 so downstream consumers can adopt it without taking a private-dependency risk. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New canonical module mountainash_settings.profiles.spec exposes: - ProfileSpec (was ProfileDescriptor) - Missing (was _Missing, now public) - MISSING (unchanged) - ParameterSpec (unchanged) Old names remain available from descriptor.py in this commit; the descriptor.py shim conversion comes in a later task. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ribute - Profile class replaces DescriptorProfile (old name aliased in Task 9). - Class attribute __spec__ replaces __descriptor__. - __pydantic_init_subclass__ accepts either attribute; raises TypeError on conflict, emits DeprecationWarning on __descriptor__-only. - post_init() uses the public lookup_class_var helper for MRO walks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up to commit 020be9c which missed this one rename. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_resolve_spec() now sets cls.__spec__ = cls.__descriptor__ when falling back to the deprecated attribute. Without this, classes that still declare __descriptor__ would have fields installed correctly but every call to profile_name/backend/provider_type/_default_kwargs() would raise AttributeError on the missing __spec__. Also bumps stacklevel from 3 to 4 so the DeprecationWarning points at the user's 'class Foo(Profile):' line rather than pydantic's ModelMetaclass.__new__ internals. Test coverage extended to assert all four methods on a __descriptor__-only class. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Registry(name, *, spec_type=ProfileSpec, profile_type=Profile) lets domain-specific registries declare their constraints at construction time. register() raises TypeError on spec or class type mismatch. Default values preserve the existing wide-open behaviour for callers that don't pass constraints. Also mirrors __spec__ to __descriptor__ on register() during the 26.5.x deprecation window (dropped in 26.6.0) so downstream code reading the old attribute keeps working. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@register (no args) reads cls.__spec__ and registers — the new canonical form, naming the spec exactly once. @register(spec) still works during deprecation with a DeprecationWarning, and additionally raises TypeError if the argument disagrees with cls.__spec__ (drift catch). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three review-driven fixes on top of 74737c6: - Reorder isinstance branches: check ProfileSpec before type. The previous order also worked but the swapped form better expresses precedence and guards against metaclass-style spec subclasses. - Drift-catch error now identifies specs by .name instead of repr(), which would otherwise produce a wall of ParameterSpec detail. - Hoist the transitional ProfileDescriptor widening to module level as _SPEC_TYPES. Task 8 can now remove the widening in a single block. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Locks in the deprecation contract that downstream readers of cls.__descriptor__ keep working through 26.5.x. Whole test class is deleted in 26.6.0 when the mirror is dropped. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Function and generated test class renamed: - descriptor_invariants_for() -> spec_invariants_for() - TestDescriptorInvariants_<name> -> TestSpecInvariants_<name> - parametrize ID 'descriptor' -> 'spec' Old name aliased in Task 9. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
descriptor.py now re-exports MISSING and ParameterSpec from spec.py (unchanged names) and uses PEP 562 __getattr__ to intercept the renamed ProfileDescriptor and _Missing with DeprecationWarning. BackendDescriptor is intentionally NOT aliased here — it's a mountainash-data symbol owned downstream. profiles/__init__.py updated to alias ProfileDescriptor = ProfileSpec directly (no import from descriptor.py) to avoid spurious DeprecationWarning at package import time. registry.py updated to remove the try/except import of ProfileDescriptor from descriptor.py — _SPEC_TYPES is now (ProfileSpec,) since ProfileDescriptor IS ProfileSpec after this task. test_descriptor.py removed; equivalent coverage in test_spec.py and test_deprecation.py (next task). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
profiles/__init__.py exports ProfileSpec, Profile, Missing, lookup_class_var, and spec_invariants_for as the canonical public names. The old names ProfileDescriptor, DescriptorProfile, and descriptor_invariants_for resolve via PEP 562 __getattr__ with DeprecationWarning until 26.6.0. Top-level mountainash_settings/__init__.py updated to import and re-export the new canonical names only (no deprecated aliases at package root). test_public_api.py updated to use new names accordingly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mountainash_settings.__init__ exports ProfileSpec, Profile, Missing, lookup_class_var, and spec_invariants_for in __all__. Old names (ProfileDescriptor, DescriptorProfile, descriptor_invariants_for) resolve via PEP 562 __getattr__ with DeprecationWarning until 26.6.0. test_public_api updated to use new names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New tests/unit/profiles/test_deprecation.py asserts every deprecated entry point still resolves, emits DeprecationWarning, and points at the right new symbol. Also verifies the __spec__ -> __descriptor__ mirror on classes registered via the new bare @register form. Entire file is deleted in 26.6.0 along with the shims it covers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renames the why-when explanation doc and updates all type references to the new vocabulary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Registry method is still named get_descriptor() in registry.py (kept as backwards-compat name per the rename plan). Reverting the doc to match the actual API. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Profile/ProfileSpec rename with deprecation aliases. See docs/superpowers/specs/2026-05-13-profile-spec-rename-design.md for the full design and migration guide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ruff F822 flagged ProfileDescriptor and _Missing in __all__ as undefined at module scope — they resolve via PEP 562 __getattr__, which ruff doesn't know about. Removing them from __all__ is the correct fix and also matches semantics: deprecated names should not be pulled in by `from descriptor import *` silently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Implements the 26.5.0 upstream half of docs/superpowers/specs/2026-05-13-profile-spec-rename-design.md.
ProfileDescriptor→ProfileSpecDescriptorProfile→Profile__descriptor__→__spec__(mirrored to the old name during 26.5.x for downstream readers)descriptor_invariants_for→spec_invariants_for_Missing→Missing(now public)lookup_class_var()Registry(spec_type=, profile_type=)constructor constraints@register(old@register(spec)form deprecated)Old names remain available via PEP 562 module
__getattr__and class-attribute fallback withDeprecationWarning. All deprecation aliases are scheduled for removal in 26.6.0.Test plan
hatch run test:test— 448 passinghatch run ruff:check— cleanhatch build— wheel + sdist build cleanly as 26.5.0python -W error::DeprecationWarning -c "import mountainash_settings"— no warnings on clean importfrom mountainash_settings import ProfileDescriptoremits aDeprecationWarningpointing atProfileSpecfrom mountainash_settings import ProfileSpec, Profile, lookup_class_var, spec_invariants_forall resolveRemoval commitment
The deprecation aliases will be removed in mountainash-settings 26.6.0. Downstream consumers (mountainash-data, others) should follow the migration guide before that release.
Implementation history
21 commits implementing the 17-task plan at docs/superpowers/plans/2026-05-13-profile-spec-rename-upstream.md. Each commit verified with full test suite green; reviews caught and fixed bugs around
__spec__aliasing on__descriptor__-only classes, deprecation warning stacklevel, drift-catch error message, and decorator dispatch ordering.🤖 Generated with Claude Code