Script function execution context

Hi all,
is there a way to know which is the execution context of a python script function? Say I have a function in a shared script library:

def foo():
  pass

That function will be called in my project by:

  1. a gateway tag event
  2. a button click
    As far as I understand, in case (1) the running context will be the gateway; in case (2) it will be the client. Well: is there a way inside foo() to know where the function is running? I cannot find any scripting function that does it.

Thanks in advance

Try using system.util.getSystemFlags(). Or you can check for the existence of functions that are scope-specific:

# invokeLater doesn't exist in gateway scopes
if hasattr(system.util, 'invokeLater'):
    # Do Client stuff
    pass
else:
    # Do Gateway stuff
    pass

Thanks pturmel, I will go for the second option, since, after some tests, system.util.getSystemFlags() just works on the Client.

1 Like

Hi pturmel, after some more palying around, I got stuck on another problem: now my function looks similar to

def foo():
  if not isClientScope():
    #force clients to open a specific popup by sending a message
    system.util.sendMessage(....)
  else:
    #open a specific popup directly, because this is Client scope
    system.nav.openWindow(......)

where isClientScope() implements the code you suggested to find if the function is running in the client or in the gateway scope.
When this function is run from a button click event, no problem. Whereas if it gets executed on a tag value changed event I get the following error:
AttributeError: 'com.inductiveautomation.ignition.common.script.Imm' object has no attribute 'gui'.
As of my understading, Ignition is trying to load a module that is not defined in the Gateway scope: is there no way to tell Ignition not to consider the else branch?
Thanks in advance

SOLUTION
First off I found that the error message was due to another module that is loaded when executing foo(). In that module I placed the following instruction in the global space:
confirmBox=system.gui.confirm
to have a shortcut to the system.gui.confirm function. That was not good for Ignition. Moreover I had to place the call to system.nav.openWindow in a separate function, which I call from the else branch.
Now it’s working pretty good.
Could you please confirm that this is a good practice, or do you have anything better to suggest me from your valuable experience?
Thanks, regards

I try to break up my script modules so that truly generic functions that I want to use from any scope are separate from functions that need any gui or nav or similar client/designer-only features. That also means import never blows up.

2 Likes

If you want an easier way to detect scope (system.util.getSystemFlags() does not give you a way to know for sure that you are running on the gateway. What if there is a new scope in the future?), give this a whirl.

from com.inductiveautomation.ignition.common.model import ApplicationScope
scope = ApplicationScope.getGlobalScope()
if ApplicationScope.isClient(scope):
	print "c"

if ApplicationScope.isDesigner(scope):
	print "d"

if ApplicationScope.isGateway(scope):
	print "g"

3 Likes

I will give it a try. Thanks!

You are right pturmel. Unfortunately this time it is not so easy to structure the application as I would like: I'm porting a Citect SCADA software to Ignition and scripting files there were a big mix of anything came to the mind of the programmer! Particularly there are some scripting files with more then 100 case in a select ... case construct, each of them doing something different, from handling a tag event to handling a UI button click! So sad is it this time!!

That sounds like a terrible idea. Why not fix the code and build it properly?

1 Like

You are so right, Kyle_Chase! Short answer: very short of time. Short answer nr 2: no one has the big picture of the old software in mind - it was developed over almost 10 years, adding features as requested, more then 1 developer involved, someone no more there … I’ll try to do my best!