Query API
New in v0.11.0
syside.query answers questions about a loaded model in one call each: which
element has this name, which parts specialize this definition, what does this
element contain, which constraints does this instance violate. It sits on top of
the syside element classes you already use, so a script can adopt it one
function at a time; nothing it returns needs a lock, a callback or a cast.
Two companion packages arrived with it. syside.evaluation checks the
assert constraint statements in a model against the instances that bind
values, and syside.testing turns modelling rules into pytest tests whose
failure messages name the offending elements.
Try it in five minutes
Given the model from the extract parts example,
listing every part that is Electrical takes a lookup and a filter:
def show_parts_of_type(model: syside.Model, part_type: str) -> None:
# Look the definition up once, then ask each part whether it
# specializes it. `specializes` follows the whole heritage chain, so
# a part typed by a subtype of `part_type` is found as well.
definition = query.find_by_name_and_type(
model, part_type, syside.PartDefinition
)
assert definition is not None, f"no part definition named {part_type}"
for part in query.find_elements_of_type(model, syside.PartUsage):
if query.specializes(part, definition):
print("- ", part.name)
find_by_name_and_type returns the
definition or None, already typed as a PartDefinition;
find_elements_of_type returns a
list of every part usage in the model, library elements excluded; and
specializes follows the whole heritage
chain, so a part typed by a subtype of Electrical is found too. The same
function written against the element classes directly walks model.nodes,
iterates part.heritage.elements, and compares declared_name on each; see it
side by side in Rewrite a script with syside.query.
Why use it
Every result is a plain Python value. A
list,set,bool, scalar orNone, never aLazyIteratorto drain or a callback to pass tofor_each. Results can be indexed, sliced, passed tolen()and iterated more than once.One name per question.
contents,containers,features_of,redefines,variants: the function is named for what you want, not for the accessor that happens to hold it.Repeated lookups stay cheap. Build a
NameIndex,TypeIndexorMetadataIndexonce and pass it asindex=to make each later lookup a dictionary read. An index changes a query’s cost, never its result.Read-only by construction. No function in
syside.querymodifies the model, so a report or a check written with it cannot corrupt what it reads.
The element classes remain the way to create and edit a model; syside.query
does not replace them, it replaces the loops you wrote around them.
Where to go next
Rewrite a script with syside.query – Two example scripts, each shown against the element classes and again with
syside.queryCheck asserted constraints from Python – Evaluate every
assert constraintagainst the instances that bind values, and read the verdictsTest a model with pytest – Write modelling rules as pytest tests that name the elements breaking them
The complete list of functions, with the cost of each, is in the
API reference.