Source code for tg_model.model.expr
"""Build unitflow expressions from model refs without ``.sym`` boilerplate.
Python evaluates ``a + b + c`` **left to parenthesized**: ``(a + b) + c``. After ``a + b`` you have an
:class:`unitflow.expr.expressions.Expr`. The next ``+ c`` calls **Expr**'s ``__add__``, which uses
unitflow's ``_promote(c)`` — and **AttributeRef** is not a valid operand there, so you get
``ExprError: Cannot promote AttributeRef to Expr``.
**Ways to write roll-ups (pick one):**
- **Parentheses:** ``a + (b + c)`` so every ``+`` still involves an
:class:`~tg_model.model.refs.AttributeRef` on the left.
- **Explicit symbols:** ``a.sym + b.sym + c.sym`` (what ``AttributeRef.__add__`` does internally for the left operand).
- **This module:** :func:`sum_attributes` / :func:`as_expr_leaf` — same thing, obvious intent for ME/MBSE authors.
"""
from __future__ import annotations
from typing import Any
from tg_model.model.refs import AttributeRef
[docs]
def as_expr_leaf(x: Any) -> Any:
"""Promote :class:`~tg_model.model.refs.AttributeRef` to unitflow expr leaf.
Parameters
----------
x
Attribute ref or already-expression value.
Returns
-------
Any
``x.sym`` for refs; otherwise ``x``.
Notes
-----
Use when hand-building sums so ``expr + AttributeRef`` never hits unitflow's ``_promote``.
"""
if isinstance(x, AttributeRef):
return x.sym
return x
[docs]
def sum_attributes(*terms: Any) -> Any:
"""Sum two or more attribute refs and/or expressions (associative-safe).
Avoids the Python ``a + b + c`` left-association trap with mixed
:class:`~tg_model.model.refs.AttributeRef` and :class:`~unitflow.expr.expressions.Expr`.
Parameters
----------
*terms
Two or more refs and/or unitflow expressions.
Returns
-------
Any
Left-folded unitflow expression after :func:`as_expr_leaf` on each term.
Raises
------
ValueError
If fewer than two terms are passed.
Examples
--------
``model.attribute("total_kg", unit=kg, expr=sum_attributes(a, b, c))``
"""
if len(terms) < 2:
raise ValueError("sum_attributes requires at least two terms")
acc = as_expr_leaf(terms[0])
for t in terms[1:]:
acc = acc + as_expr_leaf(t)
return acc