AP-25704: add inactive output support for Python nodes#92
AP-25704: add inactive output support for Python nodes#92
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a first-class “inactive output” marker for Python-based KNIME nodes and wires it through the Python↔Java port conversion layer so nodes can explicitly mark specific output slots as inactive.
Changes:
- Add
knext.InactivePortsentinel and document its use inconfigure()/execute(). - Map the sentinel to/from KNIME’s
InactiveBranchPortObject/InactiveBranchPortObjectSpecin both the Python backend launcher and Java port type registry. - Add Python and Java tests covering spec/object conversion and proxy behavior while preserving output arity.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
org.knime.python3.nodes/src/main/python/knime/extension/nodes.py |
Adds InactivePort sentinel + API doc updates for returning inactive outputs. |
org.knime.python3.nodes/src/main/python/knime/extension/__init__.py |
Re-exports InactivePort on the public knime.extension surface. |
org.knime.python3.nodes/src/main/python/_node_backend_launcher.py |
Converts inactive specs/objects between Python marker and KNIME inactive port types (by class name). |
org.knime.python3.nodes/src/main/java/org/knime/python3/nodes/ports/PythonPortTypeRegistry.java |
Adds Java-side conversion shortcuts for inactive port object/spec. |
org.knime.python3.nodes/src/main/java/org/knime/python3/nodes/ports/PythonPortObjects.java |
Introduces Java-side Python wrapper singletons for inactive port object/spec. |
org.knime.python3.nodes.tests/src/test/python/unittest/test_knime_node_backend.py |
Adds unit tests for inactive conversions and proxy output arity. |
org.knime.python3.nodes.tests/src/test/java/org/knime/python3/nodes/ports/InactivePortConversionTest.java |
Adds Java unit tests for inactive conversions. |
| Either a single spec, or a tuple or list of specs. The number of specs | ||
| must match the number of defined output ports, and they must be returned in this order. | ||
| Alternatively, instead of a spec, a knext.Column can be returned (if the spec shall | ||
| only consist of one column). | ||
| only consist of one column). Return `knext.InactivePort` for an output slot to | ||
| mark that port inactive. |
There was a problem hiding this comment.
The docstring only describes returning knext.InactivePort for outputs, but the backend also converts inactive incoming port specs/objects to knext.InactivePort (so *inputs in configure() / execute() can be this marker when an upstream branch is inactive). Consider documenting this input behavior as well, so node authors know they may need to handle/forward inactive inputs.
There was a problem hiding this comment.
Interesting remark. Are nodes executed or configured at all if they have inactive input ports? If not, then no need to explain that
cdb68f6 to
488e201
Compare
|
chaubold
left a comment
There was a problem hiding this comment.
If I'm not mistaken then we can achieve the same thing on the Java side without additional if blocks in all the conversion methods, by registering a built-in converter, right?
| } | ||
|
|
||
| if (spec instanceof InactiveBranchPortObjectSpec) { | ||
| return PythonInactivePortObjectSpec.INSTANCE; |
There was a problem hiding this comment.
why do we add an extra check here instead of registering a converter for the inactive branches and put that into m_builtinPortObjectSpecConverterMap?
| var instance = InstanceHolder.INSTANCE; | ||
| String specClassName = pythonSpec.getJavaClassName(); | ||
| if (InactiveBranchPortObjectSpec.class.getName().equals(specClassName)) { | ||
| return InactiveBranchPortObjectSpec.INSTANCE; |
There was a problem hiding this comment.
same here, it could be covered by the code below if there was an entry in m_builtinPortObjectSpecConverterMap?
| } | ||
|
|
||
| if (portObject instanceof InactiveBranchPortObject) { | ||
| return PythonInactivePortObject.INSTANCE; |
There was a problem hiding this comment.
this could also work via the m_builtinPortObjectConverterMap, right?


No description provided.