class MetersBase(DefaultDict):
r"""Base container for collections of meter objects.
Subclasses can provide a `meter_cls` attribute to enforce the type of
values stored in the dictionary and customise how callable objects are
converted into meters.
"""
meter_cls: Optional[type] = None
def __init__(self, *args: Mapping[str, Any] | None, default_factory=None, **meters: Any) -> None:
self.__dict__["_metricsdict_initialising"] = True
meter_cls = getattr(self, "meter_cls", None)
factory = default_factory if default_factory is not None else meter_cls
super().__init__(default_factory=factory)
self.__dict__["_metricsdict_initialising"] = False
dict.pop(self, "meter_cls", None)
initial: dict[str, Any] = {}
if args:
if len(args) > 1:
raise TypeError("MetersBase accepts at most one positional mapping argument.")
mapping = args[0]
if mapping is not None:
initial.update(dict(mapping))
if meters:
initial.update(meters)
for name, meter in initial.items():
self.set(name, meter)
def set(self, name: Any, value: Any) -> None:
if self.__dict__.get("_metricsdict_initialising", False):
super().set(name, value)
return
super().set(name, self._coerce_meter(value))
def _coerce_meter(self, value: Any):
meter_cls = getattr(self, "meter_cls", None)
if meter_cls is None or isinstance(value, meter_cls):
return value
raise ValueError(f"Expected value to be an instance of {meter_cls.__name__}, but got {type(value)}")
def value(self) -> RoundDict[str, float]:
return RoundDict({key: metric.value() for key, metric in self.all_items()})
def batch(self) -> RoundDict[str, float]:
return RoundDict({key: metric.batch() for key, metric in self.all_items()})
def average(self) -> RoundDict[str, float]:
return RoundDict({key: metric.average() for key, metric in self.all_items()})
@property
def val(self) -> RoundDict[str, float]:
return self.value()
@property
def bat(self) -> RoundDict[str, float]:
return self.batch()
@property
def avg(self) -> RoundDict[str, float]:
return self.average()
def reset(self) -> Self:
for metric in self.all_values():
metric.reset()
return self
def __format__(self, format_spec: str) -> str:
return "\t".join(f"{key}: {metric.__format__(format_spec)}" for key, metric in self.all_items())