adobe / adobe/pconfigs

Copy-constructing a derived config from a base instance requires explicitly re-stating pinned field defaults

Open
#3 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
1
Forks
1
PR merge metrics
No merged PRs in 30d

Description

**Summary**

When a derived config re-declares a base field as `Pinned[T]`, copy-constructing the derived config from a base instance raises a `ValueError` unless the user explicitly passes `field=Pinned` (or `field=Pin(value)`) at the call site. The derived class's `pdefaults` entry alone is not sufficient to suppress the error.

**Motivation**

The derived class has already declared the field as pinned and set its default via `pdefaults`. Requiring the user to re-state the pinned default at every call site is redundant and easy to forget, producing a confusing error with no indication of what went wrong.

**Proposed behavior**

When copy-constructing a derived config from a base instance, fields declared `Pinned[T]` in the derived class should not require the user to re-state the pinned default at the call site. The derived class's `pdefaults` entry should be sufficient.

This applies when the pinned field is managed by a `@pproperty`:

```python
from __future__ import annotations
from pconfigs import pconfig, pdefaults, Pinned, pproperty

@pconfig
class BaseConfig:
mode: str

pdefaults += BaseConfig(
mode='train',
)

@pconfig
class DerivedConfig(BaseConfig):
mode: Pinned[str]

@pproperty
def mode(self) -> str:
return 'eval'

pdefaults += DerivedConfig(
mode=Pinned,
)

print(DerivedConfig(BaseConfig()).mode) # raises ValueError ✗ — proposed: 'eval'
```

And when the pinned field uses a plain `Pin(value)` default:

```python
@pconfig
class DerivedConfig(BaseConfig):
mode: Pinned[str]

pdefaults += DerivedConfig(
mode=Pin('eval'),
)

print(DerivedConfig(BaseConfig()).mode) # raises ValueError ✗ — proposed: 'eval'
```

**Current workaround**

Pass the pinned default explicitly at the call site.

For the `@pproperty` case:
```python
config = DerivedConfig(
BaseConfig(),
mode=Pinned,
)
# ✓ returns 'eval'
```

For the `Pin(value)` case:
```python
config = DerivedConfig(
BaseConfig(),
mode=Pin(pdefaults(DerivedConfig).mode),
)
# ✓ returns 'eval'
```

Contributor guide

Open the contributing guide

Research direction

Start by tracing copy construction from BaseConfig to DerivedConfig through the pconfig, Pinned, pdefaults, pproperty, and Pin entry points shown in the examples. Reproduce both the @pproperty and Pin(value) cases, then verify that DerivedConfig(BaseConfig()).mode uses the derived pdefaults value without requiring an explicit pinned argument.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.