How to check type of PyRow

I'm trying to do some parameter validation checking and I have a parameter that could be a string or it could be a row from a dataset. Printing the type of object gives me:

<type 'com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities$PyDataSet$PyRow'>

But if I try to check it within a script via:


from com.inductiveautomation.ignition.common.script.builtin.DatasetUtilities import PyDataset

if type(myParam) is DatasetUtilities.PyDataSet.PyRow:

, I get an error saying:

AttributeError: type object 'com.inductiveautomation.ignition.common.script.bui' has no attribute 'PyRow'

Does type() not go only 1 level deep? Is there any other method to check if a dataset row was passed as a parameter?

... import PyDataset
if type(myParam) is DatasetUtilities.PyDataSet.PyRow:

Should be:

... import PyDataset
if type(myParam) is PyDataSet.PyRow:

Though I'd argue this is a bit of an antipattern - you should probably check if it's explicitly a string first, then check it's iterable in any form, and then bail if you can't handle it, to be more "Pythonic".

Or you could import and use com.inductiveautomation.ignition.common.PyUtilities.isSequence - which will return True for sequence-like things but not Python strings.

1 Like

I still get the same error. I tried different combinations of the import and the comparison of the type. no dice.

I do check if string first, but also wanted to explicitly check if it was a row. Let me try doing the isSequence to see if that works.

Update: the isSequence worked.

However, is there a way to check the type of object all the way down to the PyRow level?

This (surprisingly to me) seems to not be possible. It's probably due to the weird nature of PyRow - it's a Java nested, inner class of a static nested class of a regular class. You can import PyDataSet directly, but it seems like PyRow, even though it's public, is not visible to Jython at all.

EDIT:
Actually, I think it's because PyDataSet now explicitly tells Jython it's a "Python object", so it's not exposed to further reflection from Jython, and PyDataSet doesn't attempt to expose PyRow explicitly.

Perhaps consider ditching PyDataset for v8.3, and instead supplying a deliberate adapter that just wraps all Dataset implementations with the desired jythonic functionality. Similar to the way jython wraps all java.util.Map<> implementations with dictionary-like behaviors. Registered with the interpreter so it always works.

Then every Dataset is always a Dataset, back and forth through all .py2java() and .java2py() implicit operations, but always has the jythonic behaviors in jython. PyRow can then be a top-level class instantiated as needed by the adapter.

4 Likes

It's on my list of things to do. My concern is that it might end up breaking behaviors in some subtle way, but I definitely prefer it to the current split approach.

1 Like

Another approach would be to have the Dataset interface implement List<DatasetRow> via default methods, then have the new DatasetRow class implement List<Object>, plus inject the item getters (and maybe attribute getters) to mimic current PyRow behavior.

Then PyDataset could be deprecated.

Shouldn't it be isinstance(myParam, PyDataSet.PyRow) ?
I was always told that using type(x) to check for types is a bad practice.

Also, if you do "reunite" datasets and pyDatasets for 8.3 I'll be very happy :smiley:

1 Like

I tried isinstance() but it gave the same error regarding PyRow.