SCR307: redefined-event-handler
Event script file that rebinds its handler to something Ignition cannot call
| Code | SCR307 |
| Name | redefined-event-handler |
| Category | Scripts (SCR) |
| Default severity | error |
| Enabled by default | yes |
| Fix available | no |
| ign-lint equivalent | none |
What it does
Section titled “What it does”Checks the module-level code after the function of a gateway timer, tag
change, message handler, startup, shutdown or update script file, or of a
WebDev handler. Ignition compiles the file under its canonical header
(def handleTimerEvent():, def handleMessage(payload):, ...), runs the
module code, then looks the handler up by name and calls it with the
canonical arguments, by position. So the last module-level binding of
the name is what runs. The rule reports when that binding is certainly
one Ignition cannot call:
- a
def(orlambda) that cannot take the canonical number of positional arguments, such asdef handleTimerEvent(event):after the header: every event fails withTypeError: handleTimerEvent() takes exactly 1 argument (0 given); - a value that is not callable (
handleTimerEvent = None, a number, a string, a list, tuple, dict or set display or comprehension): Ignition reportsThe function 'handleTimerEvent' is not defined. A comparison, an operator, a call or a backquote is not followed: each runs code that may return a function (__eq__may return a lambda, and Jython then calls it).True,FalseandNonecount only where they are Jython's builtins: all three are names a module can rebind (True = lambda: 7,import x as None); del handleTimerEvent: the same.
Only bindings at module level that always run are followed: one inside
an if, a loop, a try or a with, an import, a class, any other value,
exec or import * make the outcome unknown, and nothing is reported.
So does any binding of the name that the module-level statements do not
show, found from every scope: a global declaration of the name in a
function or class (also in the handler itself, which module code may
call), a list comprehension at module level whose variable is the name
(Python 2 comprehensions leak it), exec, import * or a write through
globals() or vars() in any scope, and code that reaches a frame or
the interpreter. Bindings that stay in their scope (a local of a
function, a class attribute, the variable of a generator expression or
of a comprehension inside a function) do not matter. Parameter names do
not matter (Ignition passes the arguments by position), and defaults or
*args that make the call fit are fine.
Verified on an Ignition 8.3.3 gateway for timer, tag change, message,
startup, shutdown and update scripts and WebDev handlers. Scheduled
scripts run their first definition whatever is bound later, so for them
only del is reported (the script then fails to load with a
NameError). Perspective session and page events and Vision client
events are not checked.
Why is this bad?
Section titled “Why is this bad?”The handler never runs. The error is logged on the gateway (for timers
only the first time; later ones are logged at debug level), and for a
message handler the caller of system.util.sendRequest gets the error.
Example
Section titled “Example”def handleTimerEvent(): poll()
def handleTimerEvent(event): poll()Use instead:
def handleTimerEvent(): poll()Generated from the rule metadata by iglint generate-docs; iglint rule SCR307 prints the same page in the terminal. Source: docs/rules/SCR307.md.