@@ -220,14 +220,7 @@ def production(self) -> _GenericHigherOrderBuilder:
220220 return self ._higher_order_builder (self , self ._create_method ).production () # type: ignore
221221
222222
223- class FormulaEngine (
224- Generic [QuantityT ],
225- _ComposableFormulaEngine [
226- "FormulaEngine" , # type: ignore[type-arg]
227- "HigherOrderFormulaBuilder" , # type: ignore[type-arg]
228- QuantityT ,
229- ],
230- ):
223+ class FormulaEngine (Generic [QuantityT ]):
231224 """[`FormulaEngine`][frequenz.sdk.timeseries.formula_engine.FormulaEngine]s are a
232225 part of the SDK's data pipeline, and provide a way for the SDK to apply formulas on
233226 resampled data streams.
@@ -308,8 +301,15 @@ def __init__(
308301 self ._higher_order_builder = HigherOrderFormulaBuilder
309302 self ._name : str = builder .name
310303 self ._builder : FormulaBuilder [QuantityT ] = builder
311- self ._create_method = create_method
304+ self ._create_method : Callable [[ float ], QuantityT ] = create_method
312305 self ._channel : Broadcast [Sample [QuantityT ]] = Broadcast (name = self ._name )
306+ self ._task : asyncio .Task [None ] | None = None
307+
308+ async def _stop (self ) -> None :
309+ """Stop a running formula engine."""
310+ if self ._task is None :
311+ return
312+ await cancel_and_await (self ._task )
313313
314314 @classmethod
315315 def from_receiver (
@@ -366,6 +366,132 @@ async def run() -> None:
366366 builder .push_metric (name , receiver , nones_are_zeros = nones_are_zeros )
367367 return cls (builder , create_method )
368368
369+ def __add__ (
370+ self ,
371+ other : (
372+ FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | QuantityT
373+ ),
374+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
375+ """Return a formula builder that adds (data in) `other` to `self`.
376+
377+ Args:
378+ other: A formula receiver, or a formula builder instance corresponding to a
379+ sub-expression.
380+
381+ Returns:
382+ A formula builder that can take further expressions, or can be built
383+ into a formula engine.
384+ """
385+ return HigherOrderFormulaBuilder (self , self ._create_method ) + other
386+
387+ def __sub__ (
388+ self ,
389+ other : (
390+ FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | QuantityT
391+ ),
392+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
393+ """Return a formula builder that subtracts (data in) `other` from `self`.
394+
395+ Args:
396+ other: A formula receiver, or a formula builder instance corresponding to a
397+ sub-expression.
398+
399+ Returns:
400+ A formula builder that can take further expressions, or can be built
401+ into a formula engine.
402+ """
403+ return HigherOrderFormulaBuilder (self , self ._create_method ) - other
404+
405+ def __mul__ (
406+ self ,
407+ other : FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | float ,
408+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
409+ """Return a formula builder that multiplies (data in) `self` with `other`.
410+
411+ Args:
412+ other: A formula receiver, or a formula builder instance corresponding to a
413+ sub-expression.
414+
415+ Returns:
416+ A formula builder that can take further expressions, or can be built
417+ into a formula engine.
418+ """
419+ return HigherOrderFormulaBuilder (self , self ._create_method ) * other
420+
421+ def __truediv__ (
422+ self ,
423+ other : FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | float ,
424+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
425+ """Return a formula builder that divides (data in) `self` by `other`.
426+
427+ Args:
428+ other: A formula receiver, or a formula builder instance corresponding to a
429+ sub-expression.
430+
431+ Returns:
432+ A formula builder that can take further expressions, or can be built
433+ into a formula engine.
434+ """
435+ return HigherOrderFormulaBuilder (self , self ._create_method ) / other
436+
437+ def max (
438+ self ,
439+ other : (
440+ FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | QuantityT
441+ ),
442+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
443+ """Return a formula engine that outputs the maximum of `self` and `other`.
444+
445+ Args:
446+ other: A formula receiver, a formula builder or a QuantityT instance
447+ corresponding to a sub-expression.
448+
449+ Returns:
450+ A formula builder that can take further expressions, or can be built
451+ into a formula engine.
452+ """
453+ return HigherOrderFormulaBuilder (self , self ._create_method ).max (other )
454+
455+ def min (
456+ self ,
457+ other : (
458+ FormulaEngine [QuantityT ] | HigherOrderFormulaBuilder [QuantityT ] | QuantityT
459+ ),
460+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
461+ """Return a formula engine that outputs the minimum of `self` and `other`.
462+
463+ Args:
464+ other: A formula receiver, a formula builder or a QuantityT instance
465+ corresponding to a sub-expression.
466+
467+ Returns:
468+ A formula builder that can take further expressions, or can be built
469+ into a formula engine.
470+ """
471+ return HigherOrderFormulaBuilder (self , self ._create_method ).min (other )
472+
473+ def consumption (
474+ self ,
475+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
476+ """
477+ Return a formula builder that applies the consumption operator on `self`.
478+
479+ The consumption operator returns either the identity if the power value is
480+ positive or 0.
481+ """
482+ return HigherOrderFormulaBuilder (self , self ._create_method ).consumption ()
483+
484+ def production (
485+ self ,
486+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
487+ """
488+ Return a formula builder that applies the production operator on `self`.
489+
490+ The production operator returns either the absolute value if the power value is
491+ negative or 0.
492+ """
493+ return HigherOrderFormulaBuilder (self , self ._create_method ).production ()
494+
369495 async def _run (self ) -> None :
370496 await self ._builder .subscribe ()
371497 steps , metric_fetchers = self ._builder .finalize ()
0 commit comments