@pproperty not enforced when derived @pconfig narrows a field's type
- Dominant language
- Python
- Stars
- 1
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
**Summary**
When a derived `@pconfig` class narrows a field's type annotation and the base class defines a `@pproperty` for that field, pconfigs requires the user to write a `@pproperty` override in the derived class that upgrades the incoming type. If they do not, a config instance file that passes the old base type will be silently accepted at construction time but crash at runtime when code accesses a field that only exists on the derived type.
This is a feature request for pconfigs to auto-generate that upgrading pproperty, or to raise an actionable error at class-definition time when the narrowing is detected without a corresponding override.
**Motivation**
A derived config class that narrows a field type signals an invariant: objects constructed from that config should always receive the derived type. But the base pproperty runs and returns the user-provided value unchanged, so a plain base-typed value passes through silently. The failure surfaces only at runtime, far from the config definition. There is no signal at class-definition or construction time that a pproperty override is required.
**Proposed behavior**
When pconfigs detects that a derived config class narrows the declared type of a field that has a `@pproperty` in a base class, and the derived class does not define its own `@pproperty` for that field, it should either (a) automatically synthesize a pproperty that upgrades the base type to the declared derived type, or (b) raise an error at class-definition time.
```python
from pconfigs import pconfig, pconfiged, pproperty, pinputs, pdefaults
from typing import Optional
@pconfig
class WidgetConfig:
color: Optional[str]
@pconfig
class FancyWidgetConfig(WidgetConfig):
size: Optional[int]
pdefaults += WidgetConfig(color=None)
pdefaults += FancyWidgetConfig(color=None, size=None)
@pconfiged
class System:
config: SystemConfig
@pconfig(constructs=System)
class SystemConfig:
widget_config: WidgetConfig
@pproperty
def widget_config(self) -> WidgetConfig:
return pinputs(self).widget_config
pdefaults += SystemConfig(widget_config=pdefaults(WidgetConfig))
@pconfiged
class FancySystem(System):
config: FancySystemConfig
@pconfig(constructs=FancySystem)
class FancySystemConfig(SystemConfig):
widget_config: FancyWidgetConfig # narrowed — but no pproperty override
pdefaults += FancySystemConfig(widget_config=pdefaults(FancyWidgetConfig))
# User passes a plain WidgetConfig where FancyWidgetConfig is declared.
# The base pproperty accepts it silently. Downstream code that accesses
# .size crashes at runtime with AttributeError.
config = FancySystemConfig(widget_config=WidgetConfig(color="red"))
system = config.construct()
print(system.config.widget_config.size) # AttributeError: 'WidgetConfig' has no attribute 'size'
```
Proposed: `FancySystemConfig(widget_config=WidgetConfig(...)).construct()` should raise at construction time with a message like:
> `FancySystemConfig` narrows field `widget_config` to `FancyWidgetConfig`, but inherits a `@pproperty` from `SystemConfig` that returns `WidgetConfig`. Define a `@pproperty` override in `FancySystemConfig` to enforce the narrowed type.
**Current workaround**
The derived config class must manually define a `@pproperty` override that upgrades the user-provided base type to the derived type. This is easy to forget and there is no warning when it is omitted.
Contributor guide
Research direction
Start by tracing how @pconfig, inherited @pproperty methods, and construct() handle declared field types during FancySystemConfig construction. Reproduce the WidgetConfig/FancyWidgetConfig example, then determine whether the project should synthesize an upgrading property or raise the proposed class-definition or construction-time error. The issue names no implementation files or tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100