Source code for cfx.refs
"""Field and component reference proxies.
Accessing a field or component on a `Config` *class* (not an instance)
returns a `FieldRef` that records the dotpath to that attribute. These
references are passed to `Alias` and `Mirror` at view class definition time
so that paths are validated against the schema immediately, before any
instance exists.
Chaining attribute access extends the path one step at a time::
CalibrationConfig.psf_fitting.kernel_estimate
# → FieldRef("psf_fitting.kernel_estimate")
"""
__all__ = ["FieldRef", "ComponentRef"]
[docs]
class FieldRef:
"""A reference to a field on a `Config` class.
Obtained by accessing a field or component as a class attribute rather
than on an instance. Attribute chains are validated against the schema
at definition time — a typo in the path raises `AttributeError`
immediately, not at the first runtime access.
Pass a `FieldRef` to `Alias` or `Mirror` instead of a plain string to
keep paths refactorable via normal IDE rename and go-to-definition tools.
Examples
--------
>>> from cfx import Config, Field, Alias
>>> class Inner(Config):
... x: float = Field(1.0, "x value")
>>> class Outer(Config, components=[Inner]):
... pass
>>> Outer.inner.x # doctest: +ELLIPSIS
FieldRef(...)
>>> Alias(Outer.inner.x) # doctest: +ELLIPSIS
<...Alias object at ...>
"""
def __init__(self, path: str, resolved_cls):
self._path = path
# None for leaf fields; a Config subclass for component branch nodes.
self._cls = resolved_cls
[docs]
def __getattr__(self, name: str) -> "FieldRef":
if name.startswith("_"):
raise AttributeError(name)
if self._cls is None:
raise AttributeError(
f"cannot traverse past leaf field {self._path!r}"
)
if name in self._cls._fields:
return FieldRef(f"{self._path}.{name}", None)
if name in self._cls._nested_classes:
return FieldRef(
f"{self._path}.{name}", self._cls._nested_classes[name]
)
raise AttributeError(
f"{self._cls.__name__!r} has no field or component {name!r}"
)
[docs]
def __repr__(self) -> str:
return f"FieldRef({self._path!r})"
[docs]
class ComponentRef:
"""Descriptor installed on a `Config` class for each component slot.
Installed automatically by `_ConfigType` after ``_nested_classes`` is
built. Returns a `FieldRef` on class-level access so component paths
can be used in `Alias` and `Mirror` declarations. On instance access
returns the stored sub-config instance as normal.
"""
def __init__(self, confid: str, cls):
self.confid = confid
self.cls = cls
[docs]
def __set_name__(self, owner, name: str):
self.confid = name
[docs]
def __get__(self, obj, objtype=None):
if obj is None:
return FieldRef(self.confid, self.cls)
return obj.__dict__[self.confid]