use python Engine SDK to implements 2 inputs and 2 outputs for plugin. Please help me !
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Notify Moderator
Dear @tlarsen7572 and all, hello !
I am now trying to write a plugin using the old python Engine SDK. This plugin does not require a GUI for interaction. It has 2 input anchors, S anchor and I anchor, and 2 output anchors, L anchor and R anchor. The purpose of this plugin is to achieve the effect of automatically switching the direction of the workflow. The idea is to decide whether to output the data of I anchor to L anchor or R anchor based on the bool value input by S anchor. In short, it can only be output to one of the anchors, and the other one will not output anything at the same time (Like Detour tool but it is automation).
***Config.xml***
<InputConnections>
<Connection Name="Switch" AllowMultiple="False" Optional="False" Type="Connection" Label="S"/>
<Connection Name="Input" AllowMultiple="False" Optional="False" Type="Connection" Label="I"/>
</InputConnections>
<OutputConnections>
<Connection Name="Left" AllowMultiple="False" Optional="False" Type="Connection" Label="L"/>
<Connection Name="RecordCount" AllowMultiple="False" Optional="True" Type="Connection" Label="o"/>
<Connection Name="Right" AllowMultiple="False" Optional="False" Type="Connection" Label="R"/>
</OutputConnections>
I am a Python newbie. Could you please help me correct the errors and requirements of Line 58, Line 178, Line 206? Thank you!
Please see the notes in code.
import AlteryxPythonSDK as Sdk
import xml.etree.ElementTree as Et
from collections import deque
class AyxPlugin:
"""
Implements the plugin interface methods, to be utilized by the Alteryx engine to communicate with a plugin.
Prefixed with "pi", the Alteryx engine will expect the below five interface methods to be defined.
"""
def __init__(self, n_tool_id: int, alteryx_engine: object, output_anchor_mgr: object):
"""
Constructor is called whenever the Alteryx engine wants to instantiate an instance of this plugin.
:param n_tool_id: The assigned unique identification for a tool instance.
:param alteryx_engine: Provides an interface into the Alteryx engine.
:param output_anchor_mgr: A helper that wraps the outgoing connections for a plugin.
"""
# Default properties
self.n_tool_id = n_tool_id
self.alteryx_engine = alteryx_engine
self.output_anchor_mgr = output_anchor_mgr
# Custom properties
self.is_initialized = True
self.switch_input = None
self.data_input = None
self.left_anchor = None
self.recordcount_anchor = None
self.right_anchor = None
def pi_init(self, str_xml: str):
"""
Handles configuration based on the GUI.
Called when the Alteryx engine is ready to provide the tool configuration from the GUI.
:param str_xml: The raw XML from the GUI.
"""
# Getting the dataName data property from the Gui.html
# There is no need gui for operation.
# Getting the output anchor from Config.xml by the output connection name
self.left_anchor = self.output_anchor_mgr.get_output_anchor('Left')
self.recordcount_anchor = self.output_anchor_mgr.get_output_anchor('RecordCount')
self.right_anchor = self.output_anchor_mgr.get_output_anchor('Right')
def pi_add_incoming_connection(self, str_type: str, str_name: str) -> object:
"""
The IncomingInterface objects are instantiated here, one object per incoming connection.
Called when the Alteryx engine is attempting to add an incoming data connection.
:param str_type: The name of the input connection anchor, defined in the Config.xml file.
:param str_name: The name of the wire, defined by the workflow author.
:return: The IncomingInterface object(s).
"""
# ****** Is the code here correct? ******
# #######################################
if str_type == 'Switch':
self.switch_input = IncomingInterface(self, str_type)
return self.switch_input
elif str_type == 'Input':
self.data_input = IncomingInterface(self, str_type)
return self.data_input
else:
self.display_error_message('Invalid Input Connection')
# #########################
# ****** ??? As above******
def pi_add_outgoing_connection(self, str_name: str) -> bool:
"""
Called when the Alteryx engine is attempting to add an outgoing data connection.
:param str_name: The name of the output connection anchor, defined in the Config.xml file.
:return: True signifies that the connection is accepted.
"""
return True
def pi_push_all_records(self, n_record_limit: int) -> bool:
"""
Handles generating a new field for no incoming connections.
Called when a tool has no incoming data connection.
:param n_record_limit: Set it to <0 for no limit, 0 for no records, and >0 to specify the number of records.
:return: False if there's an error with the field name, otherwise True.
"""
# Tool is not an input tool, so must have an input to process
self.alteryx_engine.output_message(self.n_tool_id, Sdk.EngineMessageType.error, "Input connection required.")
return False
def pi_close(self, b_has_errors: bool):
"""
Called after all records have been processed.
:param b_has_errors: Set to true to not do the final processing.
"""
# Checks whether connections were properly closed.
self.left_anchor.assert_close()
self.right_anchor.assert_close()
def display_error_msg(self, msg_string: str):
"""
A non-interface method, that is responsible for displaying the relevant error message in Designer.
:param msg_string: The custom error message.
"""
self.is_initialized = False
self.alteryx_engine.output_message(self.n_tool_id, Sdk.EngineMessageType.error, self.xmsg(msg_string))
def xmsg(self, msg_string: str):
"""
A non-interface, non-operational placeholder for the eventual localization of predefined user-facing strings.
:param msg_string: The user-facing string.
:return: msg_string
"""
return msg_string
class IncomingInterface:
"""
This class is returned by pi_add_incoming_connection, and it implements the incoming interface methods, to be\
utilized by the Alteryx engine to communicate with a plugin when processing an incoming connection.
Prefixed with "ii", the Alteryx engine will expect the below four interface methods to be defined.
"""
def __init__(self, parent: object):
"""
Constructor for IncomingInterface.
:param parent: AyxPlugin
"""
# Default properties
self.parent = parent
# Custom properties
self.record_copier = None
self.record_creator = None
self.record_count = 0
self.out_records = deque()
self.record_info_in = None
self.record_info_out = None
self.field_index = None
def ii_init(self, record_info_in: object) -> bool:
"""
Handles appending the new field to the incoming data.
Called to report changes of the incoming connection's record metadata to the Alteryx engine.
:param record_info_in: A RecordInfo object for the incoming connection's fields.
:return: False if there's an error with the field name, otherwise True.
"""
if not self.parent.is_initialized:
return False
# Returns a new, empty RecordCreator object that is identical to record_info_in.
self.record_info_in = record_info_in
self.record_info_out = record_info_in.clone()
# Initialize the record copier for the in/out transfer
self.initialize_copier()
if self.parent.alteryx_engine.get_init_var(self.parent.n_tool_id,'UpdateOnly') == 'True':
self.initialize_output()
return True
def ii_push_record(self, in_record: object) -> bool:
"""
Responsible for pushing records out.
Called when an input record is being sent to the plugin.
:param in_record: The data for the incoming record.
:return: False if there's a downstream error, or if there's an error with the field name, otherwise True.
"""
if not self.parent.is_initialized:
return False
# ******The following functions are to be implemented .******
# #######################################
# 1- Because self.switch_input will only have one field column, and this field column always has only one row, the data type is bool.
# 2- so it is necessary to obtain and determine whether this bool value is True or False.
# 3- If it is False, the data of self.data_input (i.e. Connection Name="Input") is output to self.left_anchor, and self.right_anchor does not output anything.
# 4- If it is True, the data of self.data_input (i.e. Connection Name="Input") is output to self.right_anchor, and self.left_anchor does not output anything.
# #########################
# ****** ??? As above******
return True
def ii_update_progress(self, d_percent: float):
"""
Called by the upstream tool to report what percentage of records have been pushed.
:param d_percent: Value between 0.0 and 1.0.
"""
# Inform the Alteryx engine of the tool's progress.
self.parent.alteryx_engine.output_tool_progress(self.parent.n_tool_id, d_percent)
# Inform the outgoing connections of the tool's progress.
self.parent.left_anchor.update_progress(d_percent)
self.parent.right_anchor.update_progress(d_percent)
def ii_close(self):
"""
Called when the incoming connection has finished passing all of its records.
"""
# if the bool value = True , then:
self.parent.alteryx_engine.output_message(self.parent.n_tool_id, Sdk.EngineMessageType.info, self.parent.xmsg("「■」Bypass is Action! ---||"))
# Make sure that the recordcount anchor is closed.
self.parent.recordcount_anchor.close()
# Close outgoing connections.
self.parent.left_anchor.close()
self.parent.right_anchor.close()
def initialize_copier(self):
# Creating a new, empty record creator based on record_info_out's record layout.
self.record_creator = self.record_info_out.construct_record_creator()
# Instantiate a new instance of the RecordCopier class.
self.record_copier = Sdk.RecordCopier(self.record_info_out, self.record_info_in)
# Map each column of the input to where we want in the output.
for index in range(self.record_info_in.num_fields):
# Adding a field index mapping.
self.record_copier.add(index, index)
# Let record copier know that all field mappings have been added.
self.record_copier.done_adding()
def initialize_output(self):
# Lets the downstream tools know what the outgoing record metadata will look like, based on record_info_out.
self.parent.left_anchor.init(self.record_info_out)
self.parent.right_anchor.init(self.record_info_out)
- Labels:
-
Custom Tools
-
Developer
-
Python
-
SDK