Flowfile 0.5.6__py3-none-any.whl → 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flowfile/api.py +8 -6
- flowfile/web/static/assets/{AdminView-c2c7942b.js → AdminView-C4K1DdHI.js} +28 -33
- flowfile/web/static/assets/{CloudConnectionView-7a3042c6.js → CloudConnectionView-BZbPvPUL.js} +39 -50
- flowfile/web/static/assets/{CloudStorageReader-24c54524.css → CloudStorageReader-BDByiqPI.css} +25 -25
- flowfile/web/static/assets/{CloudStorageReader-709c4037.js → CloudStorageReader-DLVukNJ7.js} +30 -35
- flowfile/web/static/assets/{CloudStorageWriter-604c51a8.js → CloudStorageWriter-Bfi-C1QW.js} +32 -37
- flowfile/web/static/assets/{CloudStorageWriter-60547855.css → CloudStorageWriter-y8jL8yjG.css} +24 -24
- flowfile/web/static/assets/{ColumnActionInput-d63d6746.js → ColumnActionInput-BpiCApw9.js} +7 -12
- flowfile/web/static/assets/{ColumnSelector-0c8cd1cd.js → ColumnSelector-CEAwedI7.js} +1 -2
- flowfile/web/static/assets/ContextMenu-CdojQu0w.js +9 -0
- flowfile/web/static/assets/ContextMenu-D12mhsy1.js +9 -0
- flowfile/web/static/assets/ContextMenu-EWUR98va.js +9 -0
- flowfile/web/static/assets/{ContextMenu.vue_vue_type_script_setup_true_lang-774c517c.js → ContextMenu.vue_vue_type_script_setup_true_lang-I4rXXd6G.js} +4 -5
- flowfile/web/static/assets/{CrossJoin-38e5b99a.js → CrossJoin-BOFfxkJO.js} +19 -18
- flowfile/web/static/assets/{CrossJoin-71b4cc10.css → CrossJoin-Cmbyt9im.css} +18 -18
- flowfile/web/static/assets/{CustomNode-76e8f3f5.js → CustomNode-Bhpezobq.js} +12 -17
- flowfile/web/static/assets/{DatabaseConnectionSettings-38155669.js → DatabaseConnectionSettings-Dw3bSJKB.js} +10 -11
- flowfile/web/static/assets/{DatabaseReader-5bf8c75b.css → DatabaseReader-D6pUNUCs.css} +21 -21
- flowfile/web/static/assets/{DatabaseReader-2e549c8f.js → DatabaseReader-m87ghlw0.js} +36 -34
- flowfile/web/static/assets/{DatabaseView-dc877c29.js → DatabaseView-CisSAtpe.js} +30 -38
- flowfile/web/static/assets/{DatabaseWriter-ffb91864.js → DatabaseWriter-Bbj9JLdL.js} +33 -35
- flowfile/web/static/assets/{DatabaseWriter-bdcf2c8b.css → DatabaseWriter-RBqdFLj8.css} +17 -17
- flowfile/web/static/assets/{DesignerView-a4466dab.js → DesignerView-DemDevTQ.js} +1752 -2054
- flowfile/web/static/assets/{DesignerView-71d4e9a1.css → DesignerView-Dm6OzlIc.css} +209 -168
- flowfile/web/static/assets/{DocumentationView-979afc84.js → DocumentationView-BrC1ZR3H.js} +3 -4
- flowfile/web/static/assets/{ExploreData-e4b92aaf.js → ExploreData-BMKcDuRb.js} +8 -10
- flowfile/web/static/assets/{ExternalSource-d08e7227.js → ExternalSource-BXrNNS-f.js} +40 -42
- flowfile/web/static/assets/{ExternalSource-7ac7373f.css → ExternalSource-NB6WVl5R.css} +14 -14
- flowfile/web/static/assets/{Filter-7add806d.js → Filter-C2MjsN6P.js} +36 -33
- flowfile/web/static/assets/{Filter-7494ea97.css → Filter-DCMGGuGC.css} +9 -9
- flowfile/web/static/assets/{Formula-53d58c43.css → Formula-BYafbDj8.css} +4 -4
- flowfile/web/static/assets/{Formula-36ab24d2.js → Formula-ufuy4mVD.js} +27 -26
- flowfile/web/static/assets/{FuzzyMatch-ad6361d6.css → FuzzyMatch-BGJAwgd0.css} +42 -42
- flowfile/web/static/assets/{FuzzyMatch-cc01bb04.js → FuzzyMatch-BOHODq3h.js} +36 -38
- flowfile/web/static/assets/{GraphSolver-4fb98f3b.js → GraphSolver-B6ZzpNGO.js} +23 -21
- flowfile/web/static/assets/{GraphSolver-4b4d7db9.css → GraphSolver-DFN83sj3.css} +4 -4
- flowfile/web/static/assets/{GroupBy-b3c8f429.js → GroupBy-B9BRNcfe.js} +30 -29
- flowfile/web/static/assets/{Sort-4abb7fae.css → GroupBy-x4ooP5np.css} +1 -1
- flowfile/web/static/assets/Join-Bx_g5bZz.css +118 -0
- flowfile/web/static/assets/{Join-096b7b26.js → Join-DsBEy1IH.js} +48 -43
- flowfile/web/static/assets/{LoginView-c33a246a.js → LoginView-Ct0rhdcO.js} +1 -2
- flowfile/web/static/assets/{ManualInput-39111f19.css → ManualInput-DlZmtMdt.css} +48 -48
- flowfile/web/static/assets/{ManualInput-7307e9b1.js → ManualInput-bC4BUgnG.js} +40 -41
- flowfile/web/static/assets/{MultiSelect-14822c48.js → MultiSelect-DIQ8PuTC.js} +2 -2
- flowfile/web/static/assets/{MultiSelect.vue_vue_type_script_setup_true_lang-90c4d340.js → MultiSelect.vue_vue_type_script_setup_true_lang-BefHfqTI.js} +1 -1
- flowfile/web/static/assets/{NodeDesigner-5036c392.js → NodeDesigner-D39yzr2k.js} +178 -208
- flowfile/web/static/assets/{NodeDesigner-94cd4dd3.css → NodeDesigner-R0l6sYyY.css} +76 -76
- flowfile/web/static/assets/{NumericInput-15cf3b72.js → NumericInput-DMSX3oOr.js} +2 -2
- flowfile/web/static/assets/{NumericInput.vue_vue_type_script_setup_true_lang-91e679d7.js → NumericInput.vue_vue_type_script_setup_true_lang-d0YlVHAl.js} +1 -1
- flowfile/web/static/assets/{Output-1f8ed42c.js → Output-D0VoXGcW.js} +26 -34
- flowfile/web/static/assets/{Output-692dd25d.css → Output-DsmglIDy.css} +5 -5
- flowfile/web/static/assets/{Pivot-0e153f4e.js → Pivot-BnMB4sEe.js} +26 -26
- flowfile/web/static/assets/{Pivot-0eda81b4.css → Pivot-qKTyWxop.css} +4 -4
- flowfile/web/static/assets/{PivotValidation-81ec2a33.js → PivotValidation-B2lWvugt.js} +7 -9
- flowfile/web/static/assets/{PivotValidation-5a4f7c79.js → PivotValidation-BPlhRjpL.js} +7 -9
- flowfile/web/static/assets/{PolarsCode-a39f15ac.js → PolarsCode-5h0tHnWR.js} +22 -20
- flowfile/web/static/assets/{PopOver-ddcfe4f6.js → PopOver-BHpt5rsj.js} +5 -9
- flowfile/web/static/assets/{PopOver-d96599db.css → PopOver-CyYM4-rV.css} +1 -1
- flowfile/web/static/assets/{Read-90f366bc.css → Read-DJxkrTb_.css} +10 -10
- flowfile/web/static/assets/Read-TsLEFh3B.js +227 -0
- flowfile/web/static/assets/{RecordCount-e9048ccd.js → RecordCount-DkVixq9v.js} +18 -17
- flowfile/web/static/assets/{RecordId-ad02521d.js → RecordId-C2UEGlCf.js} +42 -39
- flowfile/web/static/assets/{SQLQueryComponent-2eeecf0b.js → SQLQueryComponent-Dr5KMoD3.js} +2 -3
- flowfile/web/static/assets/{Sample-9a68c23d.js → Sample-Cb3eQNmd.js} +30 -30
- flowfile/web/static/assets/{SecretSelector-2429f35a.js → SecretSelector-De2L2bSx.js} +3 -4
- flowfile/web/static/assets/{SecretsView-c6afc915.js → SecretsView-CheC9BPV.js} +13 -16
- flowfile/web/static/assets/{Select-fcd002b6.js → Select-CI8TloRs.js} +41 -36
- flowfile/web/static/assets/{SettingsSection-5ce15962.js → SettingsSection-B39ulIiI.js} +1 -2
- flowfile/web/static/assets/{SettingsSection-c6b1362c.js → SettingsSection-BiCc7S9h.js} +1 -2
- flowfile/web/static/assets/{SettingsSection-cebb91d5.js → SettingsSection-CITK_R7o.js} +2 -3
- flowfile/web/static/assets/{SettingsSection-26fe48d4.css → SettingsSection-D2GgY-Aq.css} +4 -4
- flowfile/web/static/assets/{SetupView-2d12e01f.js → SetupView-C1aXRDvp.js} +1 -2
- flowfile/web/static/assets/{SingleSelect-b67de4eb.js → SingleSelect-Kr_hz90m.js} +2 -2
- flowfile/web/static/assets/{SingleSelect.vue_vue_type_script_setup_true_lang-eedb70eb.js → SingleSelect.vue_vue_type_script_setup_true_lang-Rxht5Z5N.js} +1 -1
- flowfile/web/static/assets/{SliderInput-fd8134ac.js → SliderInput-CLqpCxCb.js} +1 -2
- flowfile/web/static/assets/{GroupBy-5792782d.css → Sort-BIt2kc_p.css} +1 -1
- flowfile/web/static/assets/{Sort-c005a573.js → Sort-Dnw_J6Qi.js} +25 -25
- flowfile/web/static/assets/{TextInput-1bb31dab.js → TextInput-wdlunIZC.js} +2 -2
- flowfile/web/static/assets/{TextInput.vue_vue_type_script_setup_true_lang-a51fe730.js → TextInput.vue_vue_type_script_setup_true_lang-Bcj3ywzv.js} +1 -1
- flowfile/web/static/assets/{TextToRows-4f363753.js → TextToRows-BhtyGWPq.js} +42 -49
- flowfile/web/static/assets/{TextToRows-12afb4f4.css → TextToRows-DivDOLDx.css} +9 -9
- flowfile/web/static/assets/{ToggleSwitch-ca0f2e5e.js → ToggleSwitch-B-6WzfFf.js} +2 -2
- flowfile/web/static/assets/{ToggleSwitch.vue_vue_type_script_setup_true_lang-49aa41d8.js → ToggleSwitch.vue_vue_type_script_setup_true_lang-Cj8LqT-b.js} +1 -1
- flowfile/web/static/assets/{UnavailableFields-f6147968.js → UnavailableFields-Yf6XSqFB.js} +2 -3
- flowfile/web/static/assets/{Union-c65f17b7.js → Union-CwpjeKYC.js} +20 -23
- flowfile/web/static/assets/{Unpivot-b6ad6427.css → Union-DQJcpp3-.css} +6 -6
- flowfile/web/static/assets/{Unique-a1d96fb2.js → Unique-25v3urqH.js} +75 -74
- flowfile/web/static/assets/{Union-d6a8d7d5.css → Unpivot-Deqh1gtI.css} +6 -6
- flowfile/web/static/assets/{Unpivot-c2657ff3.js → Unpivot-sYcTTXrq.js} +34 -27
- flowfile/web/static/assets/{UnpivotValidation-28e29a3b.js → UnpivotValidation-C5DDEKY2.js} +5 -7
- flowfile/web/static/assets/VueGraphicWalker-B8l1_Z92.js +131 -0
- flowfile/web/static/assets/VueGraphicWalker-Da_1-3me.css +21 -0
- flowfile/web/static/assets/{api-df48ec50.js → api-C0LvF-0C.js} +1 -1
- flowfile/web/static/assets/{api-ee542cf7.js → api-DaC83EO_.js} +1 -1
- flowfile/web/static/assets/client-C8Ygr6Gb.js +42 -0
- flowfile/web/static/assets/{dropDown-7576a76a.js → dropDown-D5YXaPRR.js} +7 -12
- flowfile/web/static/assets/{fullEditor-7583bef5.js → fullEditor-BVYnWm05.js} +300 -18
- flowfile/web/static/assets/genericNodeSettings-2wAu-QKn.css +75 -0
- flowfile/web/static/assets/genericNodeSettings-BBtW_Cpz.js +590 -0
- flowfile/web/static/assets/{VueGraphicWalker-2fc3ddd4.js → graphic-walker.es-VrK6vdGE.js} +92305 -89751
- flowfile/web/static/assets/index-BCJxPfM5.js +6693 -0
- flowfile/web/static/assets/{index-057d770d.js → index-CHPMUR0d.js} +150 -170
- flowfile/web/static/assets/index-DPkoZWq8.js +32 -0
- flowfile/web/static/assets/index-DnW_KC_I.js +277 -0
- flowfile/web/static/assets/index-UFXyfirV.css +10797 -0
- flowfile/web/static/assets/index-bcuE0Z0p.js +87456 -0
- flowfile/web/static/assets/{node.types-2c15bb7e.js → node.types-Dl4gtSW9.js} +2 -2
- flowfile/web/static/assets/{outputCsv-c492b15e.js → outputCsv-BELuBiJZ.js} +1 -2
- flowfile/web/static/assets/outputCsv-CdGkv-fN.css +2581 -0
- flowfile/web/static/assets/{outputExcel-13bfa10f.js → outputExcel-D0TTNM79.js} +1 -2
- flowfile/web/static/assets/{outputParquet-9be1523a.js → outputParquet-Cz9EbRHj.js} +1 -2
- flowfile/web/static/assets/{readCsv-5a49a8c9.js → readCsv-7bd3kUMI.js} +1 -2
- flowfile/web/static/assets/{readExcel-27c30ad8.js → readExcel-Cq8CCwIv.js} +3 -4
- flowfile/web/static/assets/{readParquet-c5244ad5.css → readParquet-CRDmBrsp.css} +4 -4
- flowfile/web/static/assets/{readParquet-446bde68.js → readParquet-DjR4mRaj.js} +4 -5
- flowfile/web/static/assets/{secrets.api-34431884.js → secrets.api-C9o2KE5V.js} +1 -1
- flowfile/web/static/assets/{selectDynamic-5754a2b1.js → selectDynamic-Bl5FVsME.js} +5 -7
- flowfile/web/static/assets/useNodeSettings-dMS9zmh_.js +69 -0
- flowfile/web/static/assets/{vue-codemirror.esm-8f46fb36.js → vue-codemirror.esm-CwaYwln0.js} +3469 -3064
- flowfile/web/static/assets/{vue-content-loader.es-808fe33a.js → vue-content-loader.es-CMoRXo7N.js} +3 -3
- flowfile/web/static/index.html +2 -3
- {flowfile-0.5.6.dist-info → flowfile-0.6.1.dist-info}/METADATA +2 -1
- flowfile-0.6.1.dist-info/RECORD +417 -0
- {flowfile-0.5.6.dist-info → flowfile-0.6.1.dist-info}/WHEEL +1 -1
- flowfile_core/auth/password.py +1 -0
- flowfile_core/database/init_db.py +7 -5
- flowfile_core/fileExplorer/funcs.py +2 -2
- flowfile_core/flowfile/code_generator/code_generator.py +13 -11
- flowfile_core/flowfile/filter_expressions.py +327 -0
- flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +61 -59
- flowfile_core/flowfile/flow_data_engine/flow_file_column/type_registry.py +3 -29
- flowfile_core/flowfile/flow_data_engine/flow_file_column/utils.py +45 -14
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/models.py +20 -3
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/streaming.py +206 -0
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +146 -24
- flowfile_core/flowfile/flow_graph.py +504 -190
- flowfile_core/flowfile/flow_node/__init__.py +32 -0
- flowfile_core/flowfile/flow_node/executor.py +404 -0
- flowfile_core/flowfile/flow_node/flow_node.py +207 -106
- flowfile_core/flowfile/flow_node/models.py +40 -0
- flowfile_core/flowfile/flow_node/output_field_config_applier.py +217 -0
- flowfile_core/flowfile/flow_node/schema_utils.py +78 -0
- flowfile_core/flowfile/flow_node/state.py +155 -0
- flowfile_core/flowfile/history_manager.py +401 -0
- flowfile_core/flowfile/manage/compatibility_enhancements.py +9 -0
- flowfile_core/flowfile/manage/io_flowfile.py +3 -1
- flowfile_core/flowfile/sources/external_sources/sql_source/models.py +20 -4
- flowfile_core/flowfile/util/execution_orderer.py +89 -36
- flowfile_core/routes/auth.py +8 -9
- flowfile_core/routes/routes.py +320 -101
- flowfile_core/routes/user_defined_components.py +18 -16
- flowfile_core/schemas/history_schema.py +220 -0
- flowfile_core/schemas/input_schema.py +130 -6
- flowfile_core/schemas/schemas.py +9 -0
- flowfile_core/schemas/transform_schema.py +27 -5
- flowfile_core/schemas/yaml_types.py +23 -5
- flowfile_frame/adding_expr.py +18 -126
- flowfile_frame/callable_utils.py +261 -0
- flowfile_frame/database/connection_manager.py +0 -1
- flowfile_frame/expr.py +8 -4
- flowfile_frame/flow_frame.py +41 -41
- flowfile_frame/lazy.py +3 -12
- flowfile_frame/lazy_methods.py +5 -64
- flowfile_frame/utils.py +13 -32
- flowfile_worker/funcs.py +6 -4
- flowfile_worker/main.py +2 -0
- flowfile_worker/models.py +31 -11
- flowfile_worker/routes.py +60 -35
- flowfile_worker/spawner.py +7 -1
- flowfile_worker/streaming.py +335 -0
- flowfile/web/static/assets/ContextMenu-366bf1b4.js +0 -9
- flowfile/web/static/assets/ContextMenu-85cf5b44.js +0 -9
- flowfile/web/static/assets/ContextMenu-9d28ae6d.js +0 -9
- flowfile/web/static/assets/Join-28b5e18f.css +0 -109
- flowfile/web/static/assets/Read-39b63932.js +0 -222
- flowfile/web/static/assets/VueGraphicWalker-430f0b86.css +0 -6
- flowfile/web/static/assets/database_reader-ce1e55f3.svg +0 -24
- flowfile/web/static/assets/database_writer-b4ad0753.svg +0 -23
- flowfile/web/static/assets/element-icons-9c88a535.woff +0 -0
- flowfile/web/static/assets/element-icons-de5eb258.ttf +0 -0
- flowfile/web/static/assets/genericNodeSettings-0155288b.js +0 -136
- flowfile/web/static/assets/genericNodeSettings-3b2507ea.css +0 -46
- flowfile/web/static/assets/index-aeec439d.js +0 -38
- flowfile/web/static/assets/index-ca6799de.js +0 -62760
- flowfile/web/static/assets/index-d60c9dd4.css +0 -10777
- flowfile/web/static/assets/nodeInput-d478b9ac.js +0 -2
- flowfile/web/static/assets/outputCsv-cc84e09f.css +0 -2499
- flowfile-0.5.6.dist-info/RECORD +0 -407
- /flowfile/web/static/assets/{AdminView-f53bad23.css → AdminView-B2Dthl3u.css} +0 -0
- /flowfile/web/static/assets/{CloudConnectionView-cf85f943.css → CloudConnectionView-BdFYGWV7.css} +0 -0
- /flowfile/web/static/assets/{ColumnActionInput-c44b7aee.css → ColumnActionInput-dCasSIC9.css} +0 -0
- /flowfile/web/static/assets/{ColumnSelector-371637fb.css → ColumnSelector-j6sEOjo1.css} +0 -0
- /flowfile/web/static/assets/{CustomNode-edb9b939.css → CustomNode-VPlajG0j.css} +0 -0
- /flowfile/web/static/assets/{DatabaseConnectionSettings-c20a1e16.css → DatabaseConnectionSettings-B78hXYgu.css} +0 -0
- /flowfile/web/static/assets/{DatabaseView-6655afd6.css → DatabaseView-B-_adk1s.css} +0 -0
- /flowfile/web/static/assets/{DocumentationView-9ea6e871.css → DocumentationView-CL7iipFL.css} +0 -0
- /flowfile/web/static/assets/{ExploreData-10c5acc8.css → ExploreData-DHjv0Plr.css} +0 -0
- /flowfile/web/static/assets/{LoginView-d325d632.css → LoginView-DN1BXY3e.css} +0 -0
- /flowfile/web/static/assets/{PivotValidation-0e905b1a.css → PivotValidation-DK-FARWe.css} +0 -0
- /flowfile/web/static/assets/{PivotValidation-41b57ad6.css → PivotValidation-FUa9F47u.css} +0 -0
- /flowfile/web/static/assets/{PolarsCode-2b1f1f23.css → PolarsCode-G-gRSrSc.css} +0 -0
- /flowfile/web/static/assets/{SQLQueryComponent-edb90b98.css → SQLQueryComponent-oAbWw0r-.css} +0 -0
- /flowfile/web/static/assets/{SecretSelector-6329f743.css → SecretSelector-CJSadIZx.css} +0 -0
- /flowfile/web/static/assets/{SecretsView-aa291340.css → SecretsView-DbzIRAba.css} +0 -0
- /flowfile/web/static/assets/{SettingsSection-8f980839.css → SettingsSection-BGcJnH6q.css} +0 -0
- /flowfile/web/static/assets/{SettingsSection-07fbbc39.css → SettingsSection-DDWn_EGW.css} +0 -0
- /flowfile/web/static/assets/{SetupView-ec26f76a.css → SetupView-CI1nd-5Z.css} +0 -0
- /flowfile/web/static/assets/{SliderInput-f2e4f23c.css → SliderInput-BRk-q_Dk.css} +0 -0
- /flowfile/web/static/assets/{UnavailableFields-394a1f78.css → UnavailableFields-DRKDImKe.css} +0 -0
- /flowfile/web/static/assets/{Unique-2b705521.css → Unique-Absb0aON.css} +0 -0
- /flowfile/web/static/assets/{UnpivotValidation-d5ca3b7b.css → UnpivotValidation-DSBkFgS-.css} +0 -0
- /flowfile/web/static/assets/{airbyte-292aa232.png → airbyte-W0xvIXwZ.png} +0 -0
- /flowfile/web/static/assets/{cloud_storage_reader-aa1415d6.png → cloud_storage_reader-3GpSCk90.png} +0 -0
- /flowfile/web/static/assets/{cross_join-d30c0290.png → cross_join-B0qpgYoV.png} +0 -0
- /flowfile/web/static/assets/{dropDown-1d6acbd9.css → dropDown-CE0VF5_P.css} +0 -0
- /flowfile/web/static/assets/{explore_data-8a0a2861.png → explore_data-tX6olPPL.png} +0 -0
- /flowfile/web/static/assets/{fa-brands-400-808443ae.ttf → fa-brands-400-D1LuMI3I.ttf} +0 -0
- /flowfile/web/static/assets/{fa-brands-400-d7236a19.woff2 → fa-brands-400-D_cYUPeE.woff2} +0 -0
- /flowfile/web/static/assets/{fa-regular-400-e3456d12.woff2 → fa-regular-400-BjRzuEpd.woff2} +0 -0
- /flowfile/web/static/assets/{fa-regular-400-54cf6086.ttf → fa-regular-400-DZaxPHgR.ttf} +0 -0
- /flowfile/web/static/assets/{fa-solid-900-aa759986.woff2 → fa-solid-900-CTAAxXor.woff2} +0 -0
- /flowfile/web/static/assets/{fa-solid-900-d2f05935.ttf → fa-solid-900-D0aA9rwL.ttf} +0 -0
- /flowfile/web/static/assets/{fa-v4compatibility-0ce9033c.woff2 → fa-v4compatibility-C9RhG_FT.woff2} +0 -0
- /flowfile/web/static/assets/{fa-v4compatibility-30f6abf6.ttf → fa-v4compatibility-CCth-dXg.ttf} +0 -0
- /flowfile/web/static/assets/{filter-d7708bda.png → filter-WRdZyUOw.png} +0 -0
- /flowfile/web/static/assets/{formula-eeeb1611.png → formula-CgM7uHVI.png} +0 -0
- /flowfile/web/static/assets/{fullEditor-fe9f7e18.css → fullEditor-CmDI7T9F.css} +0 -0
- /flowfile/web/static/assets/{fuzzy_match-40c161b2.png → fuzzy_match-Yon3k5Tc.png} +0 -0
- /flowfile/web/static/assets/{graph_solver-8b7888b8.png → graph_solver-BlMrBttD.png} +0 -0
- /flowfile/web/static/assets/{group_by-80561fc3.png → group_by-Gici0CSS.png} +0 -0
- /flowfile/web/static/assets/{input_data-ab2eb678.png → input_data-BRdGecLc.png} +0 -0
- /flowfile/web/static/assets/{join-349043ae.png → join-BITWRu73.png} +0 -0
- /flowfile/web/static/assets/{manual_input-ae98f31d.png → manual_input-CFvo_EUS.png} +0 -0
- /flowfile/web/static/assets/{old_join-5d0eb604.png → old_join-B9bkpPqv.png} +0 -0
- /flowfile/web/static/assets/{output-06ec0371.png → output-Dp7-ZpC4.png} +0 -0
- /flowfile/web/static/assets/{outputExcel-f5d272b2.css → outputExcel-CKgRe2iT.css} +0 -0
- /flowfile/web/static/assets/{outputParquet-54597c3c.css → outputParquet-d7j407cK.css} +0 -0
- /flowfile/web/static/assets/{pivot-9660df51.png → pivot-DSxKhNlD.png} +0 -0
- /flowfile/web/static/assets/{polars_code-05ce5dc6.png → polars_code-DxiztZ1c.png} +0 -0
- /flowfile/web/static/assets/{readCsv-3bfac4c3.css → readCsv-BG-1Jilp.css} +0 -0
- /flowfile/web/static/assets/{readExcel-3db6b763.css → readExcel-DBQXKPtC.css} +0 -0
- /flowfile/web/static/assets/{record_count-dab44eb5.png → record_count-DCeaLtpS.png} +0 -0
- /flowfile/web/static/assets/{record_id-0b15856b.png → record_id-FeUjyIFh.png} +0 -0
- /flowfile/web/static/assets/{sample-693a88b5.png → sample-DeqfRiB-.png} +0 -0
- /flowfile/web/static/assets/{select-b0d0437a.png → select-D4JjbdjS.png} +0 -0
- /flowfile/web/static/assets/{selectDynamic-f2fb394f.css → selectDynamic-CjeTPUUo.css} +0 -0
- /flowfile/web/static/assets/{sort-2aa579f0.png → sort-DGwUG9WS.png} +0 -0
- /flowfile/web/static/assets/{summarize-2a099231.png → summarize-DFaNHpfp.png} +0 -0
- /flowfile/web/static/assets/{text_to_rows-859b29ea.png → text_to_rows-BdiAewrN.png} +0 -0
- /flowfile/web/static/assets/{union-2d8609f4.png → union-DCK-LSMq.png} +0 -0
- /flowfile/web/static/assets/{unique-1958b98a.png → unique-CdP3zZIq.png} +0 -0
- /flowfile/web/static/assets/{unpivot-d3cb4b5b.png → unpivot-CHttrEt8.png} +0 -0
- /flowfile/web/static/assets/{user-defined-icon-0ae16c90.png → user-defined-icon-BcIp2Vzo.png} +0 -0
- /flowfile/web/static/assets/{view-7a0f0be1.png → view-DUSRwjvq.png} +0 -0
- {flowfile-0.5.6.dist-info → flowfile-0.6.1.dist-info}/entry_points.txt +0 -0
- {flowfile-0.5.6.dist-info → flowfile-0.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""Utility module for applying output field configuration to FlowDataEngine results."""
|
|
2
|
+
|
|
3
|
+
from typing import List, Set
|
|
4
|
+
import polars as pl
|
|
5
|
+
from flowfile_core.configs import logger
|
|
6
|
+
from flowfile_core.flowfile.flow_data_engine.flow_data_engine import FlowDataEngine
|
|
7
|
+
from flowfile_core.flowfile.flow_data_engine.flow_file_column.main import FlowfileColumn
|
|
8
|
+
from flowfile_core.flowfile.flow_data_engine.flow_file_column.utils import cast_str_to_polars_type
|
|
9
|
+
from flowfile_core.schemas.input_schema import OutputFieldConfig, OutputFieldInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _parse_default_value(field: OutputFieldInfo) -> pl.Expr:
|
|
13
|
+
"""Parse default value from field configuration.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
field: Output field info containing default_value
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Polars expression for the default value cast to the target data type
|
|
20
|
+
"""
|
|
21
|
+
# Get target Polars dtype from the field's data_type
|
|
22
|
+
target_dtype = cast_str_to_polars_type(field.data_type)
|
|
23
|
+
# Treat as literal value and cast to target type
|
|
24
|
+
return pl.lit(field.default_value).cast(target_dtype, strict=False, wrap_numerical=True)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _select_columns_in_order(df: pl.DataFrame, fields: list[OutputFieldInfo]) -> pl.DataFrame:
|
|
28
|
+
"""Select columns in the specified field order.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
df: Input dataframe
|
|
32
|
+
fields: List of fields specifying column order
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
DataFrame with columns selected in specified order
|
|
36
|
+
"""
|
|
37
|
+
return df.select([field.name for field in fields])
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _apply_raise_on_missing(
|
|
41
|
+
flowfile_engine: FlowDataEngine,
|
|
42
|
+
fields: list[OutputFieldInfo],
|
|
43
|
+
) -> FlowDataEngine:
|
|
44
|
+
"""Apply raise_on_missing validation mode.
|
|
45
|
+
|
|
46
|
+
Raises error if any expected columns are missing, then selects columns in order.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
flowfile_engine: Input flow data engine
|
|
50
|
+
fields: List of expected output fields
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Flow Data Engine with columns selected in specified order
|
|
54
|
+
|
|
55
|
+
Raises:
|
|
56
|
+
ValueError: If any expected columns are missing
|
|
57
|
+
"""
|
|
58
|
+
cols = [f.name for f in fields]
|
|
59
|
+
missing_columns = set(cols) - set(flowfile_engine.columns)
|
|
60
|
+
if missing_columns:
|
|
61
|
+
raise ValueError(f"Missing required columns: {', '.join(sorted(missing_columns))}")
|
|
62
|
+
if flowfile_engine.columns != cols:
|
|
63
|
+
return FlowDataEngine(_select_columns_in_order(flowfile_engine.data_frame, fields))
|
|
64
|
+
else:
|
|
65
|
+
return flowfile_engine
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _apply_add_missing(
|
|
69
|
+
engine: FlowDataEngine,
|
|
70
|
+
fields: list[OutputFieldInfo],
|
|
71
|
+
) -> FlowDataEngine:
|
|
72
|
+
"""Apply add_missing validation mode.
|
|
73
|
+
|
|
74
|
+
Adds missing columns with default values, then selects columns in order.
|
|
75
|
+
Extra columns not in the config are removed.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
engine: Input flow data engine
|
|
79
|
+
fields: List of expected output fields
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
FlowDataEngine with missing columns added and only configured columns in specified order
|
|
83
|
+
"""
|
|
84
|
+
# Add missing columns with default values
|
|
85
|
+
current_columns = set(engine.columns)
|
|
86
|
+
expressions = [_parse_default_value(field).alias(field.name)
|
|
87
|
+
for field in fields if field.name not in current_columns]
|
|
88
|
+
if expressions:
|
|
89
|
+
new_df = engine.data_frame.with_columns(expressions)
|
|
90
|
+
else:
|
|
91
|
+
new_df = engine.data_frame
|
|
92
|
+
return FlowDataEngine(_select_columns_in_order(new_df, fields))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _apply_add_missing_keep_extra(
|
|
96
|
+
engine: FlowDataEngine,
|
|
97
|
+
fields: list[OutputFieldInfo],
|
|
98
|
+
) -> FlowDataEngine:
|
|
99
|
+
"""Apply add_missing_keep_extra validation mode.
|
|
100
|
+
|
|
101
|
+
Adds missing columns with default values, but keeps all incoming columns.
|
|
102
|
+
Configured columns come first in specified order, followed by extra columns.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
engine: Input flow data engine
|
|
106
|
+
fields: List of expected output fields
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
FlowDataEngine with missing columns added and all columns preserved
|
|
110
|
+
(configured columns first, then extras)
|
|
111
|
+
"""
|
|
112
|
+
current_columns = set(engine.columns)
|
|
113
|
+
configured_names = {field.name for field in fields}
|
|
114
|
+
|
|
115
|
+
# Add missing columns with default values
|
|
116
|
+
expressions = [_parse_default_value(field).alias(field.name)
|
|
117
|
+
for field in fields if field.name not in current_columns]
|
|
118
|
+
if expressions:
|
|
119
|
+
new_df = engine.data_frame.with_columns(expressions)
|
|
120
|
+
else:
|
|
121
|
+
new_df = engine.data_frame
|
|
122
|
+
|
|
123
|
+
# Build column order: configured columns first (in order), then extras
|
|
124
|
+
configured_column_order = [field.name for field in fields]
|
|
125
|
+
extra_columns = [col for col in engine.columns if col not in configured_names]
|
|
126
|
+
|
|
127
|
+
final_column_order = configured_column_order + extra_columns
|
|
128
|
+
return FlowDataEngine(new_df.select(final_column_order))
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _validate_data_types(df: FlowDataEngine, fields: list[OutputFieldInfo]) -> None:
|
|
132
|
+
"""Validate that dataframe column types match expected types.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
df: Input dataframe or lazyframe
|
|
136
|
+
fields: List of expected output fields with data types
|
|
137
|
+
|
|
138
|
+
Raises:
|
|
139
|
+
ValueError: If any data type mismatches are found
|
|
140
|
+
"""
|
|
141
|
+
# Get schema (works for both DataFrame and LazyFrame)
|
|
142
|
+
schema: dict[str, FlowfileColumn] = {column.column_name: column for column in df.schema}
|
|
143
|
+
mismatches = []
|
|
144
|
+
for field in fields:
|
|
145
|
+
|
|
146
|
+
if field.name not in schema:
|
|
147
|
+
continue
|
|
148
|
+
# Use FlowfileColumn infrastructure to convert dtype to string
|
|
149
|
+
column = schema.get(field.name)
|
|
150
|
+
column.get_minimal_field_info()
|
|
151
|
+
if column.data_type != field.data_type:
|
|
152
|
+
mismatches.append(
|
|
153
|
+
f"Column '{field.name}': expected {field.data_type}, got {column.data_type}"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
if mismatches:
|
|
157
|
+
error_msg = "Data type validation failed:\n" + "\n".join(f" - {m}" for m in mismatches)
|
|
158
|
+
logger.error(error_msg)
|
|
159
|
+
raise ValueError(error_msg)
|
|
160
|
+
|
|
161
|
+
logger.info(f"Data type validation passed for {len(fields)} fields")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def apply_output_field_config(
|
|
165
|
+
flow_data_engine: FlowDataEngine, output_field_config: OutputFieldConfig
|
|
166
|
+
) -> FlowDataEngine:
|
|
167
|
+
"""Apply output field configuration to enforce schema requirements.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
flow_data_engine: The FlowDataEngine instance to apply configuration to
|
|
171
|
+
output_field_config: The output field configuration specifying behavior
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Modified FlowDataEngine with enforced schema
|
|
175
|
+
|
|
176
|
+
Raises:
|
|
177
|
+
ValueError: If raise_on_missing behavior is set and required columns are missing,
|
|
178
|
+
or if data type validation fails
|
|
179
|
+
"""
|
|
180
|
+
if not output_field_config or not output_field_config.enabled:
|
|
181
|
+
return flow_data_engine
|
|
182
|
+
|
|
183
|
+
if not output_field_config.fields:
|
|
184
|
+
return flow_data_engine
|
|
185
|
+
# breakpoint()
|
|
186
|
+
try:
|
|
187
|
+
# Get column sets for validation (works for both DataFrame and LazyFrame)
|
|
188
|
+
|
|
189
|
+
# Apply validation mode behavior
|
|
190
|
+
mode = output_field_config.validation_mode_behavior
|
|
191
|
+
if mode == "raise_on_missing":
|
|
192
|
+
new_flow_engine = _apply_raise_on_missing(flow_data_engine, output_field_config.fields)
|
|
193
|
+
elif mode == "add_missing":
|
|
194
|
+
new_flow_engine = _apply_add_missing(engine=flow_data_engine, fields=output_field_config.fields)
|
|
195
|
+
elif mode == "add_missing_keep_extra":
|
|
196
|
+
new_flow_engine = _apply_add_missing_keep_extra(engine=flow_data_engine, fields=output_field_config.fields)
|
|
197
|
+
elif mode == "select_only":
|
|
198
|
+
new_flow_engine = flow_data_engine.select_columns(
|
|
199
|
+
[field.name for field in output_field_config.fields]
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
raise ValueError(f"Unknown validation mode behavior: {mode}")
|
|
203
|
+
# Validate data types if enabled
|
|
204
|
+
if output_field_config.validate_data_types:
|
|
205
|
+
_validate_data_types(new_flow_engine, output_field_config.fields)
|
|
206
|
+
|
|
207
|
+
logger.info(
|
|
208
|
+
f"Applied output field config: behavior={mode}, "
|
|
209
|
+
f"fields={len(output_field_config.fields)}, "
|
|
210
|
+
f"validate_data_types={output_field_config.validate_data_types}"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
except Exception as e:
|
|
214
|
+
logger.error(f"Error applying output field config: {e}")
|
|
215
|
+
raise
|
|
216
|
+
|
|
217
|
+
return new_flow_engine
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Schema utilities for output field configuration."""
|
|
2
|
+
|
|
3
|
+
from flowfile_core.configs import logger
|
|
4
|
+
from flowfile_core.flowfile.flow_data_engine.flow_file_column.main import FlowfileColumn
|
|
5
|
+
from flowfile_core.schemas.input_schema import OutputFieldConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_schema_from_output_field_config(output_field_config: OutputFieldConfig) -> list[FlowfileColumn]:
|
|
9
|
+
"""Create a FlowfileColumn schema from OutputFieldConfig.
|
|
10
|
+
|
|
11
|
+
This is used for schema prediction - instead of running the transformation,
|
|
12
|
+
we can directly return the configured output schema.
|
|
13
|
+
|
|
14
|
+
Note: For 'add_missing_keep_extra' mode, this returns only the configured fields.
|
|
15
|
+
Extra columns from the incoming data are not predictable without running the flow,
|
|
16
|
+
so _predicted_data_getter provides more accurate results for that mode.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
output_field_config: The output field configuration
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
List of FlowfileColumn objects representing the expected output schema
|
|
23
|
+
"""
|
|
24
|
+
if not output_field_config or not output_field_config.enabled or not output_field_config.fields:
|
|
25
|
+
logger.debug("create_schema_from_output_field_config: config not enabled or no fields, returning None")
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
schema = [
|
|
29
|
+
FlowfileColumn.from_input(column_name=field.name, data_type=field.data_type)
|
|
30
|
+
for field in output_field_config.fields
|
|
31
|
+
]
|
|
32
|
+
logger.info(
|
|
33
|
+
f"create_schema_from_output_field_config: Created schema with {len(schema)} fields: "
|
|
34
|
+
f"{[f.name for f in schema]}"
|
|
35
|
+
)
|
|
36
|
+
return schema
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def create_schema_callback_with_output_config(
|
|
40
|
+
base_schema_callback: callable,
|
|
41
|
+
output_field_config: OutputFieldConfig | None
|
|
42
|
+
) -> callable:
|
|
43
|
+
"""Wraps a schema callback to use output_field_config when available.
|
|
44
|
+
|
|
45
|
+
This allows nodes to use their configured output schema for prediction
|
|
46
|
+
instead of running through transformation logic.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
base_schema_callback: The original schema callback function
|
|
50
|
+
output_field_config: The output field configuration, if any
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
A wrapped schema callback that prioritizes output_field_config
|
|
54
|
+
"""
|
|
55
|
+
logger.debug(
|
|
56
|
+
f"create_schema_callback_with_output_config called: "
|
|
57
|
+
f"base_callback={'present' if base_schema_callback else 'None'}, "
|
|
58
|
+
f"config={'enabled' if (output_field_config and output_field_config.enabled) else 'disabled/None'}"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def wrapped_schema_callback():
|
|
62
|
+
# If output_field_config is enabled, use it directly for schema prediction
|
|
63
|
+
if output_field_config and output_field_config.enabled and output_field_config.fields:
|
|
64
|
+
logger.info(
|
|
65
|
+
f"wrapped_schema_callback: Using output_field_config for schema prediction "
|
|
66
|
+
f"(validation_mode={output_field_config.validation_mode_behavior}, {len(output_field_config.fields)} fields)"
|
|
67
|
+
)
|
|
68
|
+
return create_schema_from_output_field_config(output_field_config)
|
|
69
|
+
|
|
70
|
+
# Otherwise fall back to the original schema callback
|
|
71
|
+
if base_schema_callback:
|
|
72
|
+
logger.debug("wrapped_schema_callback: Falling back to base_schema_callback")
|
|
73
|
+
return base_schema_callback()
|
|
74
|
+
else:
|
|
75
|
+
logger.warning("wrapped_schema_callback: No base_schema_callback and no output_field_config, returning None")
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
return wrapped_schema_callback
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Node execution state - separable from node definition.
|
|
3
|
+
Can be persisted to database/cache for stateless operation.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from collections.abc import Callable
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
import pyarrow as pa
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from flowfile_core.flowfile.flow_data_engine.flow_data_engine import FlowDataEngine
|
|
16
|
+
from flowfile_core.flowfile.flow_data_engine.flow_file_column.main import FlowfileColumn
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class SourceFileInfo:
|
|
21
|
+
"""
|
|
22
|
+
Tracks source file state for cache invalidation.
|
|
23
|
+
Used by read nodes to detect when source files change.
|
|
24
|
+
"""
|
|
25
|
+
path: str
|
|
26
|
+
mtime: float
|
|
27
|
+
size: int
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def from_path(cls, path: str) -> SourceFileInfo | None:
|
|
31
|
+
"""Create from file path, returns None if file doesn't exist."""
|
|
32
|
+
try:
|
|
33
|
+
stat = os.stat(path)
|
|
34
|
+
return cls(path=path, mtime=stat.st_mtime, size=stat.st_size)
|
|
35
|
+
except OSError:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def has_changed(self) -> bool:
|
|
39
|
+
"""Check if file has changed since this info was recorded."""
|
|
40
|
+
try:
|
|
41
|
+
stat = os.stat(self.path)
|
|
42
|
+
return stat.st_mtime != self.mtime or stat.st_size != self.size
|
|
43
|
+
except OSError:
|
|
44
|
+
return True # File missing = changed
|
|
45
|
+
|
|
46
|
+
def to_dict(self) -> dict:
|
|
47
|
+
"""Serialize for external storage."""
|
|
48
|
+
return {"path": self.path, "mtime": self.mtime, "size": self.size}
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, data: dict) -> SourceFileInfo:
|
|
52
|
+
"""Deserialize from external storage."""
|
|
53
|
+
return cls(path=data["path"], mtime=data["mtime"], size=data["size"])
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class NodeExecutionState:
|
|
58
|
+
"""
|
|
59
|
+
All mutable state for a node's execution.
|
|
60
|
+
|
|
61
|
+
This can be:
|
|
62
|
+
- Stored in memory (current behavior)
|
|
63
|
+
- Persisted to database (stateless workers)
|
|
64
|
+
- Stored in Redis/cache (distributed execution)
|
|
65
|
+
|
|
66
|
+
Kept separate from FlowNode to enable stateless execution patterns.
|
|
67
|
+
"""
|
|
68
|
+
# Execution tracking
|
|
69
|
+
has_run_with_current_setup: bool = False
|
|
70
|
+
has_completed_last_run: bool = False
|
|
71
|
+
is_canceled: bool = False
|
|
72
|
+
error: str | None = None
|
|
73
|
+
|
|
74
|
+
# Results (not serialized - too large)
|
|
75
|
+
resulting_data: FlowDataEngine | None = field(default=None, repr=False)
|
|
76
|
+
example_data_path: str | None = None
|
|
77
|
+
example_data_generator: Callable[[], pa.Table] | None = field(default=None, repr=False)
|
|
78
|
+
warnings: str | None = None
|
|
79
|
+
|
|
80
|
+
# Schema
|
|
81
|
+
result_schema: list[FlowfileColumn] | None = field(default=None, repr=False)
|
|
82
|
+
predicted_schema: list[FlowfileColumn] | None = field(default=None, repr=False)
|
|
83
|
+
|
|
84
|
+
# Source tracking (for read nodes)
|
|
85
|
+
source_file_info: SourceFileInfo | None = None
|
|
86
|
+
|
|
87
|
+
# Hash for cache lookup
|
|
88
|
+
execution_hash: str | None = None
|
|
89
|
+
|
|
90
|
+
def reset(self) -> None:
|
|
91
|
+
"""Reset to clean state for re-execution."""
|
|
92
|
+
self.has_run_with_current_setup = False
|
|
93
|
+
self.has_completed_last_run = False
|
|
94
|
+
self.is_canceled = False
|
|
95
|
+
self.error = None
|
|
96
|
+
self.resulting_data = None
|
|
97
|
+
self.example_data_path = None
|
|
98
|
+
self.example_data_generator = None
|
|
99
|
+
self.warnings = None
|
|
100
|
+
self.result_schema = None
|
|
101
|
+
self.predicted_schema = None
|
|
102
|
+
# Note: source_file_info intentionally NOT reset - needed for change detection
|
|
103
|
+
self.execution_hash = None
|
|
104
|
+
|
|
105
|
+
def reset_results_only(self) -> None:
|
|
106
|
+
"""Reset just the results, keep tracking state."""
|
|
107
|
+
self.error = None
|
|
108
|
+
self.resulting_data = None
|
|
109
|
+
self.example_data_path = None
|
|
110
|
+
self.example_data_generator = None
|
|
111
|
+
self.warnings = None
|
|
112
|
+
|
|
113
|
+
def mark_successful(self) -> None:
|
|
114
|
+
"""Mark execution as successful."""
|
|
115
|
+
self.has_run_with_current_setup = True
|
|
116
|
+
self.has_completed_last_run = True
|
|
117
|
+
self.error = None
|
|
118
|
+
|
|
119
|
+
def mark_failed(self, error: str) -> None:
|
|
120
|
+
"""Mark execution as failed."""
|
|
121
|
+
self.has_run_with_current_setup = False
|
|
122
|
+
self.has_completed_last_run = False
|
|
123
|
+
self.error = error
|
|
124
|
+
|
|
125
|
+
def to_dict(self) -> dict:
|
|
126
|
+
"""
|
|
127
|
+
Serialize for external storage (stateless mode).
|
|
128
|
+
Note: resulting_data and generators are not serialized.
|
|
129
|
+
"""
|
|
130
|
+
return {
|
|
131
|
+
"has_run_with_current_setup": self.has_run_with_current_setup,
|
|
132
|
+
"has_completed_last_run": self.has_completed_last_run,
|
|
133
|
+
"is_canceled": self.is_canceled,
|
|
134
|
+
"error": self.error,
|
|
135
|
+
"example_data_path": self.example_data_path,
|
|
136
|
+
"warnings": self.warnings,
|
|
137
|
+
"execution_hash": self.execution_hash,
|
|
138
|
+
"source_file_info": self.source_file_info.to_dict() if self.source_file_info else None,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def from_dict(cls, data: dict) -> NodeExecutionState:
|
|
143
|
+
"""Deserialize from external storage."""
|
|
144
|
+
state = cls(
|
|
145
|
+
has_run_with_current_setup=data.get("has_run_with_current_setup", False),
|
|
146
|
+
has_completed_last_run=data.get("has_completed_last_run", False),
|
|
147
|
+
is_canceled=data.get("is_canceled", False),
|
|
148
|
+
error=data.get("error"),
|
|
149
|
+
example_data_path=data.get("example_data_path"),
|
|
150
|
+
warnings=data.get("warnings"),
|
|
151
|
+
execution_hash=data.get("execution_hash"),
|
|
152
|
+
)
|
|
153
|
+
if data.get("source_file_info"):
|
|
154
|
+
state.source_file_info = SourceFileInfo.from_dict(data["source_file_info"])
|
|
155
|
+
return state
|