Using classes from a Python plugin in another Python plugin

I’m implementing support for some measurement equipment in OpenTAP and I’d like to have the following structure:

  • MyBasePlugin that contains MyBaseInstrument class and a test step that accepts instruments of MyBaseInstrument type
  • MyPlugin1 that containsMyInstrument1 class derived from MyBaseInstrument
  • MyPlugin2 that containsMyInstrument2 class derived from MyBaseInstrument

That works fine in case all classes are located in the same plugin, but if I try to do it as described above, I’m facing some issues. They can be reproduced using PluginExample:

clr.AddReference("Python.PluginExample")

import Python.PluginExample as PluginExample
BasicInstrument = PluginExample.BasicInstrument

@Attribute(BrowsableAttribute, True)
class MyInstrument1(BasicInstrument):
    pass

Building causes the following error:

The type or namespace name 'BasicInstrument' does not exist in the namespace 'Python' (are you missing an assembly reference?)
'MyInstrument1.load_instance()': no suitable method found to override
The name 'load' does not exist in the current context
'MyInstrument1' does not contain a definition for 'getValue' and the best extension method overload 'PythonWrapperExtensions.getValue(IPythonWrapper, string, Type)' requires a receiver of type 'IPythonWrapper'
'MyInstrument1' does not contain a definition for 'setValue' and the best extension method overload 'PythonWrapperExtensions.setValue(IPythonWrapper, string, object)' requires a receiver of type 'IPythonWrapper'
'MyInstrument1' does not contain a definition for 'getValue' and the best extension method overload 'PythonWrapperExtensions.getValue(IPythonWrapper, string, Type)' requires a receiver of type 'IPythonWrapper'
'MyInstrument1' does not contain a definition for 'setValue' and the best extension method overload 'PythonWrapperExtensions.setValue(IPythonWrapper, string, object)' requires a receiver of type 'IPythonWrapper'
'MyInstrument1' does not contain a definition for 'Call' and the best extension method overload 'PythonWrapperExtensions.Call<double>(IPythonWrapper, string, params object[])' requires a receiver of type 'IPythonWrapper'

Just as an experiment, if I do BasicInstrument = TapPlugin(PluginExample.BasicInstrument) instead, it builds successfully and MyInstrument1 can be added in the Editor. Although it shows some errors and the properties of BasicInstrument are of course gone.

Is there a way to do what I’m trying to do?

Update: probably the proper way to import BasicInstrument is from Python.PluginExample.BasicInstrument import BasicInstrument (i.e. including the namespace), though it doesn’t seem to resolve the issue.

Any input is highly appreciated.

In this version of the python plugin, the BasicInstrument class has two implementations, one C# implementation which is what you are currently using and one python implementation.
I believe you should be able to import PluginExample and use PluginExample.BasicInstrument (the python implementation), not Python.PluginExample.BasicInstrument, which is the C# class.

@rolf_madsen Thanks for the input. I can import directly from Python indeed, but it will be a different class therefore all inheritance will be lost.

Editor will load Python.PluginExample.BasicInstrument whereas my implementation will derive from PluginExample.BasicInstrument so these two instruments won’t be interchangeable.

Could you give me some insights on why it’s not possible to import from DLL built in OpenTAP? Is it a known limitation?

What do you mean that inheritance will be lost?

I think that you are right that these two class might not alias to eachother, but you might be able to use interfaces to get around that. Anyway, you are saying that if you have a test ste[ that has a PlugnExample.BasicInstrument property and an instrument which is a MyPlugin.BasicInstrument2, it cannot be assigned there?

If the test step is located in PluginExample it will expect Python.PluginExample.BasicInstrument so it won’t be possible to use MyPlugin1.BasicInstrument as it derives from a different class, namely PluginExample.BasicInstrument.

If the test step is located in MyPlugin1, it will accept MyPlugin1.BasicInstrument but won’t accept Python.PluginExample.BasicInstrument that will be loaded from PluginExample.

Ok, I thought we supported that., but maybe only within one python module.

Anyway, again I am happy to say that this is fixed in 3.0, so its getting fixed. :slight_smile:

2 Likes