Python SDK Serializer error

I am getting errors of this type for properties on my step. The errors occur when the step is added to the test plan

Serializer ; Error ; Unable to serialize property ‘iteration’.
Serializer ; Debug ; PythonException: <method ‘get’ of ‘dict’ objects> returned a result with an exception set
Serializer ; Debug ; File “C:\Users\PRODCON2\AppData\Local\Programs\Python\Python310\lib\weakref.py”, line 453, in get
Serializer ; Debug ; return self.data.get(ref(key),default)
Serializer ; Debug ; File “”, line 90, in get
Serializer ; Debug ; at Python.Runtime.PythonException.ThrowLastAsClrException()
Serializer ; Debug ; at Python.Runtime.PyObject.GetAttr(String name)
Serializer ; Debug ; at Python.Runtime.PythonDerivedType.InvokeGetProperty[T](IPythonDerivedType obj, String propertyName)
Serializer ; Debug ; at lambda_method(Closure , Object )
Serializer ; Debug ; at OpenTap.Plugins.ObjectSerializer.Serialize(XElement elem, Object obj, ITypeData expectedType)
Serializer ; Debug ; Inner PythonException: unhashable type
Serializer ; Debug ; Exception caught at:
Serializer ; Debug ; at Void Serialize(System.Xml.XmlWriter, System.Object)
Serializer ; Debug ; at Void Serialize(System.IO.Stream, System.Object)
Serializer ; Debug ; at Void Save(System.IO.Stream)
Serializer ; Debug ; at Void d(System.Threading.Tasks.Task)
Serializer ; Debug ; …

The step is written in Python, and the property that is throwing the error is declared as:

iteration = property(OpenTap.Input[Decimal], None)
.add_attribute(Browsable(False))

where Decimal is a C# System.Decimal type. In init() the property is initialized similarly:

self.iteration = OpenTap.InputDecimal

These errors occur for other similar properties as well. What is this error saying and is there a way to fix this serialization error?

I wonder why it claims it is an ‘unhashable’ type. Seems perfectly hashable to me.

  • Does this issue reproduce with Input?
  • Are you initializing iteration in the constructor of your class? e.g. self.iteration = OpenTap.Input[Decimal]()?

After some investigation it appears to impact properties declared with C# types. Including Int32, Decimal and Duts. It seems to happen when these properties are parameterized.

We have also determined that the failure first occurs after the init runs (the step is added to the test plan) and it isn’t consistent. Adding one step may not throw any errors, but adding multiple of the same step usually guarantees these errors will generate. Additionally, the errors are not always shown by the step that has just been added; often it is a step that was added previously that the error occurs in.

Below you can see one of the errors that popped up
image

An additional note is it happens in 9.19.5+ and doesn’t happen in 9.18.5

I have made a simple example that will fail when adding several of “Fancy Plan Step”

import opentap
from opentap import attribute, property

import OpenTap
from OpenTap import *
from OpenTap.Plugins import BasicSteps
from System import Int32

@attribute(OpenTap.Display("Fancy Delay", "", Groups=["Some Group", "Step"]))
class FancyDelay(BasicSteps.DelayStep): 
    FancyTime = property(Int32, 0)
    
    def __init__(self):
        super(FancyDelay, self).__init__() 

@attribute(OpenTap.Display("Fancy Plan Step", "", Groups=["Some Group", "PlanStep"]))
class FancyPlanStep(BasicSteps.SequenceStep): 
    def __init__(self):
        super(FancyPlanStep, self).__init__() 
        
        timesweep    = BasicSteps.SweepParameterStep()
        delaystep       = FancyDelay()

        self.ChildTestSteps.Add(timesweep)
        timesweep.ChildTestSteps.Add(delaystep)

        member = OpenTap.TypeData.GetTypeData(delaystep).GetMember("FancyTime")
        OpenTap.ParameterExtensions.Parameterize(member, timesweep, delaystep, "FancyTime")

        for i in range(10):
            sweepRow = OpenTap.Plugins.BasicSteps.SweepRow()
            sweepRow.Enabled =  True
            sweepRow.Loop = timesweep
            sweepRow.Values.Add("FancyTime", i)
            timesweep.SweepValues.Add(sweepRow)

    def Run(self):
        super().Run()

The error I am getting is

1 Like

Ok. To me it seems like there is an issue with programatically adding a step to a sweep inside of a constructor.

Did you notice it in other scenarios as well?

1 Like

If I adjust the code so that the steps are added by a button instead it still causes the issue. It doesn’t always happen the first time but if I add enough of the steps and child steps I will get an issue

Here is the modified code

@attribute(OpenTap.Display("Fancy Plan Step", "", Groups=["Some Group", "PlanStep"]))
class FancyPlanStep(BasicSteps.SequenceStep): 
    def __init__(self):
        super(FancyPlanStep, self).__init__() 
        
    @attribute(Browsable(True))
    @attribute(OpenTap.Display("Add Steps", None))
    @method()
    def add_steps(self):
        timesweep    = BasicSteps.SweepParameterStep()
        delaystep       = FancyDelay()

        self.ChildTestSteps.Add(timesweep)
        timesweep.ChildTestSteps.Add(delaystep)

        member = OpenTap.TypeData.GetTypeData(delaystep).GetMember("FancyTime")
        OpenTap.ParameterExtensions.Parameterize(member, timesweep, delaystep, "FancyTime")

        for i in range(10):
            sweepRow = OpenTap.Plugins.BasicSteps.SweepRow()
            sweepRow.Enabled =  True
            sweepRow.Loop = timesweep
            sweepRow.Values.Add("FancyTime", i)
            timesweep.SweepValues.Add(sweepRow)

    def Run(self):
        super().Run()