Day 2 - printing of attributes for "Reindeer" - how to handle enumerated values?

Hi!

I tried to extract all attributes from the example, and it works for “SantaSleigh”, when I call find_element_by_name, it then prints (see code snippet below)

rudolph.energyLevel = 200.0

But when I try to do the same for “Reindeer” then it fails, because the noseColor attribute is referencing an enumeration, which does not seem to be handled as a part.feature_value_expression, so in the following code, the assert is triggered….

# print if it is an attribute
if type(part) == syside.AttributeUsage:
    print ("-- at ", part.name)
    expression = part.feature_value_expression
    assert expression is not None
    evaluation = syside.Compiler().evaluate(expression)
    if evaluation[1].fatal:
        print(f"Error evaluating {part.name}")
    else:
         value = evaluation[0]
    print(" " * part_level, f"{part.owner.name}.{part.name} = {value}")

So, can you show me how to handle the case of the enumeration?

Regards,
Marcel

Hello, Marcel.

From this code snippet I think that you simply encounter the attribute noseColor : Color; that belongs to the part def Reindeer - and it does not have a feature value expression. In the case of noseColor = Color::red; the feature noseColor is Color::red, but in the case of noseColor : Color the feature is typed by the enumeration, but is not equal to a specific color.

As for why the code is failing - you are asserting that part.feature_value_expression is not None.
Assuming that you are looping through different values of part, you could do

for part in some_list:
    if type(part) == syside.AttributeUsage:
        print ("-- at ", part.name)
        expression = part.feature_value_expression
        if expression is None:
            print(f"Encountered an attribute {part.name} without a feature value expression")
            continue
        assert expression is not None
        evaluation = syside.Compiler().evaluate(expression)
        if evaluation[1].fatal:
            print(f"Error evaluating {part.name}")
        # If the feature value expression evaluates to 
        # an enumeration - we want to print its name
        elif isinstance(evaluation[0], syside.EnumerationUsage):
            value = evaluation[0].name
        else:
            value = evaluation[0]
        print(" " * part_level, f"{part.owner.name}.{part.name} = {value}")

This way you can verify that the issue is what I think it is, and you jump over the attribute without a value expression without breaking the rest of the code. Hope that helps.

On a somewhat related note, we have realized that the example model is a bit confusing - the noseColors are references rather than attributes in the “SantaSleigh”, which is why your code only outputs

rudolph.energyLevel = 200.0

and skips over the different colors assigned to noseColor, but breaks in the Reindeer.

To make it more straightforward, we have updated the model to leave the noseColor as an attribute even after the redefinition (see advent-of-sysml-v2/lesson02/models/L02_SantaSleigh.sysml at main · sensmetry/advent-of-sysml-v2 · GitHub).

Hope that cleared things up!