{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Open Alteryx XML into a string \n",
    "import polars as pl \n",
    "import xml.etree.ElementTree as ET\n",
    "\n",
    "xml_file_path = \"./SimpleWorkflow/SimpleWorkflow.yxmd\"\n",
    "tree = ET.parse(xml_file_path)\n",
    "root = tree.getroot()\n",
    "\n",
    "xml_string = ET.tostring(root, encoding='unicode')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('1', 'TextInput (1)', '<Node ToolID=\"1\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Column1\" />\\n            <Field name=\"Column 2\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>1</c>\\n              <c>4</c>\\n            </r>\\n            <r>\\n              <c>2</c>\\n              <c>5</c>\\n            </r>\\n            <r>\\n              <c>3</c>\\n              <c>6</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('2', 'AlteryxSelect (2)', '<Node ToolID=\"2\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.AlteryxSelect.AlteryxSelect\">\\n        <Position x=\"186\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <OrderChanged value=\"False\" />\\n          <CommaDecimal value=\"False\" />\\n          <SelectFields>\\n            <SelectField field=\"Column1\" selected=\"True\" type=\"Int64\" size=\"8\" />\\n            <SelectField field=\"Column 2\" selected=\"False\" type=\"WString\" size=\"3\" />\\n            <SelectField field=\"*Unknown\" selected=\"False\" />\\n          </SelectFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSelect\" />\\n    </Node>\\n    ')\n",
      "('3', 'BrowseV2 (3)', '<Node ToolID=\"3\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"318\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_9b8a61f4c39b2e4ea05f98886a386376~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('4', 'TextInput (4)', '<Node ToolID=\"4\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"246\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Column 3\" />\\n            <Field name=\"Column 4\" />\\n            <Field name=\"Ham\" />\\n            <Field name=\"Cheese\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>5</c>\\n              <c>8</c>\\n              <c>z</c>\\n              <c>a</c>\\n            </r>\\n            <r>\\n              <c>6</c>\\n              <c>9</c>\\n              <c>b</c>\\n              <c>d</c>\\n            </r>\\n            <r>\\n              <c>7</c>\\n              <c>10</c>\\n              <c>c</c>\\n              <c>c</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('5', 'AlteryxSelect (5)', '<Node ToolID=\"5\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.AlteryxSelect.AlteryxSelect\">\\n        <Position x=\"426\" y=\"390\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <OrderChanged value=\"False\" />\\n          <CommaDecimal value=\"False\" />\\n          <SelectFields>\\n            <SelectField field=\"Column 3\" selected=\"True\" rename=\"Col_3_renamed\" />\\n            <SelectField field=\"Column 4\" selected=\"False\" />\\n            <SelectField field=\"*Unknown\" selected=\"True\" />\\n          </SelectFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSelect\" />\\n    </Node>\\n    ')\n",
      "('6', 'Formula (6)', '<Node ToolID=\"6\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Formula.Formula\">\\n        <Position x=\"354\" y=\"474\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <FormulaFields>\\n            <FormulaField expression=\"[Count] + 10\" field=\"MoreCount\" size=\"4\" type=\"Int32\" />\\n          </FormulaFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>MoreCount = [Count] + 10\\n</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxFormula\" />\\n    </Node>\\n    ')\n",
      "('7', 'Join (7)', '<Node ToolID=\"7\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Join.Join\">\\n        <Position x=\"522\" y=\"402\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration joinByRecordPos=\"False\">\\n          <JoinInfo connection=\"Left\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <JoinInfo connection=\"Right\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <SelectConfiguration>\\n            <Configuration outputConnection=\"Join\">\\n              <OrderChanged value=\"False\" />\\n              <CommaDecimal value=\"False\" />\\n              <SelectFields>\\n                <SelectField field=\"Right_Ham\" selected=\"True\" rename=\"Right_Ham\" input=\"Right_\" />\\n                <SelectField field=\"Right_Cheese\" selected=\"True\" rename=\"Right_Cheese\" input=\"Right_\" />\\n                <SelectField field=\"Right_Column 3\" selected=\"True\" rename=\"Right_Column 3\" input=\"Right_\" type=\"V_String\" size=\"11\" />\\n                <SelectField field=\"Right_Column 4\" selected=\"True\" rename=\"Right_Column 4\" input=\"Right_\" type=\"Int64\" size=\"8\" />\\n                <SelectField field=\"*Unknown\" selected=\"True\" />\\n              </SelectFields>\\n            </Configuration>\\n          </SelectConfiguration>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxJoin\" />\\n    </Node>\\n    ')\n",
      "('10', 'BrowseV2 (10)', '<Node ToolID=\"10\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"618\" y=\"486\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_c1d268f486209c40bdc02a676a529ee0~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('11', 'Formula (11)', '<Node ToolID=\"11\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Formula.Formula\">\\n        <Position x=\"450\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <FormulaFields>\\n            <FormulaField expression=\"[Engine.TempFilePath]\" field=\"Path\" size=\"1073741823\" type=\"V_WString\" />\\n          </FormulaFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>Path = [Engine.TempFilePath]\\n</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxFormula\" />\\n    </Node>\\n    ')\n",
      "('12', 'Sample (12)', '<Node ToolID=\"12\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Sample.Sample\">\\n        <Position x=\"330\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <Mode>First</Mode>\\n          <N>1</N>\\n          <GroupFields orderChanged=\"False\" />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>First 1</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSample\" />\\n    </Node>\\n    ')\n",
      "('13', 'BrowseV2 (13)', '<Node ToolID=\"13\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"546\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_4d6ee2d9de8fac4095ab55a2bceed63e~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('14', 'DbFileOutput (14)', '<Node ToolID=\"14\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.DbFileOutput.DbFileOutput\">\\n        <Position x=\"702\" y=\"402\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <File MaxRecords=\"\" FileFormat=\"0\">.\\\\SimpleWorkflowOut.csv</File>\\n          <Passwords />\\n          <FormatSpecificOptions>\\n            <LineEndStyle>CRLF</LineEndStyle>\\n            <Delimeter>,</Delimeter>\\n            <ForceQuotes>False</ForceQuotes>\\n            <HeaderRow>True</HeaderRow>\\n            <CodePage>28591</CodePage>\\n            <WriteBOM>True</WriteBOM>\\n          </FormatSpecificOptions>\\n          <MultiFile value=\"False\" />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>SimpleWorkflowOut.csv</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxDbFileOutput\" />\\n    </Node>\\n    ')\n",
      "('15', 'TextInput (15)', '<Node ToolID=\"15\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"330\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Ham\" />\\n            <Field name=\"Cheese\" />\\n            <Field name=\"Count\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>a</c>\\n              <c>a</c>\\n              <c>4</c>\\n            </r>\\n            <r>\\n              <c>b</c>\\n              <c>d</c>\\n              <c>6</c>\\n            </r>\\n            <r>\\n              <c>c</c>\\n              <c>z</c>\\n              <c>7</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('16', 'HamCheeseJoin', '<Node ToolID=\"16\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Join.Join\">\\n        <Position x=\"306\" y=\"198\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration joinByRecordPos=\"False\">\\n          <JoinInfo connection=\"Left\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <JoinInfo connection=\"Right\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <SelectConfiguration>\\n            <Configuration outputConnection=\"Join\">\\n              <OrderChanged value=\"False\" />\\n              <CommaDecimal value=\"False\" />\\n              <SelectFields>\\n                <SelectField field=\"Right_Ham\" selected=\"True\" rename=\"Right_Ham\" input=\"Right_\" />\\n                <SelectField field=\"Right_Cheese\" selected=\"True\" rename=\"Right_Cheese\" input=\"Right_\" />\\n                <SelectField field=\"*Unknown\" selected=\"True\" />\\n              </SelectFields>\\n            </Configuration>\\n          </SelectConfiguration>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name>HamCheeseJoin</Name>\\n          <DefaultAnnotationText>HamCheeseJoin</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxJoin\" />\\n    </Node>\\n    ')\n",
      "('17', 'BrowseV2 (17)', '<Node ToolID=\"17\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"114\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_e692dab3020ec84ebe69a5de3e6990c9~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('18', 'BrowseV2 (18)', '<Node ToolID=\"18\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"198\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_83aac5fa43df8044b1161f8298a2a180~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('19', 'BrowseV2 (19)', '<Node ToolID=\"19\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"294\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_c2ab20e4f5222342bc00e6424dbc38bd~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n  ')\n"
     ]
    }
   ],
   "source": [
    "# Parse out nodes (tool data) into a dict\n",
    "def extract_tool_id_and_contents(xml_string):\n",
    "    root = ET.fromstring(xml_string)\n",
    "    results = []\n",
    "    for node in root.iter('Node'):\n",
    "        tool_type = node.find('GuiSettings').get('Plugin').split('.')[-1]\n",
    "        # print('tool type:',tool_type)\n",
    "        tool_id = node.attrib.get('ToolID')\n",
    "\n",
    "        tool_name = node.find('Properties/Annotation/Name').text\n",
    "        if not tool_name:\n",
    "            tool_name = tool_type + \" (\" + tool_id + \")\"\n",
    "\n",
    "        content = ET.tostring(node, encoding='unicode')\n",
    "        results.append((tool_id, tool_name, content))\n",
    "    return results\n",
    "\n",
    "results = extract_tool_id_and_contents(xml_string)\n",
    "\n",
    "\n",
    "for tool in results:\n",
    "    print(tool)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tool Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def tool_select(col_spec: dict):\n",
    "    \"\"\" Generates select tool code\"\"\"\n",
    "    dynamic_code = \"df_output = df.with_columns(\\n\"\n",
    "    dynamic_code_suffix = ''\n",
    "    for old_name, (new_name, type, selected) in col_spec.items():\n",
    "\n",
    "        if old_name == '*Unknown':\n",
    "            break \n",
    "        \n",
    "        if new_name:\n",
    "            alias = f\".alias('{new_name}')\"\n",
    "            dynamic_code_suffix += f\"df_output = df_output.drop(f'{old_name}')\\n\"\n",
    "        else:\n",
    "            alias = ''\n",
    "\n",
    "        if type is not None:\n",
    "            if 'Int' in type:\n",
    "                cast = f\".cast(pl.{pl.Int64})\"\n",
    "            elif 'String' in type:\n",
    "                cast = f\".cast(pl.{pl.String})\"\n",
    "        else:\n",
    "            cast = ''\n",
    "\n",
    "        if selected != 'False':\n",
    "            dynamic_code += f\"df.select(pl.col(f'{old_name}'){cast}{alias}),\\n\"\n",
    "        else:\n",
    "            dynamic_code_suffix += f\"df_output = df_output.drop(f'{old_name}')\\n\"\n",
    "\n",
    "    dynamic_code += \")\\n\" + dynamic_code_suffix\n",
    "    \n",
    "    return dynamic_code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L: shape: (2, 4)\n",
      "┌──────────┬──────────┬─────┬────────┐\n",
      "│ Column 3 ┆ Column 4 ┆ Ham ┆ Cheese │\n",
      "│ ---      ┆ ---      ┆ --- ┆ ---    │\n",
      "│ str      ┆ str      ┆ str ┆ str    │\n",
      "╞══════════╪══════════╪═════╪════════╡\n",
      "│ 5        ┆ 8        ┆ z   ┆ a      │\n",
      "│ 7        ┆ 10       ┆ c   ┆ c      │\n",
      "└──────────┴──────────┴─────┴────────┘\n",
      "J: shape: (1, 7)\n",
      "┌──────────┬──────────┬─────┬────────┬───────────┬──────────────┬───────┐\n",
      "│ Column 3 ┆ Column 4 ┆ Ham ┆ Cheese ┆ Ham_right ┆ Cheese_right ┆ Count │\n",
      "│ ---      ┆ ---      ┆ --- ┆ ---    ┆ ---       ┆ ---          ┆ ---   │\n",
      "│ str      ┆ str      ┆ str ┆ str    ┆ str       ┆ str          ┆ str   │\n",
      "╞══════════╪══════════╪═════╪════════╪═══════════╪══════════════╪═══════╡\n",
      "│ 6        ┆ 9        ┆ b   ┆ d      ┆ b         ┆ d            ┆ 6     │\n",
      "└──────────┴──────────┴─────┴────────┴───────────┴──────────────┴───────┘\n",
      "R: shape: (2, 3)\n",
      "┌─────┬────────┬───────┐\n",
      "│ Ham ┆ Cheese ┆ Count │\n",
      "│ --- ┆ ---    ┆ ---   │\n",
      "│ str ┆ str    ┆ str   │\n",
      "╞═════╪════════╪═══════╡\n",
      "│ a   ┆ a      ┆ 4     │\n",
      "│ c   ┆ z      ┆ 7     │\n",
      "└─────┴────────┴───────┘\n"
     ]
    }
   ],
   "source": [
    "def tool_join(join_spec: dict, df_L: pl.DataFrame, df_R: pl.DataFrame):\n",
    "    \"\"\" Generates join tool code \"\"\"\n",
    "    # dynamic_code = \"df_output = df_L.with_columns(\\n\"\n",
    "    pass\n",
    "\n",
    "    \n",
    "\n",
    "\n",
    "\n",
    "# Join spec\n",
    "xml_join_tool = results[6][2]\n",
    "join_spec = getConf_Join(xml_join_tool)\n",
    "\n",
    "# Input L: TextInput 4\n",
    "In_L = input_textInput(results[3][2])\n",
    "# Input R: TextInput 15\n",
    "In_R = input_textInput(results[12][2])\n",
    "\n",
    "# print(join_spec)\n",
    "# print(In_L, In_R)\n",
    "\n",
    "\n",
    "## Out L\n",
    "# Column 3\tColumn 4\tHam\tCheese\n",
    "# 7\t        10\t        c\tc\n",
    "# 5\t        8\t        z\ta\n",
    "\n",
    "## Out J\n",
    "# Column 3\tColumn 4\tHam\tCheese\tRight_Ham\tRight_Cheese\tCount\n",
    "# 6\t        9\t        b\td\t    b\t        d\t            6\n",
    "\n",
    "## Out R\n",
    "# Ham\tCheese\tCount\n",
    "# a\t    a\t    4\n",
    "# c\t    z\t    7\n",
    "\n",
    "\n",
    "print(\"L:\", In_L.join(In_R, on=join_spec['joinParams'], how='anti'))\n",
    "\n",
    "print(\"J:\", In_L.join(In_R, on=join_spec['joinParams'], how='inner', coalesce=False))\n",
    "\n",
    "print(\"R:\", In_R.join(In_L, on=join_spec['joinParams'], how='anti'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "L in: shape: (3, 3)\n",
      "┌─────┬─────┬─────┐\n",
      "│ foo ┆ bar ┆ ham │\n",
      "│ --- ┆ --- ┆ --- │\n",
      "│ i64 ┆ f64 ┆ str │\n",
      "╞═════╪═════╪═════╡\n",
      "│ 1   ┆ 6.0 ┆ a   │\n",
      "│ 2   ┆ 7.0 ┆ b   │\n",
      "│ 3   ┆ 8.0 ┆ c   │\n",
      "└─────┴─────┴─────┘\n",
      "R in: shape: (3, 2)\n",
      "┌───────┬─────┐\n",
      "│ apple ┆ ham │\n",
      "│ ---   ┆ --- │\n",
      "│ str   ┆ str │\n",
      "╞═══════╪═════╡\n",
      "│ x     ┆ a   │\n",
      "│ y     ┆ b   │\n",
      "│ z     ┆ d   │\n",
      "└───────┴─────┘\n",
      "L: shape: (1, 3)\n",
      "┌─────┬─────┬─────┐\n",
      "│ foo ┆ bar ┆ ham │\n",
      "│ --- ┆ --- ┆ --- │\n",
      "│ i64 ┆ f64 ┆ str │\n",
      "╞═════╪═════╪═════╡\n",
      "│ 3   ┆ 8.0 ┆ c   │\n",
      "└─────┴─────┴─────┘\n"
     ]
    }
   ],
   "source": [
    "df = pl.DataFrame(\n",
    "    {\n",
    "        \"foo\": [1, 2, 3],\n",
    "        \"bar\": [6.0, 7.0, 8.0],\n",
    "        \"ham\": [\"a\", \"b\", \"c\"],\n",
    "    }\n",
    ")\n",
    "\n",
    "other_df = pl.DataFrame(\n",
    "    {\n",
    "        \"apple\": [\"x\", \"y\", \"z\"],\n",
    "        \"ham\": [\"a\", \"b\", \"d\"],\n",
    "    }\n",
    ")\n",
    "\n",
    "print(\"L in:\", df)\n",
    "\n",
    "print(\"R in:\", other_df)\n",
    "\n",
    "print(\"L:\", df.join(other_df, left_on=\"ham\", right_on=\"ham\", how='anti'))\n",
    "\n",
    "# print(\"J: \", df.join(other_df, on=\"ham\", how='inner'))\n",
    "\n",
    "# print(\"R:\", other_df.join(df, on=\"ham\", how='anti'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Parsing Tool Config data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def input_textInput(xml_string):\n",
    "    # Get XML for a Text input tool\n",
    "    root = ET.fromstring(xml_string)\n",
    "    # Extract the field names\n",
    "    fields = [field.attrib['name'] for field in root.findall(\".//Fields/Field\")]\n",
    "    # Extract the data rows\n",
    "    data_rows = [[c.text for c in row.findall(\"c\")] for row in root.findall(\".//Data/r\")]\n",
    "    # Create the polars dataframe\n",
    "    df = pl.DataFrame(data_rows, fields, orient=\"row\")\n",
    "    # Display the dataframe\n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def getConf_Select(xml_string):\n",
    "    root = ET.fromstring(xml_string)\n",
    "    dict_SelectTool = {}\n",
    "\n",
    "    for field in root.findall(\".//SelectFields/SelectField\"):\n",
    "        field_name = field.attrib['field']\n",
    "        field_selected = field.attrib['selected']\n",
    "\n",
    "        try:\n",
    "            field_type = field.attrib['type']\n",
    "        except:\n",
    "            field_type = None\n",
    "        try:\n",
    "            field_rename =  field.attrib['rename']\n",
    "        except:\n",
    "            field_rename = None\n",
    "\n",
    "        dict_SelectTool[field_name] = (field_rename, field_type, field_selected)\n",
    "\n",
    "    return dict_SelectTool"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'joinParams': ['Ham', 'Cheese'], 'fields': {'Right_Ham': ['Right_Ham', 'Right_', None, None], 'Right_Cheese': ['Right_Cheese', 'Right_', None, None], 'Right_Column 3': ['Right_Column 3', 'Right_', 'V_String', '11'], 'Right_Column 4': ['Right_Column 4', 'Right_', 'Int64', '8']}}\n"
     ]
    }
   ],
   "source": [
    "def getConf_Join(xml_string):\n",
    "    root = ET.fromstring(xml_string)\n",
    "    dict_JoinTool = {}\n",
    "\n",
    "    # Join parameters\n",
    "    for joinField in root.findall(\".//Configuration/JoinInfo\"):\n",
    "        if joinField.attrib['connection'] == \"Left\":\n",
    "            left_on = [field.attrib['field'] for field in joinField]\n",
    "        if joinField.attrib['connection'] == \"Right\":\n",
    "            right_on = [field.attrib['field'] for field in joinField]\n",
    "\n",
    "    if left_on == right_on:\n",
    "        dict_JoinTool['joinParams'] = (left_on)\n",
    "    else:\n",
    "        dict_JoinTool['joinParams'] = (left_on, right_on)\n",
    "\n",
    "        \n",
    "    # Field Parameters\n",
    "    fieldConfig = {}\n",
    "    for fields in root.findall(\".//SelectField\"):\n",
    "        result = []\n",
    "        if fields.attrib['selected'] == 'True':\n",
    "            for field in ['rename', 'input', 'type', 'size']:\n",
    "                try:\n",
    "                    result.append(fields.attrib[field])\n",
    "                except KeyError:\n",
    "                    result.append(None)\n",
    "\n",
    "        if fields.attrib['field'] != '*Unknown':\n",
    "            fieldConfig[fields.attrib['field']] = result\n",
    "\n",
    "    dict_JoinTool['fields'] = fieldConfig\n",
    "\n",
    "    return dict_JoinTool\n",
    "\n",
    "print(getConf_Join(xml_join_tool))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Working with the XML file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "ename": "ParseError",
     "evalue": "syntax error: line 1, column 0 (<string>)",
     "output_type": "error",
     "traceback": [
      "Traceback \u001b[1;36m(most recent call last)\u001b[0m:\n",
      "\u001b[0m  File \u001b[0;32mc:\\Users\\casey.morter\\AppData\\Local\\miniconda3\\envs\\polaryx\\Lib\\site-packages\\IPython\\core\\interactiveshell.py:3577\u001b[0m in \u001b[0;35mrun_code\u001b[0m\n    exec(code_obj, self.user_global_ns, self.user_ns)\u001b[0m\n",
      "\u001b[0m  Cell \u001b[0;32mIn[11], line 6\u001b[0m\n    ToolType = ET.fromstring(ToolXML).find(\".//GuiSettings\").attrib['Plugin'].split(\".\")[2]\u001b[0m\n",
      "\u001b[1;36m  File \u001b[1;32mc:\\Users\\casey.morter\\AppData\\Local\\miniconda3\\envs\\polaryx\\Lib\\xml\\etree\\ElementTree.py:1335\u001b[1;36m in \u001b[1;35mXML\u001b[1;36m\n\u001b[1;33m    parser.feed(text)\u001b[1;36m\n",
      "\u001b[1;36m  File \u001b[1;32m<string>\u001b[1;36m\u001b[0m\n\u001b[1;31mParseError\u001b[0m\u001b[1;31m:\u001b[0m syntax error: line 1, column 0\n"
     ]
    }
   ],
   "source": [
    "# Parse all tools in tools dict\n",
    "for tool in results:\n",
    "\n",
    "    ToolID = tool[0]\n",
    "    ToolXML = tool[1]\n",
    "    ToolType = ET.fromstring(ToolXML).find(\".//GuiSettings\").attrib['Plugin'].split(\".\")[2]\n",
    "\n",
    "    print(ToolID, ToolType)\n",
    "\n",
    "    if ToolType == 'TextInput':\n",
    "        print(input_textInput(ToolXML))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "############### Input dataframe (TextInput):\n",
      " shape: (3, 4)\n",
      "┌──────────┬──────────┬─────┬────────┐\n",
      "│ Column 3 ┆ Column 4 ┆ Ham ┆ Cheese │\n",
      "│ ---      ┆ ---      ┆ --- ┆ ---    │\n",
      "│ str      ┆ str      ┆ str ┆ str    │\n",
      "╞══════════╪══════════╪═════╪════════╡\n",
      "│ 5        ┆ 8        ┆ z   ┆ a      │\n",
      "│ 6        ┆ 9        ┆ b   ┆ d      │\n",
      "│ 7        ┆ 10       ┆ c   ┆ c      │\n",
      "└──────────┴──────────┴─────┴────────┘\n",
      "\n",
      "############### Generated code from Select tool: \n",
      " df_output = df.with_columns(\n",
      "df.select(pl.col(f'Column 3').alias('Col_3_renamed')),\n",
      ")\n",
      "df_output = df_output.drop(f'Column 3')\n",
      "df_output = df_output.drop(f'Column 4')\n",
      "\n",
      "\n",
      "############### Output DF: \n",
      "\n",
      " shape: (3, 3)\n",
      "┌─────┬────────┬───────────────┐\n",
      "│ Ham ┆ Cheese ┆ Col_3_renamed │\n",
      "│ --- ┆ ---    ┆ ---           │\n",
      "│ str ┆ str    ┆ str           │\n",
      "╞═════╪════════╪═══════════════╡\n",
      "│ z   ┆ a      ┆ 5             │\n",
      "│ b   ┆ d      ┆ 6             │\n",
      "│ c   ┆ c      ┆ 7             │\n",
      "└─────┴────────┴───────────────┘\n"
     ]
    }
   ],
   "source": [
    "# Tool 1: TextInput\n",
    "xml_tool1 = results[3][2]\n",
    "df_in = input_textInput(xml_tool1)\n",
    "print(\"\\n############### Input dataframe (TextInput):\\n\", df_in)\n",
    "# Tool 2: Select\n",
    "col_spec = getConf_Select(results[4][2])\n",
    "# Generate code from \n",
    "code = tool_select(col_spec)\n",
    "print(\"\\n############### Generated code from Select tool: \\n\", code)\n",
    "# Execute and display output\n",
    "df = df_in\n",
    "exec(code)\n",
    "print(\"\\n############### Output DF: \\n\\n\", df_output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('1', 'TextInput (1)', '<Node ToolID=\"1\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Column1\" />\\n            <Field name=\"Column 2\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>1</c>\\n              <c>4</c>\\n            </r>\\n            <r>\\n              <c>2</c>\\n              <c>5</c>\\n            </r>\\n            <r>\\n              <c>3</c>\\n              <c>6</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('2', 'AlteryxSelect (2)', '<Node ToolID=\"2\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.AlteryxSelect.AlteryxSelect\">\\n        <Position x=\"186\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <OrderChanged value=\"False\" />\\n          <CommaDecimal value=\"False\" />\\n          <SelectFields>\\n            <SelectField field=\"Column1\" selected=\"True\" type=\"Int64\" size=\"8\" />\\n            <SelectField field=\"Column 2\" selected=\"False\" type=\"WString\" size=\"3\" />\\n            <SelectField field=\"*Unknown\" selected=\"False\" />\\n          </SelectFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSelect\" />\\n    </Node>\\n    ')\n",
      "('3', 'BrowseV2 (3)', '<Node ToolID=\"3\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"318\" y=\"54\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_9b8a61f4c39b2e4ea05f98886a386376~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('4', 'TextInput (4)', '<Node ToolID=\"4\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"246\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Column 3\" />\\n            <Field name=\"Column 4\" />\\n            <Field name=\"Ham\" />\\n            <Field name=\"Cheese\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>5</c>\\n              <c>8</c>\\n              <c>z</c>\\n              <c>a</c>\\n            </r>\\n            <r>\\n              <c>6</c>\\n              <c>9</c>\\n              <c>b</c>\\n              <c>d</c>\\n            </r>\\n            <r>\\n              <c>7</c>\\n              <c>10</c>\\n              <c>c</c>\\n              <c>c</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('5', 'AlteryxSelect (5)', '<Node ToolID=\"5\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.AlteryxSelect.AlteryxSelect\">\\n        <Position x=\"426\" y=\"390\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <OrderChanged value=\"False\" />\\n          <CommaDecimal value=\"False\" />\\n          <SelectFields>\\n            <SelectField field=\"Column 3\" selected=\"True\" rename=\"Col_3_renamed\" />\\n            <SelectField field=\"Column 4\" selected=\"False\" />\\n            <SelectField field=\"*Unknown\" selected=\"True\" />\\n          </SelectFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSelect\" />\\n    </Node>\\n    ')\n",
      "('6', 'Formula (6)', '<Node ToolID=\"6\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Formula.Formula\">\\n        <Position x=\"354\" y=\"474\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <FormulaFields>\\n            <FormulaField expression=\"[Count] + 10\" field=\"MoreCount\" size=\"4\" type=\"Int32\" />\\n          </FormulaFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>MoreCount = [Count] + 10\\n</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxFormula\" />\\n    </Node>\\n    ')\n",
      "('7', 'Join (7)', '<Node ToolID=\"7\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Join.Join\">\\n        <Position x=\"522\" y=\"402\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration joinByRecordPos=\"False\">\\n          <JoinInfo connection=\"Left\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <JoinInfo connection=\"Right\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <SelectConfiguration>\\n            <Configuration outputConnection=\"Join\">\\n              <OrderChanged value=\"False\" />\\n              <CommaDecimal value=\"False\" />\\n              <SelectFields>\\n                <SelectField field=\"Right_Ham\" selected=\"True\" rename=\"Right_Ham\" input=\"Right_\" />\\n                <SelectField field=\"Right_Cheese\" selected=\"True\" rename=\"Right_Cheese\" input=\"Right_\" />\\n                <SelectField field=\"Right_Column 3\" selected=\"True\" rename=\"Right_Column 3\" input=\"Right_\" type=\"V_String\" size=\"11\" />\\n                <SelectField field=\"Right_Column 4\" selected=\"True\" rename=\"Right_Column 4\" input=\"Right_\" type=\"Int64\" size=\"8\" />\\n                <SelectField field=\"*Unknown\" selected=\"True\" />\\n              </SelectFields>\\n            </Configuration>\\n          </SelectConfiguration>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxJoin\" />\\n    </Node>\\n    ')\n",
      "('10', 'BrowseV2 (10)', '<Node ToolID=\"10\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"618\" y=\"486\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_c1d268f486209c40bdc02a676a529ee0~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('11', 'Formula (11)', '<Node ToolID=\"11\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Formula.Formula\">\\n        <Position x=\"450\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <FormulaFields>\\n            <FormulaField expression=\"[Engine.TempFilePath]\" field=\"Path\" size=\"1073741823\" type=\"V_WString\" />\\n          </FormulaFields>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>Path = [Engine.TempFilePath]\\n</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxFormula\" />\\n    </Node>\\n    ')\n",
      "('12', 'Sample (12)', '<Node ToolID=\"12\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Sample.Sample\">\\n        <Position x=\"330\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <Mode>First</Mode>\\n          <N>1</N>\\n          <GroupFields orderChanged=\"False\" />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>First 1</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxSample\" />\\n    </Node>\\n    ')\n",
      "('13', 'BrowseV2 (13)', '<Node ToolID=\"13\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"546\" y=\"618\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_4d6ee2d9de8fac4095ab55a2bceed63e~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('14', 'DbFileOutput (14)', '<Node ToolID=\"14\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.DbFileOutput.DbFileOutput\">\\n        <Position x=\"702\" y=\"402\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <File MaxRecords=\"\" FileFormat=\"0\">.\\\\SimpleWorkflowOut.csv</File>\\n          <Passwords />\\n          <FormatSpecificOptions>\\n            <LineEndStyle>CRLF</LineEndStyle>\\n            <Delimeter>,</Delimeter>\\n            <ForceQuotes>False</ForceQuotes>\\n            <HeaderRow>True</HeaderRow>\\n            <CodePage>28591</CodePage>\\n            <WriteBOM>True</WriteBOM>\\n          </FormatSpecificOptions>\\n          <MultiFile value=\"False\" />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText>SimpleWorkflowOut.csv</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxDbFileOutput\" />\\n    </Node>\\n    ')\n",
      "('15', 'TextInput (15)', '<Node ToolID=\"15\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.TextInput.TextInput\">\\n        <Position x=\"54\" y=\"330\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <NumRows value=\"3\" />\\n          <Fields>\\n            <Field name=\"Ham\" />\\n            <Field name=\"Cheese\" />\\n            <Field name=\"Count\" />\\n          </Fields>\\n          <Data>\\n            <r>\\n              <c>a</c>\\n              <c>a</c>\\n              <c>4</c>\\n            </r>\\n            <r>\\n              <c>b</c>\\n              <c>d</c>\\n              <c>6</c>\\n            </r>\\n            <r>\\n              <c>c</c>\\n              <c>z</c>\\n              <c>7</c>\\n            </r>\\n          </Data>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxTextInput\" />\\n    </Node>\\n    ')\n",
      "('16', 'HamCheeseJoin', '<Node ToolID=\"16\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.Join.Join\">\\n        <Position x=\"306\" y=\"198\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration joinByRecordPos=\"False\">\\n          <JoinInfo connection=\"Left\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <JoinInfo connection=\"Right\">\\n            <Field field=\"Ham\" />\\n            <Field field=\"Cheese\" />\\n          </JoinInfo>\\n          <SelectConfiguration>\\n            <Configuration outputConnection=\"Join\">\\n              <OrderChanged value=\"False\" />\\n              <CommaDecimal value=\"False\" />\\n              <SelectFields>\\n                <SelectField field=\"Right_Ham\" selected=\"True\" rename=\"Right_Ham\" input=\"Right_\" />\\n                <SelectField field=\"Right_Cheese\" selected=\"True\" rename=\"Right_Cheese\" input=\"Right_\" />\\n                <SelectField field=\"*Unknown\" selected=\"True\" />\\n              </SelectFields>\\n            </Configuration>\\n          </SelectConfiguration>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name>HamCheeseJoin</Name>\\n          <DefaultAnnotationText>HamCheeseJoin</DefaultAnnotationText>\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxJoin\" />\\n    </Node>\\n    ')\n",
      "('17', 'BrowseV2 (17)', '<Node ToolID=\"17\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"114\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_e692dab3020ec84ebe69a5de3e6990c9~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('18', 'BrowseV2 (18)', '<Node ToolID=\"18\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"198\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_83aac5fa43df8044b1161f8298a2a180~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout />\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n    ')\n",
      "('19', 'BrowseV2 (19)', '<Node ToolID=\"19\">\\n      <GuiSettings Plugin=\"AlteryxBasePluginsGui.BrowseV2.BrowseV2\">\\n        <Position x=\"402\" y=\"294\" />\\n      </GuiSettings>\\n      <Properties>\\n        <Configuration>\\n          <TempFile>C:\\\\Users\\\\casey.morter\\\\AppData\\\\Local\\\\Temp\\\\Engine_28104_a89278053b87e446bfe970eb948f1ef4_\\\\Engine_28104_c2ab20e4f5222342bc00e6424dbc38bd~.yxdb</TempFile>\\n          <TempFileDataProfiling />\\n          <Layout>\\n            <View1>\\n              <Hints>\\n                <Table />\\n              </Hints>\\n            </View1>\\n          </Layout>\\n        </Configuration>\\n        <Annotation DisplayMode=\"0\">\\n          <Name />\\n          <DefaultAnnotationText />\\n          <Left value=\"False\" />\\n        </Annotation>\\n      </Properties>\\n      <EngineSettings EngineDll=\"AlteryxBasePluginsEngine.dll\" EngineDllEntryPoint=\"AlteryxBrowseV2\" />\\n    </Node>\\n  ')\n"
     ]
    }
   ],
   "source": [
    "for tool in results:\n",
    "    print(tool)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "vscode": {
     "languageId": "latex"
    }
   },
   "source": [
    "# DAG Analysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<Element 'Origin' at 0x0000018403B512B0>\n",
      "<Element 'Origin' at 0x0000018403B50C20>\n",
      "<Element 'Origin' at 0x0000018403B51170>\n",
      "<Element 'Origin' at 0x0000018403B50AE0>\n",
      "<Element 'Origin' at 0x0000018403B50D10>\n",
      "<Element 'Origin' at 0x0000018403B50BD0>\n",
      "<Element 'Origin' at 0x0000018403B508B0>\n",
      "<Element 'Origin' at 0x0000018403B50270>\n",
      "<Element 'Origin' at 0x0000018403B51580>\n",
      "<Element 'Origin' at 0x0000018403B50E00>\n",
      "<Element 'Origin' at 0x0000018403B50CC0>\n",
      "<Element 'Origin' at 0x0000018403B531A0>\n",
      "<Element 'Origin' at 0x0000018403B533D0>\n",
      "<Element 'Origin' at 0x0000018403B53600>\n",
      "<Element 'Origin' at 0x0000018403B536F0>\n",
      "<Element 'Origin' at 0x0000018403B53470>\n"
     ]
    }
   ],
   "source": [
    "# %pip install networkx matplotlib\n",
    "\n",
    "xml_file_path = \"./SimpleWorkflow/SimpleWorkflow.yxmd\"\n",
    "tree = ET.parse(xml_file_path)\n",
    "root = tree.getroot()\n",
    "      \n",
    "# root = ET.fromstring(xml_string)\n",
    "# connections = root.find('Connections')\n",
    "# if connections is not None:\n",
    "#     xml_connections = ''.join(connections.itertext()).strip()\n",
    "\n",
    "    \n",
    "    \n",
    "\n",
    "# Add edges to the graph\n",
    "for conn in root.iter('Connection'):\n",
    "    origin = conn.find('Origin')\n",
    "    print(origin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 158296 characters]",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import xml.etree.ElementTree as ET\n",
    "\n",
    "xml_file_path = \"./SimpleWorkflow/SimpleWorkflow.yxmd\"\n",
    "tree = ET.parse(xml_file_path)\n",
    "root = tree.getroot()\n",
    "\n",
    "# Create a directed graph\n",
    "G = nx.DiGraph()\n",
    "\n",
    "# Add edges to the graph\n",
    "for conn in root.iter('Connection'):\n",
    "    origin = conn.find('Origin')\n",
    "    destination = conn.find('Destination')\n",
    "\n",
    "    origin_id = origin.get('ToolID')\n",
    "    dest_id = destination.get('ToolID')\n",
    "    origin_conn = origin.get('Connection')\n",
    "    dest_conn = destination.get('Connection')\n",
    "\n",
    "    G.add_edge(origin_id, dest_id)\n",
    "    G.edges[origin_id, dest_id]['origin_conn'] = origin_conn\n",
    "    G.edges[origin_id, dest_id]['dest_conn'] = dest_conn\n",
    "\n",
    "# Set up the plot\n",
    "plt.figure(figsize=(12, 8))\n",
    "# pos = nx.spring_layout(G)\n",
    "pos = nx.circular_layout(G)\n",
    "\n",
    "# Draw nodes\n",
    "nx.draw_networkx_nodes(G, pos, node_size=2000, node_color='lightblue')\n",
    "nx.draw_networkx_labels(G, pos, labels={node: f\"Tool ID: {node}\" for node in G.nodes()})\n",
    "\n",
    "# Draw edges\n",
    "nx.draw_networkx_edges(G, pos, edge_color='gray', arrows=True, arrowsize=20)\n",
    "\n",
    "# Add edge labels\n",
    "edge_labels = {(u, v): f\"{d['origin_conn']} -> {d['dest_conn']}\" for u, v, d in G.edges(data=True)}\n",
    "nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8)\n",
    "\n",
    "# Remove axis\n",
    "plt.axis('off')\n",
    "\n",
    "# Show the plot\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'str' object has no attribute 'iter'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[32], line 59\u001b[0m\n\u001b[0;32m     53\u001b[0m \u001b[38;5;66;03m# Example usage:\u001b[39;00m\n\u001b[0;32m     54\u001b[0m xml_string \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[0;32m     55\u001b[0m \u001b[38;5;124m<Connections>\u001b[39m\n\u001b[0;32m     56\u001b[0m \u001b[38;5;124m    <!-- Your XML content here -->\u001b[39m\n\u001b[0;32m     57\u001b[0m \u001b[38;5;124m</Connections>\u001b[39m\n\u001b[0;32m     58\u001b[0m \u001b[38;5;124m\"\"\"\u001b[39m\n\u001b[1;32m---> 59\u001b[0m \u001b[43mvisualize_dag\u001b[49m\u001b[43m(\u001b[49m\u001b[43mxml_string\u001b[49m\u001b[43m)\u001b[49m\n",
      "Cell \u001b[1;32mIn[32], line 18\u001b[0m, in \u001b[0;36mvisualize_dag\u001b[1;34m(root)\u001b[0m\n\u001b[0;32m     15\u001b[0m G \u001b[38;5;241m=\u001b[39m nx\u001b[38;5;241m.\u001b[39mDiGraph()\n\u001b[0;32m     17\u001b[0m \u001b[38;5;66;03m# Add edges to the graph\u001b[39;00m\n\u001b[1;32m---> 18\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m conn \u001b[38;5;129;01min\u001b[39;00m \u001b[43mroot\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miter\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mConnection\u001b[39m\u001b[38;5;124m'\u001b[39m):\n\u001b[0;32m     19\u001b[0m     origin \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mfind(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mOrigin\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m     20\u001b[0m     destination \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mfind(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mDestination\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'str' object has no attribute 'iter'"
     ]
    }
   ],
   "source": [
    "import xml.etree.ElementTree as ET\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "xml_file_path = \"./SimpleWorkflow/SimpleWorkflow.yxmd\"\n",
    "tree = ET.parse(xml_file_path)\n",
    "root = tree.getroot()\n",
    "\n",
    "\n",
    "def visualize_dag(root):\n",
    "    # Parse the XML string\n",
    "#     root = ET.fromstring(xml_string)\n",
    "\n",
    "    # Create a directed graph\n",
    "    G = nx.DiGraph()\n",
    "\n",
    "    # Add edges to the graph\n",
    "    for conn in root.iter('Connection'):\n",
    "        origin = conn.find('Origin')\n",
    "        destination = conn.find('Destination')\n",
    "        \n",
    "        origin_id = origin.get('ToolID')\n",
    "        dest_id = destination.get('ToolID')\n",
    "        origin_conn = origin.get('Connection')\n",
    "        dest_conn = destination.get('Connection')\n",
    "        \n",
    "        G.add_edge(origin_id, dest_id)\n",
    "        G.edges[origin_id, dest_id]['origin_conn'] = origin_conn\n",
    "        G.edges[origin_id, dest_id]['dest_conn'] = dest_conn\n",
    "\n",
    "    # Set up the plot\n",
    "    plt.figure(figsize=(12, 8))\n",
    "    pos = nx.spring_layout(G)\n",
    "\n",
    "    # Draw nodes\n",
    "    nx.draw_networkx_nodes(G, pos, node_size=2000, node_color='lightblue')\n",
    "    nx.draw_networkx_labels(G, pos, labels={node: f\"Tool ID: {node}\" for node in G.nodes()})\n",
    "\n",
    "    # Draw edges\n",
    "    nx.draw_networkx_edges(G, pos, edge_color='gray', arrows=True, arrowsize=20)\n",
    "\n",
    "    # Add edge labels\n",
    "    edge_labels = {(u, v): f\"{d['origin_conn']} -> {d['dest_conn']}\" for u, v, d in G.edges(data=True)}\n",
    "    nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8)\n",
    "\n",
    "    # Remove axis\n",
    "    plt.axis('off')\n",
    "\n",
    "    # Show the plot\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n",
    "\n",
    "# Example usage:\n",
    "xml_string = \"\"\"\n",
    "<Connections>\n",
    "    <!-- Your XML content here -->\n",
    "</Connections>\n",
    "\"\"\"\n",
    "visualize_dag(xml_string)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
