Test variable type

Hello,

Is it possible to check if a variable is :

  • dict or DotReferenceJythonMap
  • list or JsonifiableArrayList
    ?
    Thanks

A script can do it:

isinstance(your_object, (dict, DotReferenceJythonMap))

You'll need to import the exotic types you want to test against.

edit:
You might want to use parents of some classes, for example AbstractJythonMap instead of DotReferenceJythonMap. Your call.

Thanks
I've already tried isinstance() but I have a message : DotReferenceJythonMap is not defined.

How can I call DotReferenceJythonMap and AbstractJythonMap ?

As I said:

from com.inductiveautomation.ignition.common.script.abc import AbstractJythonMap

You'll need to search the javadocs to find exactly what you need to import.

1 Like

Better question: why do you feel you need to do this? Duck typing is a better bet than relying on internal class specifics.

1 Like

@PGriffith I don't understand "Duck typing". Do you have an example ?

I try to test PyLong variable too.

Do you mean that below ?

try:
	project_id = value*1
except:
	project_id = None
	
res = device.getList({'project_id':project_id})

if it quacks like a duck, walks like a duck, etc... then you can pass it to any function that accepts a duck.
Or something.

You should try to answer this:

:yawning_face:
SO ...
In my scripts or bindings, I test my variables to deal with unexpected errors. But in Ignition you have a lot of specific variables like JythonMap, PyLong, ...

That's where duck typing comes in.

Let's say your function takes an object and tries to call its .foo() method.
Instead of checking that the object is the type you expected, you can check if it has a method called foo
Basically, you're not asking "are you a duck ?", you're asking "can you quack ?"

5 Likes

Here is what I have been using to test if a variable is a dict like object or list like object (lifted from here):

I'm curious if others have recommendation for better/preferred "Duck typing" methodology to detect a dict like objects or list like objects.

I ran into the issue with DotReferenceJythonMap types when I used a binding on a Perspective view custom property to create a list of dicts. I then tried to reference each dict in other property bindings with a script transform, attempting to merge with other programmatically created dicts. My custom method to merge dictionaries failed in some weird ways due to the DotReferenceJythonMap type.

Here is my previous custom merge function (lifted from here) that uses type checking.

def merge(d1, d2):
	
	import collections 
	
	for k,v2 in d2.items():
		v1 = d1.get(k) # returns None if v1 has no value for this key
		if ( isinstance(v1, collections.Mapping) and 
			isinstance(v2, collections.Mapping) ):
			merge(v1, v2)
		else:
			d1[k] = v2
			
	return d1

Here is my revised custom merge function that uses "duck typing".

def merge_test(d1, d2):
	for k,v2 in d2.items():
		v1 = d1.get(k)
		if ( 'iteritems' in dir(v1) and 'iteritems' in dir(v2) ):
			merge(v1, v2)
		else:
			d1[k] = v2
	return d1

Not sure if my examples are ideal (I welcome feedback) but the thread was light on actual examples so I thought I'd put these out there..

One last note... Notably the system.util.jsonEncode() function does not handle the object type systemcom.inductiveautomation.perspective.gateway.script.DotReferenceJythonMap type, nor does it handle many (any) of the other dict/list like wrapper objects Ignition like to create.

If I understand correctly, the issue stems from the fact that DotReferenceJythonMap doen't support assignments.
What I do is create a new dict from the jython map AND the values I want to add to it

dict(jython_map, **new_values)

Let's say I wanted to grab a list of objects from a perspective property, and add 'forty_two': 42 to each of those objects, it would look like this (assuming this is a script transform and value is the list referenced by a property binding):

return [
	dict(
		row,
		**{'forty_two': 42}
	) for row in value
]
1 Like

Use python's builtin hasattr() function instead of using dir(). The latter is rather expensive in comparison.

2 Likes