Using `EmbedProperties` attribute in Python

I recently discovered EmbedProperties attribute and I’m very eager to use it as it may help avoid ugly workarounds when sharing properties between steps. However, I’m not completely sure how / whether it’s possible to use it in Python.

I used the following example as a reference:

namespace OpenTap.Plugins.PluginDevelopment
{
    [Display("Embed Properties Attribute Example", Groups: new[] { "Examples", "Plugin Development", "Attributes" },
        Description: "Example step that uses the Embedded attribute for embedding properties from other objects.")]
    public class EmbedPropertiesAttributeExample : TestStep
    {
        /// <summary> This class could be used to share settings between multiple types of test steps. </summary>
        public class EmbeddedClass
        {
            // Here are some example settings:
            [Unit("Hz")]
            public double Frequency { get; set; }
            [Unit("dBm")]
            [Display("Power Level")]
            public double Power { get; set; }
        }

        // This causes the properties A and B to be embedded inside this class from the 
        // perspective of serialization and user interfaces.
        [Display("Embedded Group")] // All settings embedded from EmbeddedClass, will get this name as group.
        [EmbedProperties] //Set Prefix or PrefixOverrideProperty name to control the naming of embedded properties.
        public EmbeddedClass Embedded { get; set; } = new EmbeddedClass();
        
        public override void Run()
        {
            Log.Info($"Frequency: {Embedded.Frequency} Hz, Power: {Embedded.Power}");
        }

        // Resulting XML:
        // <EmbeddedAttributeExample type="OpenTap.Plugins.PluginDevelopment.EmbeddedAttributeExample" Version="1.0.0" Id="6e346cf0-bcdf-48a7-89d9-e20d64c7868d">
        //    <Enabled>true</Enabled>
        //    <Name>EmbeddedAttributeExample</Name>
        //    <ChildTestSteps />
        //    <!-- Notice Frequency and Power has been embedded in the test step settings. -->
        //    <Embedded.Frequency>0</Embedded.Frequency>
        //    <Embedded.Power>0</Embedded.Power>
        // </EmbeddedAttributeExample>
    }
}

And I tried to translate it to a simple example in Python:

@Attribute(BrowsableAttribute, False)
class EmbeddedClass(TestStep): # Inheriting to use AddProperty
    def __init__(self):
        super().__init__()
        self.AddProperty("my_prop", 0, Byte)\
            .AddAttribute(DisplayAttribute, "My Property", "My property description.")

@Attribute(BrowsableAttribute, True)
class MyTestStep(TestStep):
    def __init__(self):
        super().__init__()
        self.AddProperty("embedded", EmbeddedClass(), EmbeddedClass)\
            .AddAttribute(EmbedPropertiesAttribute)\
            .AddAttribute(DisplayAttribute, "Embedded Group")

It’s buildable and I can see the embedded property within MyTestStep but if I try to set my_prop to any value I get Embedded property object owner ("embedded") is null. error.

Is it supposed to work in Python? If yes, can someone spot what I’m doing wrong?

1 Like

I’m sorry to say, but I don’t think the current release of Python can support EmbeddedPropertiesAttribute and I am not sure what happens if you use it.

I have just tested it on the development branch where it works, so the next release should support it.

1 Like

Thanks for checking that. Can’t wait to see the new release for multiple reasons already!

1 Like

I’ll make a post here on the forum when the beta is ready, maybe you could try it out… It would be great if I could get your feedback!

2 Likes