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.
Files changed (329) hide show
  1. build_backends/main.py +25 -22
  2. build_backends/main_prd.py +10 -19
  3. flowfile/__init__.py +178 -74
  4. flowfile/__main__.py +10 -7
  5. flowfile/api.py +51 -57
  6. flowfile/web/__init__.py +14 -9
  7. flowfile/web/static/assets/AdminView-49392a9a.js +713 -0
  8. flowfile/web/static/assets/AdminView-f53bad23.css +129 -0
  9. flowfile/web/static/assets/CloudConnectionView-36bcd6df.css +72 -0
  10. flowfile/web/static/assets/{CloudConnectionManager-0dfba9f2.js → CloudConnectionView-f13f202b.js} +11 -11
  11. flowfile/web/static/assets/{CloudStorageReader-d5b1b6c9.js → CloudStorageReader-0023d4a5.js} +10 -8
  12. flowfile/web/static/assets/{CloudStorageReader-29d14fcc.css → CloudStorageReader-24c54524.css} +27 -27
  13. flowfile/web/static/assets/{CloudStorageWriter-b0ee067f.css → CloudStorageWriter-60547855.css} +26 -26
  14. flowfile/web/static/assets/{CloudStorageWriter-00d87aad.js → CloudStorageWriter-8e781e11.js} +10 -8
  15. flowfile/web/static/assets/{ColumnSelector-47996a16.css → ColumnSelector-371637fb.css} +2 -2
  16. flowfile/web/static/assets/{ColumnSelector-4685e75d.js → ColumnSelector-8ad68ea9.js} +3 -5
  17. flowfile/web/static/assets/{ContextMenu-c13f91d0.css → ContextMenu-26d4dd27.css} +6 -6
  18. flowfile/web/static/assets/{ContextMenu-23e909da.js → ContextMenu-31ee57f0.js} +3 -3
  19. flowfile/web/static/assets/{ContextMenu-70ae0c79.js → ContextMenu-69a74055.js} +3 -3
  20. flowfile/web/static/assets/{ContextMenu-f149cf7c.js → ContextMenu-8e2051c6.js} +3 -3
  21. flowfile/web/static/assets/{ContextMenu-4c74eef1.css → ContextMenu-8ec1729e.css} +6 -6
  22. flowfile/web/static/assets/{ContextMenu-63cfa99b.css → ContextMenu-9b310c60.css} +6 -6
  23. flowfile/web/static/assets/{CrossJoin-702a3edd.js → CrossJoin-03df6938.js} +12 -10
  24. flowfile/web/static/assets/{CrossJoin-1119d18e.css → CrossJoin-71b4cc10.css} +20 -20
  25. flowfile/web/static/assets/CustomNode-59e99a86.css +32 -0
  26. flowfile/web/static/assets/{CustomNode-b1519993.js → CustomNode-8479239b.js} +36 -24
  27. flowfile/web/static/assets/{DatabaseConnectionSettings-6f3e4ea5.js → DatabaseConnectionSettings-869e3efd.js} +5 -4
  28. flowfile/web/static/assets/{DatabaseConnectionSettings-0c04b2e5.css → DatabaseConnectionSettings-e91df89a.css} +13 -13
  29. flowfile/web/static/assets/{DatabaseReader-ae61773c.css → DatabaseReader-36898a00.css} +24 -24
  30. flowfile/web/static/assets/{DatabaseReader-d38c7295.js → DatabaseReader-c58b9552.js} +25 -15
  31. flowfile/web/static/assets/DatabaseView-6655afd6.css +57 -0
  32. flowfile/web/static/assets/{DatabaseManager-cf5ef661.js → DatabaseView-d26a9140.js} +11 -11
  33. flowfile/web/static/assets/{DatabaseWriter-2f570e53.css → DatabaseWriter-217a99f1.css} +19 -19
  34. flowfile/web/static/assets/{DatabaseWriter-b04ef46a.js → DatabaseWriter-4d05ddc7.js} +17 -10
  35. flowfile/web/static/assets/{designer-8da3ba3a.css → DesignerView-a6d0ee84.css} +614 -546
  36. flowfile/web/static/assets/{designer-9633482a.js → DesignerView-e6f5c0e8.js} +1107 -3170
  37. flowfile/web/static/assets/{documentation-ca400224.js → DocumentationView-2e78ef1b.js} +5 -5
  38. flowfile/web/static/assets/{documentation-12216a74.css → DocumentationView-fd46c656.css} +7 -7
  39. flowfile/web/static/assets/{ExploreData-2d0cf4db.css → ExploreData-10c5acc8.css} +13 -12
  40. flowfile/web/static/assets/{ExploreData-5fa10ed8.js → ExploreData-7b54caca.js} +18 -9
  41. flowfile/web/static/assets/{ExternalSource-d39af878.js → ExternalSource-3fa399b2.js} +9 -7
  42. flowfile/web/static/assets/{ExternalSource-e37b6275.css → ExternalSource-47ab05a3.css} +17 -17
  43. flowfile/web/static/assets/Filter-7494ea97.css +48 -0
  44. flowfile/web/static/assets/Filter-8cbbdbf3.js +287 -0
  45. flowfile/web/static/assets/{Formula-bb96803d.css → Formula-53d58c43.css} +7 -7
  46. flowfile/web/static/assets/{Formula-6b04fb1d.js → Formula-aac42b1e.js} +13 -11
  47. flowfile/web/static/assets/{FuzzyMatch-1010f966.css → FuzzyMatch-ad6361d6.css} +68 -69
  48. flowfile/web/static/assets/{FuzzyMatch-999521f4.js → FuzzyMatch-cd9bbfca.js} +12 -10
  49. flowfile/web/static/assets/{Pivot-cf333e3d.css → GraphSolver-c24dec17.css} +5 -5
  50. flowfile/web/static/assets/{GraphSolver-17dd2198.js → GraphSolver-c7e6780e.js} +13 -11
  51. flowfile/web/static/assets/{GroupBy-6b039e18.js → GroupBy-93c5d22b.js} +9 -7
  52. flowfile/web/static/assets/{GroupBy-b9505323.css → GroupBy-be7ac0bf.css} +10 -10
  53. flowfile/web/static/assets/{Join-fd79b451.css → Join-28b5e18f.css} +22 -22
  54. flowfile/web/static/assets/{Join-24d0f113.js → Join-a19b2de2.js} +13 -11
  55. flowfile/web/static/assets/LoginView-0df4ed0a.js +134 -0
  56. flowfile/web/static/assets/LoginView-d325d632.css +172 -0
  57. flowfile/web/static/assets/ManualInput-3702e677.css +293 -0
  58. flowfile/web/static/assets/{ManualInput-34639209.js → ManualInput-8d3374b2.js} +170 -116
  59. flowfile/web/static/assets/{MultiSelect-0e8724a3.js → MultiSelect-ad1b6243.js} +2 -2
  60. 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
  61. flowfile/web/static/assets/NodeDesigner-40b647c9.js +2610 -0
  62. flowfile/web/static/assets/NodeDesigner-5f53be3f.css +1429 -0
  63. flowfile/web/static/assets/{NumericInput-3d63a470.js → NumericInput-7100234c.js} +2 -2
  64. 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
  65. flowfile/web/static/assets/{Output-283fe388.css → Output-35e97000.css} +6 -6
  66. flowfile/web/static/assets/{Output-edea9802.js → Output-f5efd2aa.js} +12 -9
  67. flowfile/web/static/assets/{GraphSolver-f0cb7bfb.css → Pivot-0eda81b4.css} +5 -5
  68. flowfile/web/static/assets/{Pivot-61d19301.js → Pivot-d981d23c.js} +11 -9
  69. flowfile/web/static/assets/PivotValidation-0e905b1a.css +13 -0
  70. flowfile/web/static/assets/{PivotValidation-f97fec5b.js → PivotValidation-39386e95.js} +3 -3
  71. flowfile/web/static/assets/PivotValidation-41b57ad6.css +13 -0
  72. flowfile/web/static/assets/{PivotValidation-de9f43fe.js → PivotValidation-63de1f73.js} +3 -3
  73. flowfile/web/static/assets/{PolarsCode-650322d1.css → PolarsCode-2b1f1f23.css} +4 -4
  74. flowfile/web/static/assets/{PolarsCode-bc3c9984.js → PolarsCode-f9d69217.js} +18 -9
  75. flowfile/web/static/assets/PopOver-b22f049e.js +939 -0
  76. flowfile/web/static/assets/PopOver-d96599db.css +33 -0
  77. flowfile/web/static/assets/{Read-e808b239.css → Read-36e7bd51.css} +12 -12
  78. flowfile/web/static/assets/{Read-64a3f259.js → Read-aec2e377.js} +14 -11
  79. flowfile/web/static/assets/{RecordCount-3d5039be.js → RecordCount-78ed6845.js} +6 -4
  80. flowfile/web/static/assets/{RecordId-597510e0.js → RecordId-2156e890.js} +8 -6
  81. flowfile/web/static/assets/{SQLQueryComponent-36cef432.css → SQLQueryComponent-1c2f26b4.css} +5 -5
  82. flowfile/web/static/assets/{SQLQueryComponent-df51adbe.js → SQLQueryComponent-48c72f5b.js} +3 -3
  83. flowfile/web/static/assets/{Sample-4be0a507.js → Sample-1352ca74.js} +6 -4
  84. flowfile/web/static/assets/SecretSelector-22b5ff89.js +113 -0
  85. flowfile/web/static/assets/SecretSelector-6329f743.css +43 -0
  86. flowfile/web/static/assets/{SecretManager-4839be57.js → SecretsView-17df66ee.js} +35 -36
  87. flowfile/web/static/assets/SecretsView-aa291340.css +38 -0
  88. flowfile/web/static/assets/{Select-9b72f201.js → Select-0aee4c54.js} +9 -7
  89. flowfile/web/static/assets/{SettingsSection-f0f75a42.js → SettingsSection-0784e157.js} +3 -3
  90. flowfile/web/static/assets/{SettingsSection-71e6b7e3.css → SettingsSection-07fbbc39.css} +4 -4
  91. flowfile/web/static/assets/{SettingsSection-5c696bee.css → SettingsSection-26fe48d4.css} +4 -4
  92. flowfile/web/static/assets/{SettingsSection-2e4d03c4.css → SettingsSection-8f980839.css} +4 -4
  93. flowfile/web/static/assets/{SettingsSection-e1e9c953.js → SettingsSection-cd341bb6.js} +3 -3
  94. flowfile/web/static/assets/{SettingsSection-7ded385d.js → SettingsSection-f2002a6d.js} +3 -3
  95. flowfile/web/static/assets/{SingleSelect-6c777aac.js → SingleSelect-460cc0ea.js} +2 -2
  96. 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
  97. flowfile/web/static/assets/{SliderInput-7cb93e62.js → SliderInput-5d926864.js} +7 -4
  98. flowfile/web/static/assets/SliderInput-f2e4f23c.css +4 -0
  99. flowfile/web/static/assets/{Sort-6cbde21a.js → Sort-3cdc971b.js} +9 -7
  100. flowfile/web/static/assets/{Unique-f9fb0809.css → Sort-8a871341.css} +10 -10
  101. flowfile/web/static/assets/{TextInput-d9a40c11.js → TextInput-a2d0bfbd.js} +2 -2
  102. 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
  103. flowfile/web/static/assets/{TextToRows-5d2c1190.css → TextToRows-12afb4f4.css} +10 -10
  104. flowfile/web/static/assets/{TextToRows-c4fcbf4d.js → TextToRows-918945f7.js} +11 -10
  105. flowfile/web/static/assets/{ToggleSwitch-4ef91d19.js → ToggleSwitch-f0ef5196.js} +2 -2
  106. 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
  107. flowfile/web/static/assets/{UnavailableFields-5edd5322.css → UnavailableFields-54d2f518.css} +6 -6
  108. flowfile/web/static/assets/{UnavailableFields-a03f512c.js → UnavailableFields-bdad6144.js} +4 -4
  109. flowfile/web/static/assets/{Union-af6c3d9b.css → Union-d6a8d7d5.css} +7 -7
  110. flowfile/web/static/assets/{Union-bfe9b996.js → Union-e8ab8c86.js} +8 -6
  111. flowfile/web/static/assets/{Unique-5d023a27.js → Unique-8cd4f976.js} +13 -10
  112. flowfile/web/static/assets/{Sort-3643d625.css → Unique-9fb2f567.css} +10 -10
  113. flowfile/web/static/assets/{Unpivot-1e422df3.css → Unpivot-710a2948.css} +7 -7
  114. flowfile/web/static/assets/{Unpivot-91cc5354.js → Unpivot-8da14095.js} +10 -8
  115. flowfile/web/static/assets/{UnpivotValidation-7ee2de44.js → UnpivotValidation-6f7d89ff.js} +3 -3
  116. flowfile/web/static/assets/UnpivotValidation-d5ca3b7b.css +13 -0
  117. flowfile/web/static/assets/{VueGraphicWalker-e51b9924.js → VueGraphicWalker-3fb312e1.js} +4 -4
  118. flowfile/web/static/assets/{VueGraphicWalker-ed5ab88b.css → VueGraphicWalker-430f0b86.css} +1 -1
  119. flowfile/web/static/assets/{api-cf1221f0.js → api-24483f0d.js} +1 -1
  120. flowfile/web/static/assets/{api-c1bad5ca.js → api-8b81fa73.js} +1 -1
  121. flowfile/web/static/assets/{dropDown-35135ba8.css → dropDown-3d8dc5fa.css} +40 -40
  122. flowfile/web/static/assets/{dropDown-614b998d.js → dropDown-ac0fda9d.js} +3 -3
  123. flowfile/web/static/assets/{fullEditor-f7971590.js → fullEditor-5497a84a.js} +11 -10
  124. flowfile/web/static/assets/{fullEditor-178376bb.css → fullEditor-a0be62b3.css} +74 -62
  125. flowfile/web/static/assets/{genericNodeSettings-924759c7.css → genericNodeSettings-3b2507ea.css} +10 -10
  126. flowfile/web/static/assets/{genericNodeSettings-4fe5f36b.js → genericNodeSettings-99014e1d.js} +5 -5
  127. flowfile/web/static/assets/index-07dda503.js +38 -0
  128. flowfile/web/static/assets/index-3ba44389.js +2696 -0
  129. flowfile/web/static/assets/{index-50508d4d.css → index-e6289dd0.css} +1945 -569
  130. flowfile/web/static/assets/{index-5429bbf8.js → index-fb6493ae.js} +41626 -40867
  131. flowfile/web/static/assets/node.types-2c15bb7e.js +82 -0
  132. flowfile/web/static/assets/nodeInput-0eb13f1a.js +2 -0
  133. flowfile/web/static/assets/{outputCsv-076b85ab.js → outputCsv-8f8ba42d.js} +3 -3
  134. flowfile/web/static/assets/outputCsv-b9a072af.css +2499 -0
  135. flowfile/web/static/assets/{outputExcel-0fd17dbe.js → outputExcel-393f4fef.js} +3 -3
  136. flowfile/web/static/assets/{outputExcel-b41305c0.css → outputExcel-f5d272b2.css} +26 -26
  137. flowfile/web/static/assets/{outputParquet-b61e0847.js → outputParquet-07c81f65.js} +4 -4
  138. flowfile/web/static/assets/outputParquet-54597c3c.css +4 -0
  139. flowfile/web/static/assets/{readCsv-a8bb8b61.js → readCsv-07f6d9ad.js} +3 -3
  140. flowfile/web/static/assets/{readCsv-c767cb37.css → readCsv-3bfac4c3.css} +15 -15
  141. flowfile/web/static/assets/{readExcel-806d2826.css → readExcel-3db6b763.css} +13 -13
  142. flowfile/web/static/assets/{readExcel-67b4aee0.js → readExcel-ed69bc8f.js} +5 -5
  143. flowfile/web/static/assets/{readParquet-48c81530.css → readParquet-c5244ad5.css} +4 -4
  144. flowfile/web/static/assets/{readParquet-92ce1dbc.js → readParquet-e3ed4528.js} +3 -3
  145. flowfile/web/static/assets/secrets.api-002e7d7e.js +65 -0
  146. flowfile/web/static/assets/{selectDynamic-92e25ee3.js → selectDynamic-80b92899.js} +5 -5
  147. flowfile/web/static/assets/{selectDynamic-aa913ff4.css → selectDynamic-f2fb394f.css} +21 -20
  148. flowfile/web/static/assets/{vue-codemirror.esm-41b0e0d7.js → vue-codemirror.esm-0965f39f.js} +31 -640
  149. flowfile/web/static/assets/{vue-content-loader.es-2c8e608f.js → vue-content-loader.es-c506ad97.js} +1 -1
  150. flowfile/web/static/index.html +2 -2
  151. {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/METADATA +2 -3
  152. flowfile-0.5.3.dist-info/RECORD +402 -0
  153. flowfile_core/__init__.py +13 -6
  154. flowfile_core/auth/jwt.py +51 -16
  155. flowfile_core/auth/models.py +32 -7
  156. flowfile_core/auth/password.py +89 -0
  157. flowfile_core/auth/secrets.py +8 -6
  158. flowfile_core/configs/__init__.py +9 -7
  159. flowfile_core/configs/flow_logger.py +15 -14
  160. flowfile_core/configs/node_store/__init__.py +72 -4
  161. flowfile_core/configs/node_store/nodes.py +155 -172
  162. flowfile_core/configs/node_store/user_defined_node_registry.py +108 -27
  163. flowfile_core/configs/settings.py +28 -15
  164. flowfile_core/database/connection.py +7 -6
  165. flowfile_core/database/init_db.py +96 -2
  166. flowfile_core/database/models.py +3 -1
  167. flowfile_core/fileExplorer/__init__.py +17 -0
  168. flowfile_core/fileExplorer/funcs.py +123 -57
  169. flowfile_core/fileExplorer/utils.py +10 -11
  170. flowfile_core/flowfile/_extensions/real_time_interface.py +10 -8
  171. flowfile_core/flowfile/analytics/analytics_processor.py +26 -24
  172. flowfile_core/flowfile/analytics/graphic_walker.py +11 -12
  173. flowfile_core/flowfile/analytics/utils.py +1 -1
  174. flowfile_core/flowfile/code_generator/code_generator.py +358 -244
  175. flowfile_core/flowfile/connection_manager/_connection_manager.py +6 -5
  176. flowfile_core/flowfile/connection_manager/models.py +1 -1
  177. flowfile_core/flowfile/database_connection_manager/db_connections.py +60 -44
  178. flowfile_core/flowfile/database_connection_manager/models.py +1 -1
  179. flowfile_core/flowfile/extensions.py +17 -12
  180. flowfile_core/flowfile/flow_data_engine/cloud_storage_reader.py +34 -32
  181. flowfile_core/flowfile/flow_data_engine/create/funcs.py +115 -83
  182. flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +481 -423
  183. flowfile_core/flowfile/flow_data_engine/flow_file_column/interface.py +2 -2
  184. flowfile_core/flowfile/flow_data_engine/flow_file_column/main.py +92 -52
  185. flowfile_core/flowfile/flow_data_engine/flow_file_column/polars_type.py +12 -11
  186. flowfile_core/flowfile/flow_data_engine/flow_file_column/type_registry.py +6 -6
  187. flowfile_core/flowfile/flow_data_engine/flow_file_column/utils.py +26 -30
  188. flowfile_core/flowfile/flow_data_engine/fuzzy_matching/prepare_for_fuzzy_match.py +31 -20
  189. flowfile_core/flowfile/flow_data_engine/join/__init__.py +1 -1
  190. flowfile_core/flowfile/flow_data_engine/join/utils.py +11 -9
  191. flowfile_core/flowfile/flow_data_engine/join/verify_integrity.py +14 -15
  192. flowfile_core/flowfile/flow_data_engine/pivot_table.py +5 -7
  193. flowfile_core/flowfile/flow_data_engine/polars_code_parser.py +95 -82
  194. flowfile_core/flowfile/flow_data_engine/read_excel_tables.py +66 -65
  195. flowfile_core/flowfile/flow_data_engine/sample_data.py +27 -21
  196. flowfile_core/flowfile/flow_data_engine/subprocess_operations/__init__.py +1 -1
  197. flowfile_core/flowfile/flow_data_engine/subprocess_operations/models.py +13 -11
  198. flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +190 -127
  199. flowfile_core/flowfile/flow_data_engine/threaded_processes.py +8 -8
  200. flowfile_core/flowfile/flow_data_engine/utils.py +99 -67
  201. flowfile_core/flowfile/flow_graph.py +918 -571
  202. flowfile_core/flowfile/flow_graph_utils.py +31 -49
  203. flowfile_core/flowfile/flow_node/flow_node.py +330 -233
  204. flowfile_core/flowfile/flow_node/models.py +53 -41
  205. flowfile_core/flowfile/flow_node/schema_callback.py +14 -19
  206. flowfile_core/flowfile/graph_tree/graph_tree.py +41 -41
  207. flowfile_core/flowfile/handler.py +80 -30
  208. flowfile_core/flowfile/manage/compatibility_enhancements.py +209 -126
  209. flowfile_core/flowfile/manage/io_flowfile.py +54 -57
  210. flowfile_core/flowfile/node_designer/__init__.py +15 -13
  211. flowfile_core/flowfile/node_designer/_type_registry.py +34 -37
  212. flowfile_core/flowfile/node_designer/custom_node.py +162 -36
  213. flowfile_core/flowfile/node_designer/ui_components.py +135 -34
  214. flowfile_core/flowfile/schema_callbacks.py +71 -51
  215. flowfile_core/flowfile/setting_generator/__init__.py +0 -1
  216. flowfile_core/flowfile/setting_generator/setting_generator.py +6 -5
  217. flowfile_core/flowfile/setting_generator/settings.py +64 -53
  218. flowfile_core/flowfile/sources/external_sources/base_class.py +12 -10
  219. flowfile_core/flowfile/sources/external_sources/custom_external_sources/external_source.py +27 -17
  220. flowfile_core/flowfile/sources/external_sources/custom_external_sources/sample_users.py +9 -9
  221. flowfile_core/flowfile/sources/external_sources/factory.py +0 -1
  222. flowfile_core/flowfile/sources/external_sources/sql_source/models.py +45 -31
  223. flowfile_core/flowfile/sources/external_sources/sql_source/sql_source.py +198 -73
  224. flowfile_core/flowfile/sources/external_sources/sql_source/utils.py +250 -196
  225. flowfile_core/flowfile/util/calculate_layout.py +9 -13
  226. flowfile_core/flowfile/util/execution_orderer.py +25 -17
  227. flowfile_core/flowfile/util/node_skipper.py +4 -4
  228. flowfile_core/flowfile/utils.py +19 -21
  229. flowfile_core/main.py +26 -19
  230. flowfile_core/routes/auth.py +284 -11
  231. flowfile_core/routes/cloud_connections.py +25 -25
  232. flowfile_core/routes/logs.py +21 -29
  233. flowfile_core/routes/public.py +3 -3
  234. flowfile_core/routes/routes.py +70 -34
  235. flowfile_core/routes/secrets.py +25 -27
  236. flowfile_core/routes/user_defined_components.py +483 -4
  237. flowfile_core/run_lock.py +0 -1
  238. flowfile_core/schemas/__init__.py +4 -6
  239. flowfile_core/schemas/analysis_schemas/graphic_walker_schemas.py +55 -55
  240. flowfile_core/schemas/cloud_storage_schemas.py +59 -53
  241. flowfile_core/schemas/input_schema.py +231 -144
  242. flowfile_core/schemas/output_model.py +49 -34
  243. flowfile_core/schemas/schemas.py +116 -89
  244. flowfile_core/schemas/transform_schema.py +518 -263
  245. flowfile_core/schemas/yaml_types.py +21 -7
  246. flowfile_core/secret_manager/secret_manager.py +17 -13
  247. flowfile_core/types.py +29 -9
  248. flowfile_core/utils/arrow_reader.py +7 -6
  249. flowfile_core/utils/excel_file_manager.py +3 -3
  250. flowfile_core/utils/fileManager.py +7 -7
  251. flowfile_core/utils/fl_executor.py +8 -10
  252. flowfile_core/utils/utils.py +4 -4
  253. flowfile_core/utils/validate_setup.py +5 -4
  254. flowfile_frame/__init__.py +106 -51
  255. flowfile_frame/adapters.py +2 -9
  256. flowfile_frame/adding_expr.py +73 -32
  257. flowfile_frame/cloud_storage/frame_helpers.py +27 -23
  258. flowfile_frame/cloud_storage/secret_manager.py +12 -26
  259. flowfile_frame/config.py +2 -5
  260. flowfile_frame/expr.py +311 -218
  261. flowfile_frame/expr.pyi +160 -159
  262. flowfile_frame/expr_name.py +23 -23
  263. flowfile_frame/flow_frame.py +571 -476
  264. flowfile_frame/flow_frame.pyi +123 -104
  265. flowfile_frame/flow_frame_methods.py +227 -246
  266. flowfile_frame/group_frame.py +50 -20
  267. flowfile_frame/join.py +2 -2
  268. flowfile_frame/lazy.py +129 -87
  269. flowfile_frame/lazy_methods.py +83 -30
  270. flowfile_frame/list_name_space.py +55 -50
  271. flowfile_frame/selectors.py +148 -68
  272. flowfile_frame/series.py +9 -7
  273. flowfile_frame/utils.py +19 -21
  274. flowfile_worker/__init__.py +12 -7
  275. flowfile_worker/configs.py +11 -19
  276. flowfile_worker/create/__init__.py +14 -9
  277. flowfile_worker/create/funcs.py +114 -77
  278. flowfile_worker/create/models.py +46 -43
  279. flowfile_worker/create/pl_types.py +14 -15
  280. flowfile_worker/create/read_excel_tables.py +34 -41
  281. flowfile_worker/create/utils.py +22 -19
  282. flowfile_worker/external_sources/s3_source/main.py +18 -51
  283. flowfile_worker/external_sources/s3_source/models.py +34 -27
  284. flowfile_worker/external_sources/sql_source/main.py +8 -5
  285. flowfile_worker/external_sources/sql_source/models.py +13 -9
  286. flowfile_worker/flow_logger.py +10 -8
  287. flowfile_worker/funcs.py +214 -155
  288. flowfile_worker/main.py +11 -17
  289. flowfile_worker/models.py +35 -28
  290. flowfile_worker/process_manager.py +2 -3
  291. flowfile_worker/routes.py +121 -90
  292. flowfile_worker/secrets.py +9 -6
  293. flowfile_worker/spawner.py +80 -49
  294. flowfile_worker/utils.py +3 -2
  295. shared/__init__.py +2 -7
  296. shared/storage_config.py +25 -13
  297. test_utils/postgres/commands.py +3 -2
  298. test_utils/postgres/fixtures.py +9 -9
  299. test_utils/s3/commands.py +1 -1
  300. test_utils/s3/data_generator.py +3 -4
  301. test_utils/s3/demo_data_generator.py +4 -7
  302. test_utils/s3/fixtures.py +7 -5
  303. tools/migrate/__init__.py +1 -1
  304. tools/migrate/__main__.py +16 -29
  305. tools/migrate/legacy_schemas.py +251 -190
  306. tools/migrate/migrate.py +193 -181
  307. tools/migrate/tests/conftest.py +1 -3
  308. tools/migrate/tests/test_migrate.py +36 -41
  309. tools/migrate/tests/test_migration_e2e.py +28 -29
  310. tools/migrate/tests/test_node_migrations.py +50 -20
  311. flowfile/web/static/assets/CloudConnectionManager-2dfdce2f.css +0 -86
  312. flowfile/web/static/assets/CustomNode-74a37f74.css +0 -32
  313. flowfile/web/static/assets/DatabaseManager-30fa27e5.css +0 -64
  314. flowfile/web/static/assets/Filter-9b6d08db.js +0 -164
  315. flowfile/web/static/assets/Filter-f62091b3.css +0 -20
  316. flowfile/web/static/assets/ManualInput-3246a08d.css +0 -96
  317. flowfile/web/static/assets/PivotValidation-891ddfb0.css +0 -13
  318. flowfile/web/static/assets/PivotValidation-c46cd420.css +0 -13
  319. flowfile/web/static/assets/SliderInput-b8fb6a8c.css +0 -4
  320. flowfile/web/static/assets/UnpivotValidation-0d240eeb.css +0 -13
  321. flowfile/web/static/assets/nodeInput-5d0d6b79.js +0 -41
  322. flowfile/web/static/assets/outputCsv-9cc59e0b.css +0 -2499
  323. flowfile/web/static/assets/outputParquet-cf8cf3f2.css +0 -4
  324. flowfile/web/static/assets/secretApi-68435402.js +0 -46
  325. flowfile/web/static/assets/vue-codemirror-bccfde04.css +0 -32
  326. flowfile-0.5.1.dist-info/RECORD +0 -388
  327. {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/WHEEL +0 -0
  328. {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/entry_points.txt +0 -0
  329. {flowfile-0.5.1.dist-info → flowfile-0.5.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,17 +1,33 @@
1
- import polars as pl
1
+ from collections.abc import Callable
2
2
  from functools import wraps
3
- from typing import Optional, TypeVar, Type, Callable
4
- from flowfile_frame.utils import _get_function_source
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('T')
8
- FlowFrameT = TypeVar('FlowFrameT', bound='FlowFrame')
10
+ T = TypeVar("T")
11
+ FlowFrameT = TypeVar("FlowFrameT", bound="FlowFrame")
9
12
 
10
13
  PASSTHROUGH_METHODS = {
11
- 'collect', 'collect_async', 'profile', 'describe', 'explain',
12
- 'show_graph', 'fetch', 'collect_schema', 'columns', 'dtypes',
13
- 'schema', 'width', 'estimated_size', 'n_chunks', 'is_empty',
14
- 'chunk_lengths', 'get_meta'
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", "select", "with_columns", "sort", "filter", "join", "head", "tail",
37
- "limit", "drop_nulls", "fill_null", "with_row_index", "group_by", "explode",
38
- "unique", "slice", "shift", "reverse", "max", "min", "sum", "mean", "median",
39
- "std", "var", "drop_nans", "fill_nan", "interpolate", "null_count", "quantile",
40
- "unpivot", "melt", "first", "last"
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", "collect_schema", "fetch", "columns", "dtypes", "schema", "width",
45
- "describe", "explain", "profile", "show_graph"
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
- method_name in lazyframe_returning_methods or
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: Optional[str] = None, **kwargs):
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 getattr(arg, 'convertable_to_code') for arg in
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, '__name__') and arg.__name__ != '<lambda>':
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, '__name__') and value.__name__ != '<lambda>':
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 for name in existing_methods
197
- if name in dir(pl.LazyFrame) and not name.startswith('_') and callable(getattr(pl.LazyFrame, name))
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 typing import Any, Optional, Union, TYPE_CHECKING, List, TypeVar, Callable, Sequence, Literal
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: 'Expr', parent_repr_str: str):
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(self, *args, method_name: str, result_expr: Optional[pl.Expr], is_complex: bool = True, **kwargs) -> '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
- self,
71
- n: int | IntoExprColumn | None = None,
72
- *,
73
- fraction: float | IntoExprColumn | None = None,
74
- with_replacement: bool = False,
75
- shuffle: bool = False,
76
- seed: int | None = None,
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, 'expr') else fraction
86
- res_expr = self.expr.sample(n=None, fraction=expr_fraction,
87
- with_replacement=with_replacement,
88
- shuffle=shuffle, seed=seed)
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, 'expr') else (1 if n is None else n)
91
- res_expr = self.expr.sample(n=expr_n, fraction=None,
92
- with_replacement=with_replacement,
93
- shuffle=shuffle, seed=seed)
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(method_name="sort", result_expr=res_expr, descending=descending, nulls_last=nulls_last)
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, 'expr') else (pl.col(o) if isinstance(o, str) else o) for o in other]
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, 'expr') else 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, 'expr'):
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, 'expr') else n
202
- offset_expr = offset.expr if hasattr(offset, 'expr') else 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, 'expr') else 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, 'expr') else 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, 'expr') else 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, 'expr') else offset
244
- length_expr = length.expr if hasattr(length, 'expr') and length is not None else 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, 'expr') else 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, 'expr') else 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, 'expr') else 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
- self,
274
- n_field_strategy: ListToStructWidthStrategy = "first_non_null",
275
- fields: Sequence[str] | Callable[[int], str] | None = None,
276
- upper_bound: int = 0,
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, 'expr') else 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, 'expr') else 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, 'expr') else 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, 'expr') else 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, 'expr') else 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)