Source code for openfisca_core.tracers.tracing_parameter_node_at_instant
from __future__ import annotations
import typing
from typing import Union
import numpy
from openfisca_core import parameters
ParameterNode = Union[
parameters.VectorialParameterNodeAtInstant,
parameters.ParameterNodeAtInstant,
]
if typing.TYPE_CHECKING:
from numpy.typing import ArrayLike
from openfisca_core import tracers
Child = Union[ParameterNode, ArrayLike]
[docs]
class TracingParameterNodeAtInstant:
def __init__(
self,
parameter_node_at_instant: ParameterNode,
tracer: tracers.FullTracer,
) -> None:
self.parameter_node_at_instant = parameter_node_at_instant
self.tracer = tracer
def __getattr__(
self,
key: str,
) -> TracingParameterNodeAtInstant | Child:
child = getattr(self.parameter_node_at_instant, key)
return self.get_traced_child(child, key)
def __contains__(self, key) -> bool:
return key in self.parameter_node_at_instant
def __iter__(self):
return iter(self.parameter_node_at_instant)
def __getitem__(
self,
key: str | ArrayLike,
) -> TracingParameterNodeAtInstant | Child:
child = self.parameter_node_at_instant[key]
return self.get_traced_child(child, key)
def get_traced_child(
self,
child: Child,
key: str | ArrayLike,
) -> TracingParameterNodeAtInstant | Child:
period = self.parameter_node_at_instant._instant_str
if isinstance(
child,
(
parameters.ParameterNodeAtInstant,
parameters.VectorialParameterNodeAtInstant,
),
):
return TracingParameterNodeAtInstant(child, self.tracer)
if not isinstance(key, str) or isinstance(
self.parameter_node_at_instant,
parameters.VectorialParameterNodeAtInstant,
):
# In case of vectorization, we keep the parent node name as, for
# instance, rate[status].zone1 is best described as the value of
# "rate".
name = self.parameter_node_at_instant._name
else:
name = f"{self.parameter_node_at_instant._name}.{key}"
if isinstance(child, (numpy.ndarray, *parameters.ALLOWED_PARAM_TYPES)):
self.tracer.record_parameter_access(name, period, child)
return child