Pretty-printing units

Hello everyone,

I’m working with attributes with values and units, and I’m trying to set the units of an attribute to units from the standard library. It works fine, however the printed output is not nice to read because it uses the name rather than the short name of the units in the standard library.

Consider this model:

package Package {
    private import SI::*;

    attribute acceleration = 1['m/s²'];
}

And this script:

import syside

model, _ = syside.load_model(['model.sysml'])
with model.documents[-1].lock() as doc:
    root_node = doc.root_node
    package: syside.Package = root_node.children.elements[0]

    # Get the units of the acceleration attribute
    accel_attr = package.children.elements[1]
    assert isinstance(accel_attr, syside.AttributeUsage)
    assert accel_attr.name == 'acceleration'

    attr_value = accel_attr.feature_value.value
    assert isinstance(attr_value, syside.OperatorExpression)
    assert attr_value.operator == syside.Operator.Quantity

    value_feature, units_feature = attr_value.children.elements

    units_value = units_feature.feature_value.value
    assert isinstance(units_value, syside.FeatureReferenceExpression)
    units = units_value.referent
    assert isinstance(units, syside.AttributeUsage)
    assert units.name == 'metre second to the power minus 2'
    assert units.short_name == 'm⋅s⁻²'

    # Create a new attribute with the same units
    _, attr2 = package.children.append(syside.OwningMembership, syside.AttributeUsage)
    attr2.declared_name = 'accel2'

    _, quantity_expression = attr2.feature_value_member.set_member_element(syside.OperatorExpression)
    quantity_expression.operator = syside.ExplicitOperator.Quantity

    _, attr2_value_feature = quantity_expression.children.append(syside.ParameterMembership, syside.Feature)
    _, value = attr2_value_feature.feature_value_member.set_member_element(syside.LiteralInteger)
    value.value = 5

    _, attr2_units_feature = quantity_expression.children.append(syside.ParameterMembership, syside.Feature)

    reference_expression: syside.FeatureReferenceExpression
    _, reference_expression = attr2_units_feature.feature_value_member.set_member_element(syside.FeatureReferenceExpression)

    reference_expression.referent_member.set_member_element(units)

    # Print the results
    printer_config = syside.PrinterConfig(line_width=80, tab_width=4)
    printer = syside.ModelPrinter.sysml()
    output = syside.pprint(root_node, printer, printer_config)
    print(output)

The result is as follows:

package Package {
    private import SI::*;

    attribute acceleration = 1 ['m/s²'];
    attribute accel2 = 5 ['metre second to the power minus 2'];
}

As you can see, the newly created attribute has the long name of the acceleration unit.

It’s just cosmetics, however improving this would greatly improve readability.
The solution could be to hard-code using the short name for printing attributes in the units standard library, or maybe to add some way to control printing name vs short name of elements in general.

Greetings,
Jasper

1 Like

Hi, Jasper,

I think an enum NameSelection { Automatic, Longest, Shortest, Regular, Short } could work as a simple solution. I will try to add this for next release but as it is a holiday season, it will likely not be out until next year.

1 Like

Something like that would indeed be a good solution :slight_smile:

Yes of course, no rush! Enjoy the holidays :santa_claus: :christmas_tree:

v0.8.4 added ReferencePrinter that allows customizing synthetic reference output.

Yes thank you for implementing this, works like a charm!