I'm using that but the two tags are different, ones a boolean and ones a PyDocument. There could be more different tags too, I wanted to check the type and treat the value differently.
I found another post that converted the type to a string and then checked for PyDocumentObjectAdapter. That worked but wasn't sure why I needed to do that.
The pythonic way to do this is to use the isinstance() builtin.
import com.inductiveautomation.ignition.common.script.adapters.PyDocumentObjectAdapter as PyDocumentObjectAdapter
if isinstance(tagValue, PyDocumentObjectAdapter):
#do work for document type tag
elif isinstance(tagValue, bool):
#do work for boolean tag
I have seen where sometimes in Jython the builtin doesn't work all the time, so another way you could do this is:
if hasattr(tagValue,'keys'): #or items in the event you support a list and/or dict psuedo type
#do work here for document tag
elif isinstance(tagValue, bool):
#do work here for boolean tag
I tested in the script console and the first option works, so that is the route I would recomend here (since you're getting this back from a tag, scoping shouldn't matter in this instance, but you might want to check)
if len(tagValue.items()) > 0:
# process document tag
Or if is a Gateway Tag Change Script you could something like this:
if event.tagPath.getItemName() == "YourDocumentTagName":
# do work here for document tag
elif event.tagPath.getItemName() == "YourBooleanTagName":
# do work here for boolean tag
If you could explain a bit more how is executed your script it would help us.
I prefer checking the type, but if I need to run code which is agnostic to dicts or lists, then using hasattr to check for items is easier for me to read.
isinstance() is generally the preferred method. I was trying to think on when I had to use hasattr()-- it's been longer than four days, so I'm already in trouble...
IIRC it was having to do with vision charts, and having to dig down until I found what i wanted.
For most applicattions, I agree with what @lrose said.
I tend to use hasattr() when looking for dictionary-like or list-like objects. Because that is what jython itself does (approximately) when trying to boil things down to its own basic types.
That, after all, is what "duck typing" means. Types in jython/python are expected to be compatible based on the common methods exposed, not necessarily on the actual class hierarchy.
I use isintance for type checking primitives in the beginning of a function if not isinstance(param1, int): raise Type Error("blah") but hasattr for objects beause I tend to only care if a specific method is available, which like Phil said is essence of duck typing.
Generally, if I'm checking a type, it came from Java and I'm using more than 1 or 2 attributes.
Other wise, I assume that things are the types I expect and if it fails, I've either made an invalid assumption or there is some other self inflicted error. I can't think of a time when I have needed to check for a primitive type, but then I also control both the front end code and the back end code, and don't have to write functions that are handed to other people who may try to use them in an unintended way.
Yea I can see it both ways here. A lot of my old code is only isinstance. And it ceratinly works fine and I don't mind the strictness tbh given the lack of it otherwise in jython.
But for testing things that require a gateway context can be annoying and not suitable at all in a script console, so you're left modifiying your script, saving it, testing it, checking the gateway logs to see what logged/errored.
Where with hasattr you can test the flow of a function with a
class testclass(object):
def __init__(self):
pass
def methodICareToTest(self, ...):
pass
And now you can at least test the flow much more simply without needing saves, going back and forth to the gateway log.
Again this only really affects java objects that only live on the gateway and perhaps is more a workflow thing than anything else.
Personally as long as I am seeing any checks done on the code, isinstance or hastattr I would be happy that the other person who wrote it knew what they were doing and cared about the work.
For what it's worth, the base Jython object implementation exposes isMappingType and isSequenceType methods directly, e.g.
if myThing.isMappingType():
pass
# or
if myThing.mappingType:
All of our various Java objects that pretend to be Java data structures implement this faithfully.
I would also generally say that 'duck typing' is the way to go over isinstance - from a backwards compatibility standpoint, we would consider the shape of something part of our API contract with you as end users, but would not consider the exact type of something part of our contract, so refactoring (even within minor versions!) could theoretically break isinstance calls where you're importing Ignition types. Plus the issues with classloaders and visibility on the gateway.