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/lazy_methods.py
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
from collections.abc import Callable
|
|
2
2
|
from functools import wraps
|
|
3
|
-
from typing import
|
|
4
|
-
|
|
3
|
+
from typing import TypeVar
|
|
4
|
+
|
|
5
|
+
import polars as pl
|
|
6
|
+
|
|
5
7
|
from flowfile_frame.config import logger
|
|
8
|
+
from flowfile_frame.utils import _get_function_source
|
|
6
9
|
|
|
7
|
-
T = TypeVar(
|
|
8
|
-
FlowFrameT = TypeVar(
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
FlowFrameT = TypeVar("FlowFrameT", bound="FlowFrame")
|
|
9
12
|
|
|
10
13
|
PASSTHROUGH_METHODS = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
"collect",
|
|
15
|
+
"collect_async",
|
|
16
|
+
"profile",
|
|
17
|
+
"describe",
|
|
18
|
+
"explain",
|
|
19
|
+
"show_graph",
|
|
20
|
+
"fetch",
|
|
21
|
+
"collect_schema",
|
|
22
|
+
"columns",
|
|
23
|
+
"dtypes",
|
|
24
|
+
"schema",
|
|
25
|
+
"width",
|
|
26
|
+
"estimated_size",
|
|
27
|
+
"n_chunks",
|
|
28
|
+
"is_empty",
|
|
29
|
+
"chunk_lengths",
|
|
30
|
+
"get_meta",
|
|
15
31
|
}
|
|
16
32
|
|
|
17
33
|
|
|
@@ -33,31 +49,68 @@ def create_lazyframe_method_wrapper(method_name: str, original_method: Callable)
|
|
|
33
49
|
"""
|
|
34
50
|
# Determine if the original method returns a LazyFrame based on known method names
|
|
35
51
|
lazyframe_returning_methods = {
|
|
36
|
-
"drop",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
52
|
+
"drop",
|
|
53
|
+
"select",
|
|
54
|
+
"with_columns",
|
|
55
|
+
"sort",
|
|
56
|
+
"filter",
|
|
57
|
+
"join",
|
|
58
|
+
"head",
|
|
59
|
+
"tail",
|
|
60
|
+
"limit",
|
|
61
|
+
"drop_nulls",
|
|
62
|
+
"fill_null",
|
|
63
|
+
"with_row_index",
|
|
64
|
+
"group_by",
|
|
65
|
+
"explode",
|
|
66
|
+
"unique",
|
|
67
|
+
"slice",
|
|
68
|
+
"shift",
|
|
69
|
+
"reverse",
|
|
70
|
+
"max",
|
|
71
|
+
"min",
|
|
72
|
+
"sum",
|
|
73
|
+
"mean",
|
|
74
|
+
"median",
|
|
75
|
+
"std",
|
|
76
|
+
"var",
|
|
77
|
+
"drop_nans",
|
|
78
|
+
"fill_nan",
|
|
79
|
+
"interpolate",
|
|
80
|
+
"null_count",
|
|
81
|
+
"quantile",
|
|
82
|
+
"unpivot",
|
|
83
|
+
"melt",
|
|
84
|
+
"first",
|
|
85
|
+
"last",
|
|
41
86
|
}
|
|
42
87
|
|
|
43
88
|
non_lazyframe_methods = {
|
|
44
|
-
"collect",
|
|
45
|
-
"
|
|
89
|
+
"collect",
|
|
90
|
+
"collect_schema",
|
|
91
|
+
"fetch",
|
|
92
|
+
"columns",
|
|
93
|
+
"dtypes",
|
|
94
|
+
"schema",
|
|
95
|
+
"width",
|
|
96
|
+
"describe",
|
|
97
|
+
"explain",
|
|
98
|
+
"profile",
|
|
99
|
+
"show_graph",
|
|
46
100
|
}
|
|
47
101
|
|
|
48
|
-
returns_lazyframe = (
|
|
49
|
-
|
|
50
|
-
(method_name not in non_lazyframe_methods and not method_name.startswith("_"))
|
|
102
|
+
returns_lazyframe = method_name in lazyframe_returning_methods or (
|
|
103
|
+
method_name not in non_lazyframe_methods and not method_name.startswith("_")
|
|
51
104
|
)
|
|
52
105
|
|
|
53
106
|
@wraps(original_method)
|
|
54
|
-
def wrapper(self, *args, description:
|
|
107
|
+
def wrapper(self, *args, description: str | None = None, **kwargs):
|
|
55
108
|
# Import here to avoid circular imports
|
|
56
109
|
from flowfile_frame.flow_frame import generate_node_id
|
|
110
|
+
|
|
57
111
|
new_node_id = generate_node_id()
|
|
58
112
|
|
|
59
|
-
if not all([True if not hasattr(arg, "convertable_to_code") else
|
|
60
|
-
args]):
|
|
113
|
+
if not all([True if not hasattr(arg, "convertable_to_code") else arg.convertable_to_code for arg in args]):
|
|
61
114
|
logger.debug("Warning, could not create a good node")
|
|
62
115
|
return self.__class__(getattr(self.data, method_name)(arg.expr for arg in args), flow_graph=self.flow_graph)
|
|
63
116
|
|
|
@@ -72,7 +125,7 @@ def create_lazyframe_method_wrapper(method_name: str, original_method: Callable)
|
|
|
72
125
|
# Try to get function source
|
|
73
126
|
try:
|
|
74
127
|
source, is_module_level = _get_function_source(arg)
|
|
75
|
-
if source and hasattr(arg,
|
|
128
|
+
if source and hasattr(arg, "__name__") and arg.__name__ != "<lambda>":
|
|
76
129
|
function_sources.append(source)
|
|
77
130
|
# Use the function name in the representation
|
|
78
131
|
args_representations.append(arg.__name__)
|
|
@@ -89,7 +142,7 @@ def create_lazyframe_method_wrapper(method_name: str, original_method: Callable)
|
|
|
89
142
|
# Try to get function source
|
|
90
143
|
try:
|
|
91
144
|
source, is_module_level = _get_function_source(value)
|
|
92
|
-
if source and hasattr(value,
|
|
145
|
+
if source and hasattr(value, "__name__") and value.__name__ != "<lambda>":
|
|
93
146
|
function_sources.append(source)
|
|
94
147
|
kwargs_representations.append(f"{key}={value.__name__}")
|
|
95
148
|
else:
|
|
@@ -166,8 +219,7 @@ def add_lazyframe_methods(cls):
|
|
|
166
219
|
|
|
167
220
|
# Skip properties and private methods
|
|
168
221
|
skip_methods = {
|
|
169
|
-
name for name in dir(pl.LazyFrame)
|
|
170
|
-
if name.startswith('_') or isinstance(getattr(pl.LazyFrame, name), property)
|
|
222
|
+
name for name in dir(pl.LazyFrame) if name.startswith("_") or isinstance(getattr(pl.LazyFrame, name), property)
|
|
171
223
|
}
|
|
172
224
|
|
|
173
225
|
# Add all public LazyFrame methods that don't already exist
|
|
@@ -176,8 +228,8 @@ def add_lazyframe_methods(cls):
|
|
|
176
228
|
continue
|
|
177
229
|
attr = getattr(pl.LazyFrame, name)
|
|
178
230
|
if name in PASSTHROUGH_METHODS:
|
|
179
|
-
def create_passthrough_method(method_name, method_attr):
|
|
180
231
|
|
|
232
|
+
def create_passthrough_method(method_name, method_attr):
|
|
181
233
|
@wraps(method_attr)
|
|
182
234
|
def passthrough_method(self, *args, **kwargs):
|
|
183
235
|
return getattr(self.data, method_name)(*args, **kwargs)
|
|
@@ -193,9 +245,10 @@ def add_lazyframe_methods(cls):
|
|
|
193
245
|
setattr(cls, name, wrapped_method)
|
|
194
246
|
|
|
195
247
|
overlap = {
|
|
196
|
-
name
|
|
197
|
-
|
|
248
|
+
name
|
|
249
|
+
for name in existing_methods
|
|
250
|
+
if name in dir(pl.LazyFrame) and not name.startswith("_") and callable(getattr(pl.LazyFrame, name))
|
|
198
251
|
}
|
|
199
252
|
if overlap:
|
|
200
253
|
logger.debug(f"Preserved existing methods in {cls.__name__}: {', '.join(sorted(overlap))}")
|
|
201
|
-
return cls
|
|
254
|
+
return cls
|
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
4
5
|
|
|
5
6
|
import polars as pl
|
|
6
7
|
|
|
7
|
-
|
|
8
8
|
# --- TYPE CHECKING IMPORTS ---
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
from flowfile_frame.expr import Expr, _get_expr_and_repr, col, lit
|
|
11
|
-
from polars._typing import IntoExprColumn, NullBehavior, ListToStructWidthStrategy
|
|
12
10
|
from datetime import date, datetime, time
|
|
13
11
|
|
|
12
|
+
from polars._typing import IntoExprColumn, ListToStructWidthStrategy, NullBehavior
|
|
13
|
+
|
|
14
|
+
from flowfile_frame.expr import Expr
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
class ExprListNameSpace:
|
|
16
18
|
"""Namespace for list related expressions."""
|
|
17
19
|
|
|
18
|
-
def __init__(self, parent_expr:
|
|
20
|
+
def __init__(self, parent_expr: Expr, parent_repr_str: str):
|
|
19
21
|
self.parent = parent_expr
|
|
20
22
|
self.expr = parent_expr.expr.list if parent_expr.expr is not None else None
|
|
21
23
|
self.parent_repr_str = parent_repr_str
|
|
22
24
|
|
|
23
|
-
def _create_next_expr(
|
|
25
|
+
def _create_next_expr(
|
|
26
|
+
self, *args, method_name: str, result_expr: pl.Expr | None, is_complex: bool = True, **kwargs
|
|
27
|
+
) -> Expr:
|
|
24
28
|
from flowfile_frame.expr import Expr
|
|
29
|
+
|
|
25
30
|
"""Creates a new Expr instance, appending method call to repr string."""
|
|
26
31
|
args_repr = ", ".join(repr(a) for a in args)
|
|
27
32
|
kwargs_repr = ", ".join(f"{k}={repr(v)}" for k, v in kwargs.items())
|
|
@@ -46,7 +51,7 @@ class ExprListNameSpace:
|
|
|
46
51
|
selector=None,
|
|
47
52
|
agg_func=self.parent.agg_func,
|
|
48
53
|
is_complex=is_complex,
|
|
49
|
-
convertable_to_code=self.parent.convertable_to_code
|
|
54
|
+
convertable_to_code=self.parent.convertable_to_code,
|
|
50
55
|
)
|
|
51
56
|
return new_expr_instance
|
|
52
57
|
|
|
@@ -67,13 +72,13 @@ class ExprListNameSpace:
|
|
|
67
72
|
return self._create_next_expr(method_name="drop_nulls", result_expr=res_expr)
|
|
68
73
|
|
|
69
74
|
def sample(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
self,
|
|
76
|
+
n: int | IntoExprColumn | None = None,
|
|
77
|
+
*,
|
|
78
|
+
fraction: float | IntoExprColumn | None = None,
|
|
79
|
+
with_replacement: bool = False,
|
|
80
|
+
shuffle: bool = False,
|
|
81
|
+
seed: int | None = None,
|
|
77
82
|
) -> Expr:
|
|
78
83
|
if n is not None and fraction is not None:
|
|
79
84
|
raise ValueError("cannot specify both `n` and `fraction`")
|
|
@@ -82,15 +87,15 @@ class ExprListNameSpace:
|
|
|
82
87
|
if self.expr is not None:
|
|
83
88
|
try:
|
|
84
89
|
if fraction is not None:
|
|
85
|
-
expr_fraction = fraction.expr if hasattr(fraction,
|
|
86
|
-
res_expr = self.expr.sample(
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
expr_fraction = fraction.expr if hasattr(fraction, "expr") else fraction
|
|
91
|
+
res_expr = self.expr.sample(
|
|
92
|
+
n=None, fraction=expr_fraction, with_replacement=with_replacement, shuffle=shuffle, seed=seed
|
|
93
|
+
)
|
|
89
94
|
else:
|
|
90
|
-
expr_n = n.expr if hasattr(n,
|
|
91
|
-
res_expr = self.expr.sample(
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
expr_n = n.expr if hasattr(n, "expr") else (1 if n is None else n)
|
|
96
|
+
res_expr = self.expr.sample(
|
|
97
|
+
n=expr_n, fraction=None, with_replacement=with_replacement, shuffle=shuffle, seed=seed
|
|
98
|
+
)
|
|
94
99
|
except Exception as e:
|
|
95
100
|
print(f"Warning: Could not create polars expression for list.sample(): {e}")
|
|
96
101
|
|
|
@@ -101,7 +106,7 @@ class ExprListNameSpace:
|
|
|
101
106
|
fraction=fraction,
|
|
102
107
|
with_replacement=with_replacement,
|
|
103
108
|
shuffle=shuffle,
|
|
104
|
-
seed=seed
|
|
109
|
+
seed=seed,
|
|
105
110
|
)
|
|
106
111
|
|
|
107
112
|
def sum(self) -> Expr:
|
|
@@ -134,7 +139,9 @@ class ExprListNameSpace:
|
|
|
134
139
|
|
|
135
140
|
def sort(self, *, descending: bool = False, nulls_last: bool = False) -> Expr:
|
|
136
141
|
res_expr = self.expr.sort(descending=descending, nulls_last=nulls_last) if self.expr is not None else None
|
|
137
|
-
return self._create_next_expr(
|
|
142
|
+
return self._create_next_expr(
|
|
143
|
+
method_name="sort", result_expr=res_expr, descending=descending, nulls_last=nulls_last
|
|
144
|
+
)
|
|
138
145
|
|
|
139
146
|
def reverse(self) -> Expr:
|
|
140
147
|
res_expr = self.expr.reverse() if self.expr is not None else None
|
|
@@ -163,7 +170,7 @@ class ExprListNameSpace:
|
|
|
163
170
|
elif isinstance(other, list):
|
|
164
171
|
if len(other) > 0 and isinstance(other[0], (Expr, str, pl.Series)):
|
|
165
172
|
# List of expressions
|
|
166
|
-
other_expr = [o.expr if hasattr(o,
|
|
173
|
+
other_expr = [o.expr if hasattr(o, "expr") else (pl.col(o) if isinstance(o, str) else o) for o in other]
|
|
167
174
|
else:
|
|
168
175
|
# List of values
|
|
169
176
|
other_expr = pl.lit(other)
|
|
@@ -183,7 +190,7 @@ class ExprListNameSpace:
|
|
|
183
190
|
return self._create_next_expr(other, method_name="concat", result_expr=res_expr)
|
|
184
191
|
|
|
185
192
|
def get(self, index: int | Expr | str, *, null_on_oob: bool = False) -> Expr:
|
|
186
|
-
index_expr = index.expr if hasattr(index,
|
|
193
|
+
index_expr = index.expr if hasattr(index, "expr") else index
|
|
187
194
|
res_expr = self.expr.get(index_expr, null_on_oob=null_on_oob) if self.expr is not None else None
|
|
188
195
|
return self._create_next_expr(index, method_name="get", result_expr=res_expr, null_on_oob=null_on_oob)
|
|
189
196
|
|
|
@@ -191,15 +198,15 @@ class ExprListNameSpace:
|
|
|
191
198
|
indices_expr = indices
|
|
192
199
|
if isinstance(indices, list):
|
|
193
200
|
indices_expr = pl.Series(indices)
|
|
194
|
-
elif hasattr(indices,
|
|
201
|
+
elif hasattr(indices, "expr"):
|
|
195
202
|
indices_expr = indices.expr
|
|
196
203
|
|
|
197
204
|
res_expr = self.expr.gather(indices_expr, null_on_oob=null_on_oob) if self.expr is not None else None
|
|
198
205
|
return self._create_next_expr(indices, method_name="gather", result_expr=res_expr, null_on_oob=null_on_oob)
|
|
199
206
|
|
|
200
207
|
def gather_every(self, n: int | IntoExprColumn, offset: int | IntoExprColumn = 0) -> Expr:
|
|
201
|
-
n_expr = n.expr if hasattr(n,
|
|
202
|
-
offset_expr = offset.expr if hasattr(offset,
|
|
208
|
+
n_expr = n.expr if hasattr(n, "expr") else n
|
|
209
|
+
offset_expr = offset.expr if hasattr(offset, "expr") else offset
|
|
203
210
|
|
|
204
211
|
res_expr = self.expr.gather_every(n_expr, offset_expr) if self.expr is not None else None
|
|
205
212
|
return self._create_next_expr(n, method_name="gather_every", result_expr=res_expr, offset=offset)
|
|
@@ -213,12 +220,12 @@ class ExprListNameSpace:
|
|
|
213
220
|
return self._create_next_expr(method_name="last", result_expr=res_expr)
|
|
214
221
|
|
|
215
222
|
def contains(self, item: float | str | bool | int | date | datetime | time | IntoExprColumn) -> Expr:
|
|
216
|
-
item_expr = item.expr if hasattr(item,
|
|
223
|
+
item_expr = item.expr if hasattr(item, "expr") else item
|
|
217
224
|
res_expr = self.expr.contains(item_expr) if self.expr is not None else None
|
|
218
225
|
return self._create_next_expr(item, method_name="contains", result_expr=res_expr)
|
|
219
226
|
|
|
220
227
|
def join(self, separator: IntoExprColumn, *, ignore_nulls: bool = True) -> Expr:
|
|
221
|
-
separator_expr = separator.expr if hasattr(separator,
|
|
228
|
+
separator_expr = separator.expr if hasattr(separator, "expr") else separator
|
|
222
229
|
res_expr = self.expr.join(separator_expr, ignore_nulls=ignore_nulls) if self.expr is not None else None
|
|
223
230
|
return self._create_next_expr(separator, method_name="join", result_expr=res_expr, ignore_nulls=ignore_nulls)
|
|
224
231
|
|
|
@@ -235,24 +242,24 @@ class ExprListNameSpace:
|
|
|
235
242
|
return self._create_next_expr(method_name="diff", result_expr=res_expr, n=n, null_behavior=null_behavior)
|
|
236
243
|
|
|
237
244
|
def shift(self, n: int | IntoExprColumn = 1) -> Expr:
|
|
238
|
-
n_expr = n.expr if hasattr(n,
|
|
245
|
+
n_expr = n.expr if hasattr(n, "expr") else n
|
|
239
246
|
res_expr = self.expr.shift(n_expr) if self.expr is not None else None
|
|
240
247
|
return self._create_next_expr(n, method_name="shift", result_expr=res_expr)
|
|
241
248
|
|
|
242
249
|
def slice(self, offset: int | str | Expr, length: int | str | Expr | None = None) -> Expr:
|
|
243
|
-
offset_expr = offset.expr if hasattr(offset,
|
|
244
|
-
length_expr = length.expr if hasattr(length,
|
|
250
|
+
offset_expr = offset.expr if hasattr(offset, "expr") else offset
|
|
251
|
+
length_expr = length.expr if hasattr(length, "expr") and length is not None else length
|
|
245
252
|
|
|
246
253
|
res_expr = self.expr.slice(offset_expr, length_expr) if self.expr is not None else None
|
|
247
254
|
return self._create_next_expr(offset, length, method_name="slice", result_expr=res_expr)
|
|
248
255
|
|
|
249
256
|
def head(self, n: int | str | Expr = 5) -> Expr:
|
|
250
|
-
n_expr = n.expr if hasattr(n,
|
|
257
|
+
n_expr = n.expr if hasattr(n, "expr") else n
|
|
251
258
|
res_expr = self.expr.head(n_expr) if self.expr is not None else None
|
|
252
259
|
return self._create_next_expr(n, method_name="head", result_expr=res_expr)
|
|
253
260
|
|
|
254
261
|
def tail(self, n: int | str | Expr = 5) -> Expr:
|
|
255
|
-
n_expr = n.expr if hasattr(n,
|
|
262
|
+
n_expr = n.expr if hasattr(n, "expr") else n
|
|
256
263
|
res_expr = self.expr.tail(n_expr) if self.expr is not None else None
|
|
257
264
|
return self._create_next_expr(n, method_name="tail", result_expr=res_expr)
|
|
258
265
|
|
|
@@ -261,7 +268,7 @@ class ExprListNameSpace:
|
|
|
261
268
|
return self._create_next_expr(method_name="explode", result_expr=res_expr)
|
|
262
269
|
|
|
263
270
|
def count_matches(self, element: Any) -> Expr:
|
|
264
|
-
element_expr = element.expr if hasattr(element,
|
|
271
|
+
element_expr = element.expr if hasattr(element, "expr") else element
|
|
265
272
|
res_expr = self.expr.count_matches(element_expr) if self.expr is not None else None
|
|
266
273
|
return self._create_next_expr(element, method_name="count_matches", result_expr=res_expr)
|
|
267
274
|
|
|
@@ -270,10 +277,10 @@ class ExprListNameSpace:
|
|
|
270
277
|
return self._create_next_expr(width, method_name="to_array", result_expr=res_expr)
|
|
271
278
|
|
|
272
279
|
def to_struct(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
280
|
+
self,
|
|
281
|
+
n_field_strategy: ListToStructWidthStrategy = "first_non_null",
|
|
282
|
+
fields: Sequence[str] | Callable[[int], str] | None = None,
|
|
283
|
+
upper_bound: int = 0,
|
|
277
284
|
) -> Expr:
|
|
278
285
|
res_expr = None
|
|
279
286
|
|
|
@@ -283,9 +290,7 @@ class ExprListNameSpace:
|
|
|
283
290
|
res_expr = self.expr.to_struct(fields=fields)
|
|
284
291
|
else:
|
|
285
292
|
res_expr = self.expr.to_struct(
|
|
286
|
-
n_field_strategy=n_field_strategy,
|
|
287
|
-
fields=fields,
|
|
288
|
-
upper_bound=upper_bound
|
|
293
|
+
n_field_strategy=n_field_strategy, fields=fields, upper_bound=upper_bound
|
|
289
294
|
)
|
|
290
295
|
except Exception as e:
|
|
291
296
|
print(f"Warning: Could not create polars expression for list.to_struct(): {e}")
|
|
@@ -299,26 +304,26 @@ class ExprListNameSpace:
|
|
|
299
304
|
)
|
|
300
305
|
|
|
301
306
|
def eval(self, expr: Expr, *, parallel: bool = False) -> Expr:
|
|
302
|
-
expr_inner = expr.expr if hasattr(expr,
|
|
307
|
+
expr_inner = expr.expr if hasattr(expr, "expr") else expr
|
|
303
308
|
res_expr = self.expr.eval(expr_inner, parallel=parallel) if self.expr is not None else None
|
|
304
309
|
return self._create_next_expr(expr, method_name="eval", result_expr=res_expr, parallel=parallel)
|
|
305
310
|
|
|
306
311
|
def set_union(self, other: Any) -> Expr:
|
|
307
|
-
other_expr = other.expr if hasattr(other,
|
|
312
|
+
other_expr = other.expr if hasattr(other, "expr") else other
|
|
308
313
|
res_expr = self.expr.set_union(other_expr) if self.expr is not None else None
|
|
309
314
|
return self._create_next_expr(other, method_name="set_union", result_expr=res_expr)
|
|
310
315
|
|
|
311
316
|
def set_difference(self, other: Any) -> Expr:
|
|
312
|
-
other_expr = other.expr if hasattr(other,
|
|
317
|
+
other_expr = other.expr if hasattr(other, "expr") else other
|
|
313
318
|
res_expr = self.expr.set_difference(other_expr) if self.expr is not None else None
|
|
314
319
|
return self._create_next_expr(other, method_name="set_difference", result_expr=res_expr)
|
|
315
320
|
|
|
316
321
|
def set_intersection(self, other: Any) -> Expr:
|
|
317
|
-
other_expr = other.expr if hasattr(other,
|
|
322
|
+
other_expr = other.expr if hasattr(other, "expr") else other
|
|
318
323
|
res_expr = self.expr.set_intersection(other_expr) if self.expr is not None else None
|
|
319
324
|
return self._create_next_expr(other, method_name="set_intersection", result_expr=res_expr)
|
|
320
325
|
|
|
321
326
|
def set_symmetric_difference(self, other: Any) -> Expr:
|
|
322
|
-
other_expr = other.expr if hasattr(other,
|
|
327
|
+
other_expr = other.expr if hasattr(other, "expr") else other
|
|
323
328
|
res_expr = self.expr.set_symmetric_difference(other_expr) if self.expr is not None else None
|
|
324
|
-
return self._create_next_expr(other, method_name="set_symmetric_difference", result_expr=res_expr)
|
|
329
|
+
return self._create_next_expr(other, method_name="set_symmetric_difference", result_expr=res_expr)
|