Reflection
When developing in Ignition, it is often helpful to take a close look at the data types of objects available in jython, whether those types are imports from Java, or a native Jython types, or some exotic wrapper applied to a particular java object for best behavior in Jython.
These script functions are the successor to
shared.inspect.introspect()
, a workhorse
written in jython that dates back to 2008 and the FactoryPMI
predecessor to Ignition. (It is still available as
inspect.py
if you need it.)
Certain data types are misleading when reflection is executed purely within jython–this set of functions resolves that difficulty.
object()
Plain Java Reflection
The function signature of object()
below triggers generic conversion of
Jython values to Java equivalents, so that reflection occurs with
a native java object where applicable (for the most part).
When jython has wrapped
a generic Java object for the interpreter’s use, this generic
conversion simply yields the original java object, for no surprises.
For native Jython types, you get some subclass of PyObject
as it
appears to native java code. These are rather busy and the output
is long even when verbose
is False
.
system.reflect.object(javaObject, verbose=False)
returns String
javaObject | Any java object to be examined in detail with reflection. |
verbose | A boolean flag to trigger a complete walk of the subject's java class hierarchy, reporting non-public methods and fields, and where possible, the current (possibly abbreviated) value of those fields. |
coerced()
Coerced Java Reflection
When jython is passing objects as arguments to java methods, it it naively selects a method overload based on number of parameters, then attempts to coerce the supplied arguments to the data types needed by the java method. Some of the coercion decisions are complex, and the plain java introspection above may not correspond to what really happens in specific cases.
If you know a java method’s parameter types, you can have the jython object coerced into the target type just as if it were being handed to that method by the interpreter.
system.reflect.coerced(pyObject, class, verbose=False)
returns String
pyObject | Any jython object that you might supply to a java method and for which you need to examine the coerced form in detail, via reflection. |
class | A java data type (instance of Class<?> ) that corresponds to the
method parameter type. You can use reflection before this call to
obtain the correct type. |
verbose | A boolean flag to trigger a complete walk of the subject's java class hierarchy, reporting non-public methods and fields, and where possible, the current (possibly abbreviated) value of those fields. |
pyObject()
Jython PyObject Reflection
Jython’s own objects’ structure is hidden from jython scripts as implementation details. Some of those implementation details, particularly of wrapper types, may be important. The jython object itself, and its multiple inheritance hierarchy (in method resolution order) can be examined in detail.
system.reflect.pyObject(pyObject, verbose=False)
returns String
pyObject | Any jython object to be examined in detail with reflection. |
verbose | A boolean flag to trigger reporting of the current (possibly abbreviated) attribute values. |
asThrowable()
Jython Exception Conversion
Jython’s native exceptions do not play well with Java’s
Throwable
heirarchy. In particular, Jython exceptions cannot be passed to
loggers to produce clean tracebacks, and cannot be added to an
outer Java exception as a cause
.
To correct these issues, the following function takes a Jython
Exception, or traceback from the environment, and constructs a
Java-friendly Throwable
instance (really a RuntimeException
).
The resulting object is very similar to the PythonAsJavaException
class provided by Automation Professionals’ later.py
utility
script, but with two key enhancements:
-
Serializable, due to its pure Java implementation, and
-
Includes full script module paths where available.
system.reflect.asThrowable(e, tb)
returns PyAsJavaException
system.reflect.asThrowable(tb, cause)
returns PyAsJavaException
e | A Jython Exception (any subclass of BaseException ). |
tb | A Jython Traceback object, or None . If not
supplied, it will be extracted from the thread context. |
cause | Any Java Throwable object to be attached as the cause
of the outer exception's traceback. This form of asThrowable()
will return just this cause if there is no traceback supplied nor in the
jython environment. |
getModulePath()
Ignition’s project library scripts do not have reliable access
to their own full path via python’s normal __package__
and
__name__
module globals. However, Ignition does put this full
path into a virtual file name for the module, which can be
extracted from Jython’s interpreter frame.
A determined coder can raise a dummy Jython exception in order to gain access to the necessary frame, but this function does it without the exception overhead.
system.reflect.getModulePath()
returns String