Flowfile 0.5.1__py3-none-any.whl → 0.5.3__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.
- build_backends/main.py +25 -22
- build_backends/main_prd.py +10 -19
- flowfile/__init__.py +178 -74
- flowfile/__main__.py +10 -7
- flowfile/api.py +51 -57
- flowfile/web/__init__.py +14 -9
- flowfile/web/static/assets/AdminView-49392a9a.js +713 -0
- flowfile/web/static/assets/AdminView-f53bad23.css +129 -0
- flowfile/web/static/assets/CloudConnectionView-36bcd6df.css +72 -0
- flowfile/web/static/assets/{CloudConnectionManager-0dfba9f2.js → CloudConnectionView-f13f202b.js} +11 -11
- flowfile/web/static/assets/{CloudStorageReader-d5b1b6c9.js → CloudStorageReader-0023d4a5.js} +10 -8
- flowfile/web/static/assets/{CloudStorageReader-29d14fcc.css → CloudStorageReader-24c54524.css} +27 -27
- flowfile/web/static/assets/{CloudStorageWriter-b0ee067f.css → CloudStorageWriter-60547855.css} +26 -26
- flowfile/web/static/assets/{CloudStorageWriter-00d87aad.js → CloudStorageWriter-8e781e11.js} +10 -8
- flowfile/web/static/assets/{ColumnSelector-47996a16.css → ColumnSelector-371637fb.css} +2 -2
- flowfile/web/static/assets/{ColumnSelector-4685e75d.js → ColumnSelector-8ad68ea9.js} +3 -5
- flowfile/web/static/assets/{ContextMenu-c13f91d0.css → ContextMenu-26d4dd27.css} +6 -6
- flowfile/web/static/assets/{ContextMenu-23e909da.js → ContextMenu-31ee57f0.js} +3 -3
- flowfile/web/static/assets/{ContextMenu-70ae0c79.js → ContextMenu-69a74055.js} +3 -3
- flowfile/web/static/assets/{ContextMenu-f149cf7c.js → ContextMenu-8e2051c6.js} +3 -3
- flowfile/web/static/assets/{ContextMenu-4c74eef1.css → ContextMenu-8ec1729e.css} +6 -6
- flowfile/web/static/assets/{ContextMenu-63cfa99b.css → ContextMenu-9b310c60.css} +6 -6
- flowfile/web/static/assets/{CrossJoin-702a3edd.js → CrossJoin-03df6938.js} +12 -10
- flowfile/web/static/assets/{CrossJoin-1119d18e.css → CrossJoin-71b4cc10.css} +20 -20
- flowfile/web/static/assets/CustomNode-59e99a86.css +32 -0
- flowfile/web/static/assets/{CustomNode-b1519993.js → CustomNode-8479239b.js} +36 -24
- flowfile/web/static/assets/{DatabaseConnectionSettings-6f3e4ea5.js → DatabaseConnectionSettings-869e3efd.js} +5 -4
- flowfile/web/static/assets/{DatabaseConnectionSettings-0c04b2e5.css → DatabaseConnectionSettings-e91df89a.css} +13 -13
- flowfile/web/static/assets/{DatabaseReader-ae61773c.css → DatabaseReader-36898a00.css} +24 -24
- flowfile/web/static/assets/{DatabaseReader-d38c7295.js → DatabaseReader-c58b9552.js} +25 -15
- flowfile/web/static/assets/DatabaseView-6655afd6.css +57 -0
- flowfile/web/static/assets/{DatabaseManager-cf5ef661.js → DatabaseView-d26a9140.js} +11 -11
- flowfile/web/static/assets/{DatabaseWriter-2f570e53.css → DatabaseWriter-217a99f1.css} +19 -19
- flowfile/web/static/assets/{DatabaseWriter-b04ef46a.js → DatabaseWriter-4d05ddc7.js} +17 -10
- flowfile/web/static/assets/{designer-8da3ba3a.css → DesignerView-a6d0ee84.css} +614 -546
- flowfile/web/static/assets/{designer-9633482a.js → DesignerView-e6f5c0e8.js} +1107 -3170
- flowfile/web/static/assets/{documentation-ca400224.js → DocumentationView-2e78ef1b.js} +5 -5
- flowfile/web/static/assets/{documentation-12216a74.css → DocumentationView-fd46c656.css} +7 -7
- flowfile/web/static/assets/{ExploreData-2d0cf4db.css → ExploreData-10c5acc8.css} +13 -12
- flowfile/web/static/assets/{ExploreData-5fa10ed8.js → ExploreData-7b54caca.js} +18 -9
- flowfile/web/static/assets/{ExternalSource-d39af878.js → ExternalSource-3fa399b2.js} +9 -7
- flowfile/web/static/assets/{ExternalSource-e37b6275.css → ExternalSource-47ab05a3.css} +17 -17
- flowfile/web/static/assets/Filter-7494ea97.css +48 -0
- flowfile/web/static/assets/Filter-8cbbdbf3.js +287 -0
- flowfile/web/static/assets/{Formula-bb96803d.css → Formula-53d58c43.css} +7 -7
- flowfile/web/static/assets/{Formula-6b04fb1d.js → Formula-aac42b1e.js} +13 -11
- flowfile/web/static/assets/{FuzzyMatch-1010f966.css → FuzzyMatch-ad6361d6.css} +68 -69
- flowfile/web/static/assets/{FuzzyMatch-999521f4.js → FuzzyMatch-cd9bbfca.js} +12 -10
- flowfile/web/static/assets/{Pivot-cf333e3d.css → GraphSolver-c24dec17.css} +5 -5
- flowfile/web/static/assets/{GraphSolver-17dd2198.js → GraphSolver-c7e6780e.js} +13 -11
- flowfile/web/static/assets/{GroupBy-6b039e18.js → GroupBy-93c5d22b.js} +9 -7
- flowfile/web/static/assets/{GroupBy-b9505323.css → GroupBy-be7ac0bf.css} +10 -10
- flowfile/web/static/assets/{Join-fd79b451.css → Join-28b5e18f.css} +22 -22
- flowfile/web/static/assets/{Join-24d0f113.js → Join-a19b2de2.js} +13 -11
- flowfile/web/static/assets/LoginView-0df4ed0a.js +134 -0
- flowfile/web/static/assets/LoginView-d325d632.css +172 -0
- flowfile/web/static/assets/ManualInput-3702e677.css +293 -0
- flowfile/web/static/assets/{ManualInput-34639209.js → ManualInput-8d3374b2.js} +170 -116
- flowfile/web/static/assets/{MultiSelect-0e8724a3.js → MultiSelect-ad1b6243.js} +2 -2
- flowfile/web/static/assets/{MultiSelect.vue_vue_type_script_setup_true_lang-b0e538c2.js → MultiSelect.vue_vue_type_script_setup_true_lang-e278950d.js} +1 -1
- flowfile/web/static/assets/NodeDesigner-40b647c9.js +2610 -0
- flowfile/web/static/assets/NodeDesigner-5f53be3f.css +1429 -0
- flowfile/web/static/assets/{NumericInput-3d63a470.js → NumericInput-7100234c.js} +2 -2
- flowfile/web/static/assets/{NumericInput.vue_vue_type_script_setup_true_lang-e0edeccc.js → NumericInput.vue_vue_type_script_setup_true_lang-5130219f.js} +5 -2
- flowfile/web/static/assets/{Output-283fe388.css → Output-35e97000.css} +6 -6
- flowfile/web/static/assets/{Output-edea9802.js → Output-f5efd2aa.js} +12 -9
- flowfile/web/static/assets/{GraphSolver-f0cb7bfb.css → Pivot-0eda81b4.css} +5 -5
- flowfile/web/static/assets/{Pivot-61d19301.js → Pivot-d981d23c.js} +11 -9
- flowfile/web/static/assets/PivotValidation-0e905b1a.css +13 -0
- flowfile/web/static/assets/{PivotValidation-f97fec5b.js → PivotValidation-39386e95.js} +3 -3
- flowfile/web/static/assets/PivotValidation-41b57ad6.css +13 -0
- flowfile/web/static/assets/{PivotValidation-de9f43fe.js → PivotValidation-63de1f73.js} +3 -3
- flowfile/web/static/assets/{PolarsCode-650322d1.css → PolarsCode-2b1f1f23.css} +4 -4
- flowfile/web/static/assets/{PolarsCode-bc3c9984.js → PolarsCode-f9d69217.js} +18 -9
- flowfile/web/static/assets/PopOver-b22f049e.js +939 -0
- flowfile/web/static/assets/PopOver-d96599db.css +33 -0
- flowfile/web/static/assets/{Read-e808b239.css → Read-36e7bd51.css} +12 -12
- flowfile/web/static/assets/{Read-64a3f259.js → Read-aec2e377.js} +14 -11
- flowfile/web/static/assets/{RecordCount-3d5039be.js → RecordCount-78ed6845.js} +6 -4
- flowfile/web/static/assets/{RecordId-597510e0.js → RecordId-2156e890.js} +8 -6
- flowfile/web/static/assets/{SQLQueryComponent-36cef432.css → SQLQueryComponent-1c2f26b4.css} +5 -5
- flowfile/web/static/assets/{SQLQueryComponent-df51adbe.js → SQLQueryComponent-48c72f5b.js} +3 -3
- flowfile/web/static/assets/{Sample-4be0a507.js → Sample-1352ca74.js} +6 -4
- flowfile/web/static/assets/SecretSelector-22b5ff89.js +113 -0
- flowfile/web/static/assets/SecretSelector-6329f743.css +43 -0
- flowfile/web/static/assets/{SecretManager-4839be57.js → SecretsView-17df66ee.js} +35 -36
- flowfile/web/static/assets/SecretsView-aa291340.css +38 -0
- flowfile/web/static/assets/{Select-9b72f201.js → Select-0aee4c54.js} +9 -7
- flowfile/web/static/assets/{SettingsSection-f0f75a42.js → SettingsSection-0784e157.js} +3 -3
- flowfile/web/static/assets/{SettingsSection-71e6b7e3.css → SettingsSection-07fbbc39.css} +4 -4
- flowfile/web/static/assets/{SettingsSection-5c696bee.css → SettingsSection-26fe48d4.css} +4 -4
- flowfile/web/static/assets/{SettingsSection-2e4d03c4.css → SettingsSection-8f980839.css} +4 -4
- flowfile/web/static/assets/{SettingsSection-e1e9c953.js → SettingsSection-cd341bb6.js} +3 -3
- flowfile/web/static/assets/{SettingsSection-7ded385d.js → SettingsSection-f2002a6d.js} +3 -3
- flowfile/web/static/assets/{SingleSelect-6c777aac.js → SingleSelect-460cc0ea.js} +2 -2
- flowfile/web/static/assets/{SingleSelect.vue_vue_type_script_setup_true_lang-33e3ff9b.js → SingleSelect.vue_vue_type_script_setup_true_lang-30741bb2.js} +1 -1
- flowfile/web/static/assets/{SliderInput-7cb93e62.js → SliderInput-5d926864.js} +7 -4
- flowfile/web/static/assets/SliderInput-f2e4f23c.css +4 -0
- flowfile/web/static/assets/{Sort-6cbde21a.js → Sort-3cdc971b.js} +9 -7
- flowfile/web/static/assets/{Unique-f9fb0809.css → Sort-8a871341.css} +10 -10
- flowfile/web/static/assets/{TextInput-d9a40c11.js → TextInput-a2d0bfbd.js} +2 -2
- flowfile/web/static/assets/{TextInput.vue_vue_type_script_setup_true_lang-5896c375.js → TextInput.vue_vue_type_script_setup_true_lang-abad1ca2.js} +5 -2
- flowfile/web/static/assets/{TextToRows-5d2c1190.css → TextToRows-12afb4f4.css} +10 -10
- flowfile/web/static/assets/{TextToRows-c4fcbf4d.js → TextToRows-918945f7.js} +11 -10
- flowfile/web/static/assets/{ToggleSwitch-4ef91d19.js → ToggleSwitch-f0ef5196.js} +2 -2
- flowfile/web/static/assets/{ToggleSwitch.vue_vue_type_script_setup_true_lang-38478c20.js → ToggleSwitch.vue_vue_type_script_setup_true_lang-5605c793.js} +1 -1
- flowfile/web/static/assets/{UnavailableFields-5edd5322.css → UnavailableFields-54d2f518.css} +6 -6
- flowfile/web/static/assets/{UnavailableFields-a03f512c.js → UnavailableFields-bdad6144.js} +4 -4
- flowfile/web/static/assets/{Union-af6c3d9b.css → Union-d6a8d7d5.css} +7 -7
- flowfile/web/static/assets/{Union-bfe9b996.js → Union-e8ab8c86.js} +8 -6
- flowfile/web/static/assets/{Unique-5d023a27.js → Unique-8cd4f976.js} +13 -10
- flowfile/web/static/assets/{Sort-3643d625.css → Unique-9fb2f567.css} +10 -10
- flowfile/web/static/assets/{Unpivot-1e422df3.css → Unpivot-710a2948.css} +7 -7
- flowfile/web/static/assets/{Unpivot-91cc5354.js → Unpivot-8da14095.js} +10 -8
- flowfile/web/static/assets/{UnpivotValidation-7ee2de44.js → UnpivotValidation-6f7d89ff.js} +3 -3
- flowfile/web/static/assets/UnpivotValidation-d5ca3b7b.css +13 -0
- flowfile/web/static/assets/{VueGraphicWalker-e51b9924.js → VueGraphicWalker-3fb312e1.js} +4 -4
- flowfile/web/static/assets/{VueGraphicWalker-ed5ab88b.css → VueGraphicWalker-430f0b86.css} +1 -1
- flowfile/web/static/assets/{api-cf1221f0.js → api-24483f0d.js} +1 -1
- flowfile/web/static/assets/{api-c1bad5ca.js → api-8b81fa73.js} +1 -1
- flowfile/web/static/assets/{dropDown-35135ba8.css → dropDown-3d8dc5fa.css} +40 -40
- flowfile/web/static/assets/{dropDown-614b998d.js → dropDown-ac0fda9d.js} +3 -3
- flowfile/web/static/assets/{fullEditor-f7971590.js → fullEditor-5497a84a.js} +11 -10
- flowfile/web/static/assets/{fullEditor-178376bb.css → fullEditor-a0be62b3.css} +74 -62
- flowfile/web/static/assets/{genericNodeSettings-924759c7.css → genericNodeSettings-3b2507ea.css} +10 -10
- flowfile/web/static/assets/{genericNodeSettings-4fe5f36b.js → genericNodeSettings-99014e1d.js} +5 -5
- flowfile/web/static/assets/index-07dda503.js +38 -0
- flowfile/web/static/assets/index-3ba44389.js +2696 -0
- flowfile/web/static/assets/{index-50508d4d.css → index-e6289dd0.css} +1945 -569
- flowfile/web/static/assets/{index-5429bbf8.js → index-fb6493ae.js} +41626 -40867
- flowfile/web/static/assets/node.types-2c15bb7e.js +82 -0
- flowfile/web/static/assets/nodeInput-0eb13f1a.js +2 -0
- flowfile/web/static/assets/{outputCsv-076b85ab.js → outputCsv-8f8ba42d.js} +3 -3
- flowfile/web/static/assets/outputCsv-b9a072af.css +2499 -0
- flowfile/web/static/assets/{outputExcel-0fd17dbe.js → outputExcel-393f4fef.js} +3 -3
- flowfile/web/static/assets/{outputExcel-b41305c0.css → outputExcel-f5d272b2.css} +26 -26
- flowfile/web/static/assets/{outputParquet-b61e0847.js → outputParquet-07c81f65.js} +4 -4
- flowfile/web/static/assets/outputParquet-54597c3c.css +4 -0
- flowfile/web/static/assets/{readCsv-a8bb8b61.js → readCsv-07f6d9ad.js} +3 -3
- flowfile/web/static/assets/{readCsv-c767cb37.css → readCsv-3bfac4c3.css} +15 -15
- flowfile/web/static/assets/{readExcel-806d2826.css → readExcel-3db6b763.css} +13 -13
- flowfile/web/static/assets/{readExcel-67b4aee0.js → readExcel-ed69bc8f.js} +5 -5
- flowfile/web/static/assets/{readParquet-48c81530.css → readParquet-c5244ad5.css} +4 -4
- flowfile/web/static/assets/{readParquet-92ce1dbc.js → readParquet-e3ed4528.js} +3 -3
- flowfile/web/static/assets/secrets.api-002e7d7e.js +65 -0
- flowfile/web/static/assets/{selectDynamic-92e25ee3.js → selectDynamic-80b92899.js} +5 -5
- flowfile/web/static/assets/{selectDynamic-aa913ff4.css → selectDynamic-f2fb394f.css} +21 -20
- flowfile/web/static/assets/{vue-codemirror.esm-41b0e0d7.js → vue-codemirror.esm-0965f39f.js} +31 -640
- flowfile/web/static/assets/{vue-content-loader.es-2c8e608f.js → vue-content-loader.es-c506ad97.js} +1 -1
- flowfile/web/static/index.html +2 -2
- {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/METADATA +2 -3
- flowfile-0.5.3.dist-info/RECORD +402 -0
- flowfile_core/__init__.py +13 -6
- flowfile_core/auth/jwt.py +51 -16
- flowfile_core/auth/models.py +32 -7
- flowfile_core/auth/password.py +89 -0
- flowfile_core/auth/secrets.py +8 -6
- flowfile_core/configs/__init__.py +9 -7
- flowfile_core/configs/flow_logger.py +15 -14
- flowfile_core/configs/node_store/__init__.py +72 -4
- flowfile_core/configs/node_store/nodes.py +155 -172
- flowfile_core/configs/node_store/user_defined_node_registry.py +108 -27
- flowfile_core/configs/settings.py +28 -15
- flowfile_core/database/connection.py +7 -6
- flowfile_core/database/init_db.py +96 -2
- flowfile_core/database/models.py +3 -1
- flowfile_core/fileExplorer/__init__.py +17 -0
- flowfile_core/fileExplorer/funcs.py +123 -57
- flowfile_core/fileExplorer/utils.py +10 -11
- flowfile_core/flowfile/_extensions/real_time_interface.py +10 -8
- flowfile_core/flowfile/analytics/analytics_processor.py +26 -24
- flowfile_core/flowfile/analytics/graphic_walker.py +11 -12
- flowfile_core/flowfile/analytics/utils.py +1 -1
- flowfile_core/flowfile/code_generator/code_generator.py +358 -244
- flowfile_core/flowfile/connection_manager/_connection_manager.py +6 -5
- flowfile_core/flowfile/connection_manager/models.py +1 -1
- flowfile_core/flowfile/database_connection_manager/db_connections.py +60 -44
- flowfile_core/flowfile/database_connection_manager/models.py +1 -1
- flowfile_core/flowfile/extensions.py +17 -12
- flowfile_core/flowfile/flow_data_engine/cloud_storage_reader.py +34 -32
- flowfile_core/flowfile/flow_data_engine/create/funcs.py +115 -83
- flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +481 -423
- flowfile_core/flowfile/flow_data_engine/flow_file_column/interface.py +2 -2
- flowfile_core/flowfile/flow_data_engine/flow_file_column/main.py +92 -52
- flowfile_core/flowfile/flow_data_engine/flow_file_column/polars_type.py +12 -11
- flowfile_core/flowfile/flow_data_engine/flow_file_column/type_registry.py +6 -6
- flowfile_core/flowfile/flow_data_engine/flow_file_column/utils.py +26 -30
- flowfile_core/flowfile/flow_data_engine/fuzzy_matching/prepare_for_fuzzy_match.py +31 -20
- flowfile_core/flowfile/flow_data_engine/join/__init__.py +1 -1
- flowfile_core/flowfile/flow_data_engine/join/utils.py +11 -9
- flowfile_core/flowfile/flow_data_engine/join/verify_integrity.py +14 -15
- flowfile_core/flowfile/flow_data_engine/pivot_table.py +5 -7
- flowfile_core/flowfile/flow_data_engine/polars_code_parser.py +95 -82
- flowfile_core/flowfile/flow_data_engine/read_excel_tables.py +66 -65
- flowfile_core/flowfile/flow_data_engine/sample_data.py +27 -21
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/__init__.py +1 -1
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/models.py +13 -11
- flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +190 -127
- flowfile_core/flowfile/flow_data_engine/threaded_processes.py +8 -8
- flowfile_core/flowfile/flow_data_engine/utils.py +99 -67
- flowfile_core/flowfile/flow_graph.py +918 -571
- flowfile_core/flowfile/flow_graph_utils.py +31 -49
- flowfile_core/flowfile/flow_node/flow_node.py +330 -233
- flowfile_core/flowfile/flow_node/models.py +53 -41
- flowfile_core/flowfile/flow_node/schema_callback.py +14 -19
- flowfile_core/flowfile/graph_tree/graph_tree.py +41 -41
- flowfile_core/flowfile/handler.py +80 -30
- flowfile_core/flowfile/manage/compatibility_enhancements.py +209 -126
- flowfile_core/flowfile/manage/io_flowfile.py +54 -57
- flowfile_core/flowfile/node_designer/__init__.py +15 -13
- flowfile_core/flowfile/node_designer/_type_registry.py +34 -37
- flowfile_core/flowfile/node_designer/custom_node.py +162 -36
- flowfile_core/flowfile/node_designer/ui_components.py +135 -34
- flowfile_core/flowfile/schema_callbacks.py +71 -51
- flowfile_core/flowfile/setting_generator/__init__.py +0 -1
- flowfile_core/flowfile/setting_generator/setting_generator.py +6 -5
- flowfile_core/flowfile/setting_generator/settings.py +64 -53
- flowfile_core/flowfile/sources/external_sources/base_class.py +12 -10
- flowfile_core/flowfile/sources/external_sources/custom_external_sources/external_source.py +27 -17
- flowfile_core/flowfile/sources/external_sources/custom_external_sources/sample_users.py +9 -9
- flowfile_core/flowfile/sources/external_sources/factory.py +0 -1
- flowfile_core/flowfile/sources/external_sources/sql_source/models.py +45 -31
- flowfile_core/flowfile/sources/external_sources/sql_source/sql_source.py +198 -73
- flowfile_core/flowfile/sources/external_sources/sql_source/utils.py +250 -196
- flowfile_core/flowfile/util/calculate_layout.py +9 -13
- flowfile_core/flowfile/util/execution_orderer.py +25 -17
- flowfile_core/flowfile/util/node_skipper.py +4 -4
- flowfile_core/flowfile/utils.py +19 -21
- flowfile_core/main.py +26 -19
- flowfile_core/routes/auth.py +284 -11
- flowfile_core/routes/cloud_connections.py +25 -25
- flowfile_core/routes/logs.py +21 -29
- flowfile_core/routes/public.py +3 -3
- flowfile_core/routes/routes.py +70 -34
- flowfile_core/routes/secrets.py +25 -27
- flowfile_core/routes/user_defined_components.py +483 -4
- flowfile_core/run_lock.py +0 -1
- flowfile_core/schemas/__init__.py +4 -6
- flowfile_core/schemas/analysis_schemas/graphic_walker_schemas.py +55 -55
- flowfile_core/schemas/cloud_storage_schemas.py +59 -53
- flowfile_core/schemas/input_schema.py +231 -144
- flowfile_core/schemas/output_model.py +49 -34
- flowfile_core/schemas/schemas.py +116 -89
- flowfile_core/schemas/transform_schema.py +518 -263
- flowfile_core/schemas/yaml_types.py +21 -7
- flowfile_core/secret_manager/secret_manager.py +17 -13
- flowfile_core/types.py +29 -9
- flowfile_core/utils/arrow_reader.py +7 -6
- flowfile_core/utils/excel_file_manager.py +3 -3
- flowfile_core/utils/fileManager.py +7 -7
- flowfile_core/utils/fl_executor.py +8 -10
- flowfile_core/utils/utils.py +4 -4
- flowfile_core/utils/validate_setup.py +5 -4
- flowfile_frame/__init__.py +106 -51
- flowfile_frame/adapters.py +2 -9
- flowfile_frame/adding_expr.py +73 -32
- flowfile_frame/cloud_storage/frame_helpers.py +27 -23
- flowfile_frame/cloud_storage/secret_manager.py +12 -26
- flowfile_frame/config.py +2 -5
- flowfile_frame/expr.py +311 -218
- flowfile_frame/expr.pyi +160 -159
- flowfile_frame/expr_name.py +23 -23
- flowfile_frame/flow_frame.py +571 -476
- flowfile_frame/flow_frame.pyi +123 -104
- flowfile_frame/flow_frame_methods.py +227 -246
- flowfile_frame/group_frame.py +50 -20
- flowfile_frame/join.py +2 -2
- flowfile_frame/lazy.py +129 -87
- flowfile_frame/lazy_methods.py +83 -30
- flowfile_frame/list_name_space.py +55 -50
- flowfile_frame/selectors.py +148 -68
- flowfile_frame/series.py +9 -7
- flowfile_frame/utils.py +19 -21
- flowfile_worker/__init__.py +12 -7
- flowfile_worker/configs.py +11 -19
- flowfile_worker/create/__init__.py +14 -9
- flowfile_worker/create/funcs.py +114 -77
- flowfile_worker/create/models.py +46 -43
- flowfile_worker/create/pl_types.py +14 -15
- flowfile_worker/create/read_excel_tables.py +34 -41
- flowfile_worker/create/utils.py +22 -19
- flowfile_worker/external_sources/s3_source/main.py +18 -51
- flowfile_worker/external_sources/s3_source/models.py +34 -27
- flowfile_worker/external_sources/sql_source/main.py +8 -5
- flowfile_worker/external_sources/sql_source/models.py +13 -9
- flowfile_worker/flow_logger.py +10 -8
- flowfile_worker/funcs.py +214 -155
- flowfile_worker/main.py +11 -17
- flowfile_worker/models.py +35 -28
- flowfile_worker/process_manager.py +2 -3
- flowfile_worker/routes.py +121 -90
- flowfile_worker/secrets.py +9 -6
- flowfile_worker/spawner.py +80 -49
- flowfile_worker/utils.py +3 -2
- shared/__init__.py +2 -7
- shared/storage_config.py +25 -13
- test_utils/postgres/commands.py +3 -2
- test_utils/postgres/fixtures.py +9 -9
- test_utils/s3/commands.py +1 -1
- test_utils/s3/data_generator.py +3 -4
- test_utils/s3/demo_data_generator.py +4 -7
- test_utils/s3/fixtures.py +7 -5
- tools/migrate/__init__.py +1 -1
- tools/migrate/__main__.py +16 -29
- tools/migrate/legacy_schemas.py +251 -190
- tools/migrate/migrate.py +193 -181
- tools/migrate/tests/conftest.py +1 -3
- tools/migrate/tests/test_migrate.py +36 -41
- tools/migrate/tests/test_migration_e2e.py +28 -29
- tools/migrate/tests/test_node_migrations.py +50 -20
- flowfile/web/static/assets/CloudConnectionManager-2dfdce2f.css +0 -86
- flowfile/web/static/assets/CustomNode-74a37f74.css +0 -32
- flowfile/web/static/assets/DatabaseManager-30fa27e5.css +0 -64
- flowfile/web/static/assets/Filter-9b6d08db.js +0 -164
- flowfile/web/static/assets/Filter-f62091b3.css +0 -20
- flowfile/web/static/assets/ManualInput-3246a08d.css +0 -96
- flowfile/web/static/assets/PivotValidation-891ddfb0.css +0 -13
- flowfile/web/static/assets/PivotValidation-c46cd420.css +0 -13
- flowfile/web/static/assets/SliderInput-b8fb6a8c.css +0 -4
- flowfile/web/static/assets/UnpivotValidation-0d240eeb.css +0 -13
- flowfile/web/static/assets/nodeInput-5d0d6b79.js +0 -41
- flowfile/web/static/assets/outputCsv-9cc59e0b.css +0 -2499
- flowfile/web/static/assets/outputParquet-cf8cf3f2.css +0 -4
- flowfile/web/static/assets/secretApi-68435402.js +0 -46
- flowfile/web/static/assets/vue-codemirror-bccfde04.css +0 -32
- flowfile-0.5.1.dist-info/RECORD +0 -388
- {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/WHEEL +0 -0
- {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/entry_points.txt +0 -0
- {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/licenses/LICENSE +0 -0
flowfile_frame/selectors.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import List, Union, TYPE_CHECKING # Added TYPE_CHECKING
|
|
2
|
-
|
|
3
1
|
import polars as pl
|
|
4
2
|
|
|
5
3
|
# --- TYPE CHECKING IMPORTS ---
|
|
@@ -7,11 +5,12 @@ import polars as pl
|
|
|
7
5
|
# Import Expr only for type hints
|
|
8
6
|
from flowfile_frame.expr import Expr
|
|
9
7
|
|
|
10
|
-
|
|
11
8
|
# --- Selector Base Classes (Compound, Complement) ---
|
|
12
9
|
|
|
10
|
+
|
|
13
11
|
class Selector:
|
|
14
12
|
"""Base class for column selectors, inspired by polars.selectors"""
|
|
13
|
+
|
|
15
14
|
def __init__(self):
|
|
16
15
|
self._repr_str = self._get_repr_str() # Use base repr calculation method
|
|
17
16
|
# No agg_func state stored here anymore
|
|
@@ -28,25 +27,25 @@ class Selector:
|
|
|
28
27
|
def __repr__(self) -> str:
|
|
29
28
|
return self._repr_str
|
|
30
29
|
|
|
31
|
-
def __or__(self, other:
|
|
32
|
-
return CompoundSelector(self, other,
|
|
30
|
+
def __or__(self, other: "Selector") -> "CompoundSelector":
|
|
31
|
+
return CompoundSelector(self, other, "union")
|
|
33
32
|
|
|
34
|
-
def __and__(self, other:
|
|
35
|
-
return CompoundSelector(self, other,
|
|
33
|
+
def __and__(self, other: "Selector") -> "CompoundSelector":
|
|
34
|
+
return CompoundSelector(self, other, "intersection")
|
|
36
35
|
|
|
37
|
-
def __sub__(self, other:
|
|
38
|
-
return CompoundSelector(self, other,
|
|
36
|
+
def __sub__(self, other: "Selector") -> "CompoundSelector":
|
|
37
|
+
return CompoundSelector(self, other, "difference")
|
|
39
38
|
|
|
40
|
-
def __xor__(self, other:
|
|
41
|
-
return CompoundSelector(self, other,
|
|
39
|
+
def __xor__(self, other: "Selector") -> "CompoundSelector":
|
|
40
|
+
return CompoundSelector(self, other, "symmetric_difference")
|
|
42
41
|
|
|
43
|
-
def __invert__(self) ->
|
|
42
|
+
def __invert__(self) -> "ComplementSelector":
|
|
44
43
|
return ComplementSelector(self)
|
|
45
44
|
|
|
46
45
|
# --- Aggregation Methods ---
|
|
47
46
|
# These methods now return Expr objects, importing Expr locally
|
|
48
47
|
|
|
49
|
-
def sum(self) ->
|
|
48
|
+
def sum(self) -> "Expr":
|
|
50
49
|
"""Create an expression to sum columns selected by this selector."""
|
|
51
50
|
# Expr init will handle creating the 'pl.sum(selector)' repr
|
|
52
51
|
return Expr(expr=None, selector=self, agg_func="sum")
|
|
@@ -54,43 +53,43 @@ class Selector:
|
|
|
54
53
|
def expr(self):
|
|
55
54
|
return eval(self.repr_str)
|
|
56
55
|
|
|
57
|
-
def mean(self) ->
|
|
56
|
+
def mean(self) -> "Expr":
|
|
58
57
|
"""Create an expression to average columns selected by this selector."""
|
|
59
58
|
return Expr(expr=None, selector=self, agg_func="mean")
|
|
60
59
|
|
|
61
|
-
def median(self) ->
|
|
60
|
+
def median(self) -> "Expr":
|
|
62
61
|
"""Create an expression to find the median of columns selected by this selector."""
|
|
63
62
|
return Expr(expr=None, selector=self, agg_func="median")
|
|
64
63
|
|
|
65
|
-
def min(self) ->
|
|
64
|
+
def min(self) -> "Expr":
|
|
66
65
|
"""Create an expression to find the minimum of columns selected by this selector."""
|
|
67
66
|
return Expr(expr=None, selector=self, agg_func="min")
|
|
68
67
|
|
|
69
|
-
def max(self) ->
|
|
68
|
+
def max(self) -> "Expr":
|
|
70
69
|
"""Create an expression to find the maximum of columns selected by this selector."""
|
|
71
70
|
return Expr(expr=None, selector=self, agg_func="max")
|
|
72
71
|
|
|
73
|
-
def std(self, ddof: int = 1) ->
|
|
72
|
+
def std(self, ddof: int = 1) -> "Expr":
|
|
74
73
|
"""Create an expression to find the standard deviation of columns selected by this selector."""
|
|
75
74
|
return Expr(expr=None, selector=self, agg_func="std", ddof=ddof)
|
|
76
75
|
|
|
77
|
-
def var(self, ddof: int = 1) ->
|
|
76
|
+
def var(self, ddof: int = 1) -> "Expr":
|
|
78
77
|
"""Create an expression to find the variance of columns selected by this selector."""
|
|
79
78
|
return Expr(expr=None, selector=self, agg_func="var", ddof=ddof)
|
|
80
79
|
|
|
81
|
-
def first(self) ->
|
|
80
|
+
def first(self) -> "Expr":
|
|
82
81
|
"""Create an expression to get the first element of columns selected by this selector."""
|
|
83
82
|
return Expr(expr=None, selector=self, agg_func="first")
|
|
84
83
|
|
|
85
|
-
def last(self) ->
|
|
84
|
+
def last(self) -> "Expr":
|
|
86
85
|
"""Create an expression to get the last element of columns selected by this selector."""
|
|
87
86
|
return Expr(expr=None, selector=self, agg_func="last")
|
|
88
87
|
|
|
89
|
-
def count(self) ->
|
|
88
|
+
def count(self) -> "Expr":
|
|
90
89
|
"""Create an expression to count elements in columns selected by this selector."""
|
|
91
90
|
return Expr(expr=None, selector=self, agg_func="count")
|
|
92
91
|
|
|
93
|
-
def n_unique(self) ->
|
|
92
|
+
def n_unique(self) -> "Expr":
|
|
94
93
|
"""Create an expression to count unique elements in columns selected by this selector."""
|
|
95
94
|
return Expr(expr=None, selector=self, agg_func="n_unique")
|
|
96
95
|
|
|
@@ -99,6 +98,7 @@ class Selector:
|
|
|
99
98
|
|
|
100
99
|
class CompoundSelector(Selector):
|
|
101
100
|
"""Selector representing a compound operation between two selectors"""
|
|
101
|
+
|
|
102
102
|
def __init__(self, left: Selector, right: Selector, operation: str):
|
|
103
103
|
self.left = left
|
|
104
104
|
self.right = right
|
|
@@ -106,8 +106,8 @@ class CompoundSelector(Selector):
|
|
|
106
106
|
super().__init__()
|
|
107
107
|
|
|
108
108
|
def _get_repr_str(self) -> str:
|
|
109
|
-
op_map = {
|
|
110
|
-
op_symbol = op_map.get(self.operation,
|
|
109
|
+
op_map = {"union": "|", "intersection": "&", "difference": "-", "symmetric_difference": "^"}
|
|
110
|
+
op_symbol = op_map.get(self.operation, "|")
|
|
111
111
|
# Use base repr (_repr_str) of operands
|
|
112
112
|
left_repr = f"({self.left._repr_str})" if isinstance(self.left, CompoundSelector) else self.left._repr_str
|
|
113
113
|
right_repr = f"({self.right._repr_str})" if isinstance(self.right, CompoundSelector) else self.right._repr_str
|
|
@@ -116,77 +116,95 @@ class CompoundSelector(Selector):
|
|
|
116
116
|
|
|
117
117
|
class ComplementSelector(Selector):
|
|
118
118
|
"""Selector representing the complement (NOT) of another selector"""
|
|
119
|
+
|
|
119
120
|
def __init__(self, selector: Selector):
|
|
120
121
|
self.selector = selector
|
|
121
122
|
super().__init__()
|
|
122
123
|
|
|
123
124
|
def _get_repr_str(self) -> str:
|
|
124
|
-
selector_repr =
|
|
125
|
+
selector_repr = (
|
|
126
|
+
f"({self.selector._repr_str})" if isinstance(self.selector, CompoundSelector) else self.selector._repr_str
|
|
127
|
+
)
|
|
125
128
|
return f"~{selector_repr}"
|
|
126
129
|
|
|
127
130
|
|
|
128
131
|
class NumericSelector(Selector):
|
|
129
|
-
def _get_repr_str(self) -> str:
|
|
132
|
+
def _get_repr_str(self) -> str:
|
|
133
|
+
return "pl.selectors.numeric()"
|
|
130
134
|
|
|
131
135
|
|
|
132
136
|
class FloatSelector(Selector):
|
|
133
|
-
def _get_repr_str(self) -> str:
|
|
137
|
+
def _get_repr_str(self) -> str:
|
|
138
|
+
return "pl.selectors.float()"
|
|
134
139
|
|
|
135
140
|
|
|
136
141
|
class IntegerSelector(Selector):
|
|
137
|
-
def _get_repr_str(self) -> str:
|
|
142
|
+
def _get_repr_str(self) -> str:
|
|
143
|
+
return "pl.selectors.integer()"
|
|
138
144
|
|
|
139
145
|
|
|
140
146
|
class StringSelector(Selector):
|
|
141
|
-
def _get_repr_str(self) -> str:
|
|
147
|
+
def _get_repr_str(self) -> str:
|
|
148
|
+
return "pl.selectors.string()"
|
|
142
149
|
|
|
143
150
|
|
|
144
151
|
class TemporalSelector(Selector):
|
|
145
|
-
def _get_repr_str(self) -> str:
|
|
152
|
+
def _get_repr_str(self) -> str:
|
|
153
|
+
return "pl.selectors.temporal()"
|
|
146
154
|
|
|
147
155
|
|
|
148
156
|
class DatetimeSelector(Selector):
|
|
149
|
-
def _get_repr_str(self) -> str:
|
|
157
|
+
def _get_repr_str(self) -> str:
|
|
158
|
+
return "pl.selectors.datetime()"
|
|
150
159
|
|
|
151
160
|
|
|
152
161
|
class DateSelector(Selector):
|
|
153
|
-
def _get_repr_str(self) -> str:
|
|
162
|
+
def _get_repr_str(self) -> str:
|
|
163
|
+
return "pl.selectors.date()"
|
|
154
164
|
|
|
155
165
|
|
|
156
166
|
class TimeSelector(Selector):
|
|
157
|
-
def _get_repr_str(self) -> str:
|
|
167
|
+
def _get_repr_str(self) -> str:
|
|
168
|
+
return "pl.selectors.time()"
|
|
158
169
|
|
|
159
170
|
|
|
160
171
|
class DurationSelector(Selector):
|
|
161
|
-
def _get_repr_str(self) -> str:
|
|
172
|
+
def _get_repr_str(self) -> str:
|
|
173
|
+
return "pl.selectors.duration()"
|
|
162
174
|
|
|
163
175
|
|
|
164
176
|
class BooleanSelector(Selector):
|
|
165
|
-
def _get_repr_str(self) -> str:
|
|
177
|
+
def _get_repr_str(self) -> str:
|
|
178
|
+
return "pl.selectors.boolean()"
|
|
166
179
|
|
|
167
180
|
|
|
168
181
|
class CategoricalSelector(Selector):
|
|
169
|
-
def _get_repr_str(self) -> str:
|
|
182
|
+
def _get_repr_str(self) -> str:
|
|
183
|
+
return "pl.selectors.categorical()"
|
|
170
184
|
|
|
171
185
|
|
|
172
186
|
class ObjectSelector(Selector):
|
|
173
|
-
def _get_repr_str(self) -> str:
|
|
187
|
+
def _get_repr_str(self) -> str:
|
|
188
|
+
return "pl.selectors.object()"
|
|
174
189
|
|
|
175
190
|
|
|
176
191
|
class ListSelector(Selector):
|
|
177
|
-
def _get_repr_str(self) -> str:
|
|
192
|
+
def _get_repr_str(self) -> str:
|
|
193
|
+
return "pl.selectors.list()"
|
|
178
194
|
|
|
179
195
|
|
|
180
196
|
class StructSelector(Selector):
|
|
181
|
-
def _get_repr_str(self) -> str:
|
|
197
|
+
def _get_repr_str(self) -> str:
|
|
198
|
+
return "pl.selectors.struct()"
|
|
182
199
|
|
|
183
200
|
|
|
184
201
|
class AllSelector(Selector):
|
|
185
|
-
def _get_repr_str(self) -> str:
|
|
202
|
+
def _get_repr_str(self) -> str:
|
|
203
|
+
return "pl.selectors.all()"
|
|
186
204
|
|
|
187
205
|
|
|
188
206
|
class DtypeSelector(Selector):
|
|
189
|
-
def __init__(self, dtypes:
|
|
207
|
+
def __init__(self, dtypes: pl.DataType | list[pl.DataType]):
|
|
190
208
|
self.dtypes = dtypes if isinstance(dtypes, list) else [dtypes]
|
|
191
209
|
super().__init__()
|
|
192
210
|
|
|
@@ -208,38 +226,100 @@ class PatternSelector(Selector):
|
|
|
208
226
|
|
|
209
227
|
|
|
210
228
|
class ContainsSelector(PatternSelector):
|
|
211
|
-
def _get_repr_str(self) -> str:
|
|
229
|
+
def _get_repr_str(self) -> str:
|
|
230
|
+
return f"pl.selectors.contains({self.pattern!r})"
|
|
212
231
|
|
|
213
232
|
|
|
214
233
|
class StartsWithSelector(PatternSelector):
|
|
215
|
-
def _get_repr_str(self) -> str:
|
|
234
|
+
def _get_repr_str(self) -> str:
|
|
235
|
+
return f"pl.selectors.starts_with({self.pattern!r})"
|
|
216
236
|
|
|
217
237
|
|
|
218
238
|
class EndsWithSelector(PatternSelector):
|
|
219
|
-
def _get_repr_str(self) -> str:
|
|
239
|
+
def _get_repr_str(self) -> str:
|
|
240
|
+
return f"pl.selectors.ends_with({self.pattern!r})"
|
|
220
241
|
|
|
221
242
|
|
|
222
243
|
class MatchesSelector(PatternSelector):
|
|
223
|
-
def _get_repr_str(self) -> str:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
def
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
def
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
def _get_repr_str(self) -> str:
|
|
245
|
+
return f"pl.selectors.matches({self.pattern!r})"
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def numeric() -> NumericSelector:
|
|
249
|
+
return NumericSelector()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def float_() -> FloatSelector:
|
|
253
|
+
return FloatSelector()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def integer() -> IntegerSelector:
|
|
257
|
+
return IntegerSelector()
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def string() -> StringSelector:
|
|
261
|
+
return StringSelector()
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def temporal() -> TemporalSelector:
|
|
265
|
+
return TemporalSelector()
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def datetime() -> DatetimeSelector:
|
|
269
|
+
return DatetimeSelector()
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def date() -> DateSelector:
|
|
273
|
+
return DateSelector()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def time() -> TimeSelector:
|
|
277
|
+
return TimeSelector()
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def duration() -> DurationSelector:
|
|
281
|
+
return DurationSelector()
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def boolean() -> BooleanSelector:
|
|
285
|
+
return BooleanSelector()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def categorical() -> CategoricalSelector:
|
|
289
|
+
return CategoricalSelector()
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def object_() -> ObjectSelector:
|
|
293
|
+
return ObjectSelector()
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def list_() -> ListSelector:
|
|
297
|
+
return ListSelector()
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def struct() -> StructSelector:
|
|
301
|
+
return StructSelector()
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def all_() -> AllSelector:
|
|
305
|
+
return AllSelector()
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def by_dtype(dtypes: pl.DataType | list[pl.DataType]) -> DtypeSelector:
|
|
309
|
+
return DtypeSelector(dtypes)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def contains(pattern: str) -> ContainsSelector:
|
|
313
|
+
return ContainsSelector(pattern)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def starts_with(pattern: str) -> StartsWithSelector:
|
|
317
|
+
return StartsWithSelector(pattern)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def ends_with(pattern: str) -> EndsWithSelector:
|
|
321
|
+
return EndsWithSelector(pattern)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def matches(pattern: str) -> MatchesSelector:
|
|
325
|
+
return MatchesSelector(pattern)
|
flowfile_frame/series.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
2
5
|
import polars as pl
|
|
3
|
-
from typing import Any, Optional, Union, List
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class Series:
|
|
@@ -9,11 +11,11 @@ class Series:
|
|
|
9
11
|
"""
|
|
10
12
|
|
|
11
13
|
def __init__(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
self,
|
|
15
|
+
name: str | list | pl.Series | None = None,
|
|
16
|
+
values: list | None = None,
|
|
17
|
+
dtype: Any = None,
|
|
18
|
+
**kwargs, # Ignored parameters
|
|
17
19
|
):
|
|
18
20
|
"""
|
|
19
21
|
Initialize a FlowSeries with the same API as pl.Series.
|
|
@@ -67,4 +69,4 @@ class Series:
|
|
|
67
69
|
|
|
68
70
|
def __str__(self) -> str:
|
|
69
71
|
"""Same as __repr__."""
|
|
70
|
-
return self.__repr__()
|
|
72
|
+
return self.__repr__()
|
flowfile_frame/utils.py
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import textwrap
|
|
1
3
|
import uuid
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import subprocess
|
|
6
|
-
from pathlib import Path
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
7
|
import polars as pl
|
|
8
|
-
from typing import Iterable, Any, List, Optional
|
|
9
8
|
|
|
10
9
|
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
11
10
|
from flowfile_core.schemas import schemas
|
|
12
|
-
|
|
13
|
-
import inspect
|
|
14
|
-
import textwrap
|
|
11
|
+
|
|
15
12
|
|
|
16
13
|
def _is_iterable(obj: Any) -> bool:
|
|
17
14
|
# Avoid treating strings as iterables in this context
|
|
18
15
|
return isinstance(obj, Iterable) and not isinstance(obj, (str, bytes))
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
def _check_if_convertible_to_code(expressions:
|
|
18
|
+
def _check_if_convertible_to_code(expressions: list[Any]) -> bool:
|
|
22
19
|
from flowfile_frame.expr import Expr
|
|
20
|
+
|
|
23
21
|
for expr in expressions:
|
|
24
22
|
if isinstance(expr, Expr):
|
|
25
23
|
if not expr.convertable_to_code:
|
|
@@ -27,7 +25,9 @@ def _check_if_convertible_to_code(expressions: List[Any]) -> bool:
|
|
|
27
25
|
return True
|
|
28
26
|
|
|
29
27
|
|
|
30
|
-
def _parse_inputs_as_iterable(
|
|
28
|
+
def _parse_inputs_as_iterable(
|
|
29
|
+
inputs: tuple[Any, ...] | tuple[Iterable[Any]],
|
|
30
|
+
) -> list[Any]:
|
|
31
31
|
if not inputs:
|
|
32
32
|
return []
|
|
33
33
|
|
|
@@ -55,7 +55,7 @@ def _get_function_source(func):
|
|
|
55
55
|
source = inspect.getsource(func)
|
|
56
56
|
|
|
57
57
|
# Check if it's a lambda
|
|
58
|
-
if func.__name__ ==
|
|
58
|
+
if func.__name__ == "<lambda>":
|
|
59
59
|
# Extract just the lambda expression
|
|
60
60
|
# This is tricky as getsource returns the entire line
|
|
61
61
|
return None, False
|
|
@@ -72,9 +72,9 @@ def _get_function_source(func):
|
|
|
72
72
|
return None, False
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
def ensure_inputs_as_iterable(inputs: Any | Iterable[Any]) ->
|
|
75
|
+
def ensure_inputs_as_iterable(inputs: Any | Iterable[Any]) -> list[Any]:
|
|
76
76
|
"""Convert inputs to list, treating strings as single items."""
|
|
77
|
-
if inputs is None or (hasattr(inputs,
|
|
77
|
+
if inputs is None or (hasattr(inputs, "__len__") and len(inputs) == 0):
|
|
78
78
|
return []
|
|
79
79
|
# Treat strings/bytes as atomic items, everything else check if iterable
|
|
80
80
|
if isinstance(inputs, (str, bytes)) or not _is_iterable(inputs):
|
|
@@ -99,13 +99,11 @@ def create_flow_graph(flow_id: int = None) -> FlowGraph:
|
|
|
99
99
|
"""
|
|
100
100
|
if flow_id is None:
|
|
101
101
|
flow_id = _generate_id()
|
|
102
|
-
flow_settings = schemas.FlowSettings(
|
|
103
|
-
flow_id=flow_id,
|
|
104
|
-
name=f"Flow_{flow_id}",
|
|
105
|
-
path=f"flow_{flow_id}"
|
|
106
|
-
)
|
|
102
|
+
flow_settings = schemas.FlowSettings(flow_id=flow_id, name=f"Flow_{flow_id}", path=f"flow_{flow_id}")
|
|
107
103
|
flow_graph = FlowGraph(flow_settings=flow_settings)
|
|
108
|
-
flow_graph.flow_settings.execution_location =
|
|
104
|
+
flow_graph.flow_settings.execution_location = (
|
|
105
|
+
"local" # always create a local frame so that the run time does not attempt to use the flowfile_worker process
|
|
106
|
+
)
|
|
109
107
|
return flow_graph
|
|
110
108
|
|
|
111
109
|
|
|
@@ -140,4 +138,4 @@ def generate_node_id() -> int:
|
|
|
140
138
|
|
|
141
139
|
def set_node_id(node_id):
|
|
142
140
|
"""Set the node ID to a specific value."""
|
|
143
|
-
data["c"] = node_id
|
|
141
|
+
data["c"] = node_id
|
flowfile_worker/__init__.py
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# ruff: noqa: E402
|
|
2
|
+
|
|
3
3
|
import multiprocessing
|
|
4
|
-
|
|
5
|
-
from importlib.metadata import version
|
|
4
|
+
import threading
|
|
5
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from shared.storage_config import storage
|
|
8
8
|
|
|
9
|
+
try:
|
|
10
|
+
__version__ = version("Flowfile")
|
|
11
|
+
except PackageNotFoundError:
|
|
12
|
+
__version__ = "0.5.0"
|
|
9
13
|
multiprocessing.set_start_method('spawn', force=True)
|
|
10
14
|
|
|
11
15
|
from multiprocessing import get_context
|
|
16
|
+
|
|
12
17
|
from flowfile_worker.models import Status
|
|
13
18
|
|
|
14
19
|
mp_context = get_context("spawn")
|
|
15
20
|
|
|
16
|
-
status_dict:
|
|
21
|
+
status_dict: dict[str, Status] = dict()
|
|
17
22
|
process_dict = dict()
|
|
18
23
|
|
|
19
24
|
status_dict_lock = threading.Lock()
|
|
@@ -26,4 +31,4 @@ CACHE_EXPIRATION_TIME = 24 * 60 * 60
|
|
|
26
31
|
CACHE_DIR = storage.cache_directory
|
|
27
32
|
|
|
28
33
|
|
|
29
|
-
PROCESS_MEMORY_USAGE:
|
|
34
|
+
PROCESS_MEMORY_USAGE: dict[str, float] = dict()
|
flowfile_worker/configs.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# flowfile_worker.configs
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
|
-
import platform
|
|
5
3
|
import argparse
|
|
4
|
+
import logging
|
|
6
5
|
import os
|
|
7
|
-
|
|
6
|
+
import platform
|
|
8
7
|
|
|
8
|
+
from connectorx import __version__
|
|
9
9
|
|
|
10
10
|
# Configure logging
|
|
11
|
-
logging.basicConfig(format=
|
|
12
|
-
logger = logging.getLogger(
|
|
11
|
+
logging.basicConfig(format="%(asctime)s: %(message)s")
|
|
12
|
+
logger = logging.getLogger("FlowfileWorker")
|
|
13
13
|
logger.setLevel(logging.INFO)
|
|
14
14
|
|
|
15
15
|
# Constants for worker and core configuration
|
|
@@ -17,18 +17,14 @@ DEFAULT_SERVICE_HOST = "0.0.0.0" if platform.system() != "Windows" else "127.0.0
|
|
|
17
17
|
DEFAULT_SERVICE_PORT = 63579
|
|
18
18
|
DEFAULT_CORE_HOST = "0.0.0.0" if platform.system() != "Windows" else "127.0.0.1"
|
|
19
19
|
DEFAULT_CORE_PORT = 63578
|
|
20
|
-
TEST_MODE = True if
|
|
20
|
+
TEST_MODE = True if "TEST_MODE" in os.environ else False
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def parse_args():
|
|
24
24
|
"""Parse command line arguments"""
|
|
25
25
|
parser = argparse.ArgumentParser(description="Flowfile Worker Server")
|
|
26
|
-
parser.add_argument(
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
parser.add_argument(
|
|
30
|
-
"--port", type=int, default=DEFAULT_SERVICE_PORT, help="Port to bind worker to"
|
|
31
|
-
)
|
|
26
|
+
parser.add_argument("--host", type=str, default=DEFAULT_SERVICE_HOST, help="Host to bind worker to")
|
|
27
|
+
parser.add_argument("--port", type=int, default=DEFAULT_SERVICE_PORT, help="Port to bind worker to")
|
|
32
28
|
parser.add_argument(
|
|
33
29
|
"--core-host",
|
|
34
30
|
type=str,
|
|
@@ -47,14 +43,10 @@ def parse_args():
|
|
|
47
43
|
|
|
48
44
|
# Validate arguments
|
|
49
45
|
if args.port < 1 or args.port > 65535:
|
|
50
|
-
raise ValueError(
|
|
51
|
-
f"Invalid port number: {args.port}. Port must be between 1 and 65535."
|
|
52
|
-
)
|
|
46
|
+
raise ValueError(f"Invalid port number: {args.port}. Port must be between 1 and 65535.")
|
|
53
47
|
|
|
54
48
|
if args.core_port < 1 or args.core_port > 65535:
|
|
55
|
-
raise ValueError(
|
|
56
|
-
f"Invalid core port number: {args.core_port}. Port must be between 1 and 65535."
|
|
57
|
-
)
|
|
49
|
+
raise ValueError(f"Invalid core port number: {args.core_port}. Port must be between 1 and 65535.")
|
|
58
50
|
|
|
59
51
|
# Check if hosts are valid (basic check)
|
|
60
52
|
if not args.host:
|
|
@@ -92,4 +84,4 @@ FLOWFILE_CORE_URI = get_core_url(CORE_HOST, CORE_PORT)
|
|
|
92
84
|
logger.info(f"ConnectorX version: {__version__}")
|
|
93
85
|
# Log configuration
|
|
94
86
|
logger.info(f"Worker configured at {SERVICE_HOST}:{SERVICE_PORT}")
|
|
95
|
-
logger.info(f"Core service configured at {FLOWFILE_CORE_URI}")
|
|
87
|
+
logger.info(f"Core service configured at {FLOWFILE_CORE_URI}")
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
from flowfile_worker.create.funcs import (create_from_path_csv, create_from_path_parquet, create_from_path_excel,
|
|
3
|
-
create_from_path_json)
|
|
4
1
|
from typing import Literal
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
from flowfile_worker.create.funcs import (
|
|
4
|
+
create_from_path_csv,
|
|
5
|
+
create_from_path_excel,
|
|
6
|
+
create_from_path_json,
|
|
7
|
+
create_from_path_parquet,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
FileType = Literal["csv", "parquet", "json", "excel"]
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
def table_creator_factory_method(file_type: FileType) -> callable:
|
|
9
14
|
match file_type:
|
|
10
|
-
case
|
|
15
|
+
case "csv":
|
|
11
16
|
return create_from_path_csv
|
|
12
|
-
case
|
|
17
|
+
case "parquet":
|
|
13
18
|
return create_from_path_parquet
|
|
14
|
-
case
|
|
19
|
+
case "excel":
|
|
15
20
|
return create_from_path_excel
|
|
16
|
-
case
|
|
21
|
+
case "json":
|
|
17
22
|
return create_from_path_json
|
|
18
23
|
case _:
|
|
19
|
-
raise ValueError(f
|
|
24
|
+
raise ValueError(f"Unsupported file type: {file_type}")
|