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,9 +1,14 @@
1
- from flowfile_frame.expr import col, Expr, Column, lit
2
- from flowfile_frame.selectors import Selector
3
- from flowfile_frame.utils import _parse_inputs_as_iterable
4
- from flowfile_core.schemas import transform_schema, input_schema
5
1
  from typing import TYPE_CHECKING, Any
6
- from flowfile_frame.utils import _check_if_convertible_to_code, ensure_inputs_as_iterable, get_pl_expr_from_expr
2
+
3
+ from flowfile_core.schemas import input_schema, transform_schema
4
+ from flowfile_frame.expr import Column, Expr, col, lit
5
+ from flowfile_frame.selectors import Selector
6
+ from flowfile_frame.utils import (
7
+ _check_if_convertible_to_code,
8
+ _parse_inputs_as_iterable,
9
+ ensure_inputs_as_iterable,
10
+ get_pl_expr_from_expr,
11
+ )
7
12
 
8
13
  if TYPE_CHECKING:
9
14
  from flowfile_frame.flow_frame import FlowFrame
@@ -53,11 +58,11 @@ class GroupByFrame:
53
58
  parts.append(f'''"{str(c)}"''')
54
59
  return ", ".join(parts)
55
60
 
56
- def len(self) -> 'FlowFrame':
61
+ def len(self) -> "FlowFrame":
57
62
  """Count number of rows per group. Output column is named 'len'."""
58
63
  return self._generate_direct_polars_code("len")
59
64
 
60
- def count(self) -> 'FlowFrame':
65
+ def count(self) -> "FlowFrame":
61
66
  """Count number of rows per group. Output column is named 'count'."""
62
67
  return self._generate_direct_polars_code("count")
63
68
 
@@ -82,8 +87,15 @@ class GroupByFrame:
82
87
  if can_be_converted:
83
88
  can_be_converted = self._process_named_agg_expressions(agg_cols, named_agg_exprs)
84
89
  node_desc = self.description or f"Aggregate after grouping by {self.readable_group()}"
85
- return self._create_agg_node(self.node_id, can_be_converted, agg_cols, agg_expressions, named_agg_exprs,
86
- convertable_to_code=convertable_to_code, description=node_desc)
90
+ return self._create_agg_node(
91
+ self.node_id,
92
+ can_be_converted,
93
+ agg_cols,
94
+ agg_expressions,
95
+ named_agg_exprs,
96
+ convertable_to_code=convertable_to_code,
97
+ description=node_desc,
98
+ )
87
99
 
88
100
  def _process_group_columns(self, agg_cols: list[transform_schema.AggColl]) -> bool:
89
101
  """Process grouping columns for aggregation schema."""
@@ -150,8 +162,16 @@ class GroupByFrame:
150
162
  return False
151
163
  return True
152
164
 
153
- def _create_agg_node(self, node_id_to_use: int, can_be_converted: bool, agg_cols: list, agg_expressions,
154
- named_agg_exprs, convertable_to_code: bool, description: str):
165
+ def _create_agg_node(
166
+ self,
167
+ node_id_to_use: int,
168
+ can_be_converted: bool,
169
+ agg_cols: list,
170
+ agg_expressions,
171
+ named_agg_exprs,
172
+ convertable_to_code: bool,
173
+ description: str,
174
+ ):
155
175
  """Create node for explicit aggregations via self.agg()."""
156
176
 
157
177
  if can_be_converted:
@@ -159,9 +179,11 @@ class GroupByFrame:
159
179
  flow_id=self.parent.flow_graph.flow_id,
160
180
  node_id=node_id_to_use,
161
181
  groupby_input=transform_schema.GroupByInput(agg_cols=agg_cols),
162
- pos_x=200, pos_y=200, is_setup=True,
182
+ pos_x=200,
183
+ pos_y=200,
184
+ is_setup=True,
163
185
  depending_on_id=self.parent.node_id,
164
- description=description
186
+ description=description,
165
187
  )
166
188
  self.parent.flow_graph.add_group_by(group_by_settings)
167
189
  else:
@@ -169,11 +191,17 @@ class GroupByFrame:
169
191
  pl_agg_expressions = list(map(get_pl_expr_from_expr, ensure_inputs_as_iterable(agg_expressions)))
170
192
  pl_group_expr = list(map(get_pl_expr_from_expr, ensure_inputs_as_iterable(self.expr_by_cols)))
171
193
  pl_kwargs_expr = {k: self._create_expr_col(c).expr for k, c in named_agg_exprs.items()}
172
- self.parent._add_polars_code(new_node_id=node_id_to_use, code=code, description=description,
173
- method_name='group_by', convertable_to_code=convertable_to_code,
174
- polars_expr=pl_agg_expressions, group_expr=pl_group_expr,
175
- kwargs_expr=pl_kwargs_expr,
176
- group_kwargs={'maintain_order': self.maintain_order})
194
+ self.parent._add_polars_code(
195
+ new_node_id=node_id_to_use,
196
+ code=code,
197
+ description=description,
198
+ method_name="group_by",
199
+ convertable_to_code=convertable_to_code,
200
+ polars_expr=pl_agg_expressions,
201
+ group_expr=pl_group_expr,
202
+ kwargs_expr=pl_kwargs_expr,
203
+ group_kwargs={"maintain_order": self.maintain_order},
204
+ )
177
205
  return self.parent._create_child_frame(node_id_to_use)
178
206
 
179
207
  def _generate_direct_polars_code(self, method_name: str, *args, **kwargs) -> "FlowFrame":
@@ -190,7 +218,9 @@ class GroupByFrame:
190
218
  readable_group_str = self.readable_group()
191
219
  execution = "(" + ",".join(args) + ",".join([f"{k}={v}" for k, v in kwargs.items()]) + ")"
192
220
 
193
- code = f"input_df.group_by([{readable_group_str}], maintain_order={self.maintain_order}).{method_name}{execution}"
221
+ code = (
222
+ f"input_df.group_by([{readable_group_str}], maintain_order={self.maintain_order}).{method_name}{execution}"
223
+ )
194
224
  node_description = self.description or f"{method_name.capitalize()} after grouping by {readable_group_str}"
195
225
  self.parent._add_polars_code(new_node_id=self.node_id, code=code, description=node_description)
196
226
  return self.parent._create_child_frame(self.node_id)
@@ -246,4 +276,4 @@ class GroupByFrame:
246
276
 
247
277
  def last(self):
248
278
  """Get last value for all non-grouping columns."""
249
- return self._generate_direct_polars_code("last")
279
+ return self._generate_direct_polars_code("last")
flowfile_frame/join.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Assume these imports are correct from your original context
2
- from flowfile_frame.expr import Column
3
2
  from flowfile_core.schemas import transform_schema
3
+ from flowfile_frame.expr import Column
4
4
 
5
5
 
6
6
  def _normalize_columns_to_list(columns):
@@ -61,7 +61,7 @@ def _create_join_mappings(left_columns, right_columns):
61
61
  join_mappings = []
62
62
  needs_polars_code = False
63
63
 
64
- for left_col, right_col in zip(left_columns, right_columns):
64
+ for left_col, right_col in zip(left_columns, right_columns, strict=False):
65
65
  left_name, left_needs_code = _extract_column_name(left_col)
66
66
  right_name, right_needs_code = _extract_column_name(right_col)
67
67
 
flowfile_frame/lazy.py CHANGED
@@ -1,12 +1,14 @@
1
1
  import inspect
2
- from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
2
+ from collections.abc import Callable
3
+ from functools import wraps
4
+ from typing import Any, Literal, Optional, cast
5
+
3
6
  import polars as pl
4
- from flowfile_frame.flow_frame import FlowFrame, can_be_expr, generate_node_id
7
+
5
8
  from flowfile_core.flowfile.flow_graph import FlowGraph
6
9
  from flowfile_frame.expr import Expr
10
+ from flowfile_frame.flow_frame import FlowFrame, can_be_expr, generate_node_id
7
11
  from flowfile_frame.utils import _get_function_source
8
- from typing import cast
9
- from functools import wraps
10
12
 
11
13
 
12
14
  def _determine_return_type(func_signature: inspect.Signature) -> Literal["FlowFrame", "Expr"]:
@@ -32,16 +34,18 @@ def _determine_return_type(func_signature: inspect.Signature) -> Literal["FlowFr
32
34
  # Allow for type aliases or Union types that might include DataFrame/LazyFrame/Expr
33
35
  if "DataFrame" in return_annotation or "LazyFrame" in return_annotation:
34
36
  return "FlowFrame"
35
- if "Expr" in return_annotation and "DataFrame" not in return_annotation and "LazyFrame" not in return_annotation:
37
+ if (
38
+ "Expr" in return_annotation
39
+ and "DataFrame" not in return_annotation
40
+ and "LazyFrame" not in return_annotation
41
+ ):
36
42
  return "Expr"
37
- raise ValueError(
38
- f"Function does not return a Frame or Expr. "
39
- f"Got return annotation: {return_annotation}"
40
- )
43
+ raise ValueError(f"Function does not return a Frame or Expr. " f"Got return annotation: {return_annotation}")
41
44
 
42
45
 
43
- def _analyze_parameters(func_signature: inspect.Signature) -> Tuple[
44
- Dict[str, bool], List[Tuple[str, inspect.Parameter]]]:
46
+ def _analyze_parameters(
47
+ func_signature: inspect.Signature,
48
+ ) -> tuple[dict[str, bool], list[tuple[str, inspect.Parameter]]]:
45
49
  """
46
50
  Analyze function parameters to determine which can accept Expr types.
47
51
 
@@ -99,6 +103,7 @@ def _deep_get_repr(obj: Any, can_be_expr: bool = False) -> str:
99
103
  String representation suitable for code generation
100
104
  """
101
105
  from flowfile_frame.expr import _get_expr_and_repr
106
+
102
107
  if isinstance(obj, Expr):
103
108
  # FlowFile Expr - get its representation
104
109
  _, repr_str = _get_expr_and_repr(obj)
@@ -131,7 +136,7 @@ def _deep_get_repr(obj: Any, can_be_expr: bool = False) -> str:
131
136
  return repr(obj)
132
137
 
133
138
 
134
- def _process_callable_arg(arg: Any) -> Tuple[str, Any, bool, Optional[str]]:
139
+ def _process_callable_arg(arg: Any) -> tuple[str, Any, bool, str | None]:
135
140
  """
136
141
  Process a callable argument for representation and conversion.
137
142
 
@@ -154,7 +159,7 @@ def _process_callable_arg(arg: Any) -> Tuple[str, Any, bool, Optional[str]]:
154
159
  return repr(arg), arg, False, None
155
160
 
156
161
 
157
- def _process_argument(arg: Any, can_be_expr: bool) -> Tuple[str, Any, bool, Optional[str]]:
162
+ def _process_argument(arg: Any, can_be_expr: bool) -> tuple[str, Any, bool, str | None]:
158
163
  """
159
164
  Process a single argument, handling all types including nested structures.
160
165
 
@@ -166,7 +171,7 @@ def _process_argument(arg: Any, can_be_expr: bool) -> Tuple[str, Any, bool, Opti
166
171
  Tuple of (repr_string, processed_arg_for_polars, convertible_to_code, function_source)
167
172
  """
168
173
  # Special handling for callables (but not Expr objects which might be callable)
169
- if callable(arg) and not isinstance(arg, (Expr, pl.Expr)) and not hasattr(arg, 'expr'):
174
+ if callable(arg) and not isinstance(arg, (Expr, pl.Expr)) and not hasattr(arg, "expr"):
170
175
  return _process_callable_arg(arg)
171
176
  repr_str = _deep_get_repr(arg, can_be_expr)
172
177
 
@@ -177,8 +182,9 @@ def _process_argument(arg: Any, can_be_expr: bool) -> Tuple[str, Any, bool, Opti
177
182
  return repr_str, processed_arg, convertible, None
178
183
 
179
184
 
180
- def _process_arguments(args: Tuple[Any, ...], param_can_be_expr: Dict[str, bool],
181
- param_list: List[Tuple[str, inspect.Parameter]]) -> Tuple[List[str], List[Any], bool, List[str]]:
185
+ def _process_arguments(
186
+ args: tuple[Any, ...], param_can_be_expr: dict[str, bool], param_list: list[tuple[str, inspect.Parameter]]
187
+ ) -> tuple[list[str], list[Any], bool, list[str]]:
182
188
  """
183
189
  Process positional arguments for the wrapper function.
184
190
 
@@ -213,8 +219,9 @@ def _process_arguments(args: Tuple[Any, ...], param_can_be_expr: Dict[str, bool]
213
219
  return args_repr, pl_args, convertible_to_code, function_sources
214
220
 
215
221
 
216
- def _process_keyword_arguments(kwargs: Dict[str, Any],
217
- param_can_be_expr: Dict[str, bool]) -> Tuple[List[str], Dict[str, Any], bool, List[str]]:
222
+ def _process_keyword_arguments(
223
+ kwargs: dict[str, Any], param_can_be_expr: dict[str, bool]
224
+ ) -> tuple[list[str], dict[str, Any], bool, list[str]]:
218
225
  """
219
226
  Process keyword arguments for the wrapper function.
220
227
 
@@ -244,8 +251,9 @@ def _process_keyword_arguments(kwargs: Dict[str, Any],
244
251
  return kwargs_repr, pl_kwargs, convertible_to_code, function_sources
245
252
 
246
253
 
247
- def _build_repr_string(polars_func_name: str, args_repr: List[str], kwargs_repr: List[str],
248
- function_sources: List[str] = None) -> str:
254
+ def _build_repr_string(
255
+ polars_func_name: str, args_repr: list[str], kwargs_repr: list[str], function_sources: list[str] = None
256
+ ) -> str:
249
257
  """
250
258
  Build the string representation of the function call.
251
259
 
@@ -290,7 +298,7 @@ def _build_repr_string(polars_func_name: str, args_repr: List[str], kwargs_repr:
290
298
  return call_repr
291
299
 
292
300
 
293
- def _create_flowframe_result(polars_func_name: str, full_repr: str, flow_graph: Optional[Any]) -> "FlowFrame":
301
+ def _create_flowframe_result(polars_func_name: str, full_repr: str, flow_graph: Any | None) -> "FlowFrame":
294
302
  """
295
303
  Create a FlowFrame result for functions that return DataFrames/LazyFrames.
296
304
 
@@ -320,11 +328,12 @@ def _create_flowframe_result(polars_func_name: str, full_repr: str, flow_graph:
320
328
  node_id=node_id,
321
329
  depending_on_ids=[],
322
330
  description=f"Execute: {polars_func_name}",
323
- polars_code_input=transform_schema.PolarsCodeInput(polars_code)
331
+ polars_code_input=transform_schema.PolarsCodeInput(polars_code),
324
332
  )
325
333
  flow_graph.add_polars_code(node_polars_code)
326
334
 
327
335
  try:
336
+
328
337
  class MockNode:
329
338
  def get_resulting_data(self):
330
339
  class MockData:
@@ -332,7 +341,7 @@ def _create_flowframe_result(polars_func_name: str, full_repr: str, flow_graph:
332
341
 
333
342
  return MockData()
334
343
 
335
- if not hasattr(flow_graph, 'get_node'):
344
+ if not hasattr(flow_graph, "get_node"):
336
345
  flow_graph.get_node = lambda nid: MockNode()
337
346
 
338
347
  actual_data = flow_graph.get_node(node_id).get_resulting_data().data_frame
@@ -348,7 +357,7 @@ def _create_flowframe_result(polars_func_name: str, full_repr: str, flow_graph:
348
357
  )
349
358
 
350
359
 
351
- def _check_for_non_serializable_functions(args: List[Any], kwargs: Dict[str, Any]) -> List[str]:
360
+ def _check_for_non_serializable_functions(args: list[Any], kwargs: dict[str, Any]) -> list[str]:
352
361
  """
353
362
  Check for non-serializable functions in arguments and return warnings.
354
363
 
@@ -365,16 +374,16 @@ def _check_for_non_serializable_functions(args: List[Any], kwargs: Dict[str, Any
365
374
  """Recursively check for non-serializable functions."""
366
375
  if callable(value) and not isinstance(value, (type, pl.Expr)):
367
376
  # Check if it's a lambda or local function
368
- if hasattr(value, '__name__'):
369
- if value.__name__ == '<lambda>':
377
+ if hasattr(value, "__name__"):
378
+ if value.__name__ == "<lambda>":
370
379
  warnings.append(
371
380
  f"Lambda function found at {path}. "
372
381
  "This will cause 'serialization not supported for this opaque function' error. "
373
382
  "Consider using a named function at module level instead."
374
383
  )
375
- elif hasattr(value, '__code__') and value.__code__.co_flags & 0x10: # CO_NESTED flag
384
+ elif hasattr(value, "__code__") and value.__code__.co_flags & 0x10: # CO_NESTED flag
376
385
  # Check if it's a local/nested function (excluding top-level module functions)
377
- if value.__code__.co_name != '<module>': # Ensure it's not a module itself
386
+ if value.__code__.co_name != "<module>": # Ensure it's not a module itself
378
387
  warnings.append(
379
388
  f"Local function '{value.__name__}' found at {path}. "
380
389
  "This may cause serialization issues. "
@@ -401,9 +410,16 @@ def _check_for_non_serializable_functions(args: List[Any], kwargs: Dict[str, Any
401
410
  return warnings
402
411
 
403
412
 
404
- def _create_expr_result(polars_func: Callable, pl_args: List[Any], pl_kwargs: Dict[str, Any],
405
- polars_func_name: str, full_repr: str, is_agg: bool,
406
- convertible_to_code: bool, function_sources: List[str] = None) -> "Expr":
413
+ def _create_expr_result(
414
+ polars_func: Callable,
415
+ pl_args: list[Any],
416
+ pl_kwargs: dict[str, Any],
417
+ polars_func_name: str,
418
+ full_repr: str,
419
+ is_agg: bool,
420
+ convertible_to_code: bool,
421
+ function_sources: list[str] = None,
422
+ ) -> "Expr":
407
423
  """
408
424
  Create an Expr result for functions that return expressions.
409
425
 
@@ -422,9 +438,10 @@ def _create_expr_result(polars_func: Callable, pl_args: List[Any], pl_kwargs: Di
422
438
  Returns:
423
439
  Expr instance wrapping the polars expression
424
440
  """
425
- from flowfile_frame.expr import Expr
426
441
  import warnings
427
442
 
443
+ from flowfile_frame.expr import Expr
444
+
428
445
  # Check for non-serializable functions
429
446
  serialization_warnings = _check_for_non_serializable_functions(pl_args, pl_kwargs)
430
447
 
@@ -440,28 +457,30 @@ def _create_expr_result(polars_func: Callable, pl_args: List[Any], pl_kwargs: Di
440
457
  try:
441
458
  # Test serialization
442
459
  import io
460
+
443
461
  buffer = io.BytesIO()
444
- pl_expr.serialize(file=buffer, format='json')
462
+ pl_expr.serialize(file=buffer, format="json")
445
463
  except Exception as e:
446
464
  serialization_error = str(e)
447
465
 
448
466
  except Exception as e:
449
467
  print(
450
- f"Warning: Polars function '{polars_func_name}' failed to create an expression with provided arguments. Error: {e}")
468
+ f"Warning: Polars function '{polars_func_name}' failed to create an expression with provided arguments. Error: {e}"
469
+ )
451
470
  if "serialization not supported" in str(e).lower():
452
471
  serialization_error = str(e)
453
472
 
454
473
  # Issue warnings if we found non-serializable functions
455
474
  if serialization_warnings:
456
475
  warnings.warn(
457
- f"\n⚠️ SERIALIZATION WARNING for {polars_func_name}:\n" +
458
- "\n".join(f" • {w}" for w in serialization_warnings) +
459
- "\n\nThis expression cannot be saved to a FlowFile format and will need to be " +
460
- "recreated from scratch when loading the flow. The expression will work in the " +
461
- "current session but won't persist.\n" +
462
- (f"\nActual error from Polars: {serialization_error}" if serialization_error else ""),
476
+ f"\n⚠️ SERIALIZATION WARNING for {polars_func_name}:\n"
477
+ + "\n".join(f" • {w}" for w in serialization_warnings)
478
+ + "\n\nThis expression cannot be saved to a FlowFile format and will need to be "
479
+ + "recreated from scratch when loading the flow. The expression will work in the "
480
+ + "current session but won't persist.\n"
481
+ + (f"\nActual error from Polars: {serialization_error}" if serialization_error else ""),
463
482
  category=UserWarning,
464
- stacklevel=3
483
+ stacklevel=3,
465
484
  )
466
485
 
467
486
  # Extract just the expression part without function definitions for repr_str
@@ -469,7 +488,7 @@ def _create_expr_result(polars_func: Callable, pl_args: List[Any], pl_kwargs: Di
469
488
  # Get the part after the split
470
489
  repr_str = full_repr.split("─────SPLIT─────")[-1].strip()
471
490
  if repr_str.startswith("output_df = "):
472
- repr_str = repr_str[len("output_df = "):]
491
+ repr_str = repr_str[len("output_df = ") :]
473
492
  else:
474
493
  repr_str = full_repr
475
494
 
@@ -479,11 +498,11 @@ def _create_expr_result(polars_func: Callable, pl_args: List[Any], pl_kwargs: Di
479
498
  agg_func=polars_func_name if is_agg else None,
480
499
  is_complex=True,
481
500
  convertable_to_code=convertible_to_code and (pl_expr is not None),
482
- _function_sources=function_sources # Pass function sources to Expr
501
+ _function_sources=function_sources, # Pass function sources to Expr
483
502
  )
484
503
 
485
504
 
486
- def _copy_function_metadata(original_func: Callable, polars_func_name: str) -> Tuple[str, str]:
505
+ def _copy_function_metadata(original_func: Callable, polars_func_name: str) -> tuple[str, str]:
487
506
  """
488
507
  Copy metadata from the original polars function.
489
508
 
@@ -494,7 +513,7 @@ def _copy_function_metadata(original_func: Callable, polars_func_name: str) -> T
494
513
  Returns:
495
514
  Tuple of (function_name, docstring)
496
515
  """
497
- original_doc = getattr(original_func, '__doc__', None) or ""
516
+ original_doc = getattr(original_func, "__doc__", None) or ""
498
517
  enhanced_doc = f"""FlowFile wrapper for pl.{polars_func_name}.
499
518
 
500
519
  Original Polars documentation:
@@ -509,9 +528,9 @@ Wrapped functions returning Exprs will produce FlowFile Expr objects.
509
528
 
510
529
 
511
530
  def polars_function_wrapper(
512
- polars_func_name_or_callable: Union[str, Callable],
513
- is_agg: bool = False,
514
- return_type: Optional[Literal["FlowFrame", "Expr"]] = None
531
+ polars_func_name_or_callable: str | Callable,
532
+ is_agg: bool = False,
533
+ return_type: Literal["FlowFrame", "Expr"] | None = None,
515
534
  ):
516
535
  """
517
536
  Create a wrapper for a polars function that returns either a FlowFrame or Expr.
@@ -547,31 +566,35 @@ def polars_function_wrapper(
547
566
  wrapper_return_annotation_str: str
548
567
 
549
568
  if determined_rt == "FlowFrame":
550
- wrapper_return_annotation_str = 'FlowFrame'
551
- if not any(p.name == 'flow_graph' for p in final_params_for_sig):
569
+ wrapper_return_annotation_str = "FlowFrame"
570
+ if not any(p.name == "flow_graph" for p in final_params_for_sig):
552
571
  fg_param = inspect.Parameter(
553
- name='flow_graph', kind=inspect.Parameter.KEYWORD_ONLY,
554
- default=None, annotation=Optional[FlowGraph] # Corrected annotation
572
+ name="flow_graph",
573
+ kind=inspect.Parameter.KEYWORD_ONLY,
574
+ default=None,
575
+ annotation=Optional[FlowGraph], # Corrected annotation
555
576
  )
556
577
  var_kw_idx = next(
557
- (i for i, p in enumerate(final_params_for_sig) if p.kind == inspect.Parameter.VAR_KEYWORD), -1)
578
+ (i for i, p in enumerate(final_params_for_sig) if p.kind == inspect.Parameter.VAR_KEYWORD), -1
579
+ )
558
580
  if var_kw_idx != -1:
559
581
  final_params_for_sig.insert(var_kw_idx, fg_param)
560
582
  else:
561
583
  final_params_for_sig.append(fg_param)
562
584
  elif determined_rt == "Expr":
563
- wrapper_return_annotation_str = 'Expr'
585
+ wrapper_return_annotation_str = "Expr"
564
586
  else:
565
587
  wrapper_return_annotation_str = str(original_polars_sig.return_annotation)
566
588
 
567
- wrapper_sig = inspect.Signature(parameters=final_params_for_sig,
568
- return_annotation=wrapper_return_annotation_str)
589
+ wrapper_sig = inspect.Signature(
590
+ parameters=final_params_for_sig, return_annotation=wrapper_return_annotation_str
591
+ )
569
592
 
570
593
  @wraps(polars_f)
571
594
  def wrapper(*args, **kwargs):
572
595
  flow_graph_val = None
573
596
  if determined_rt == "FlowFrame":
574
- flow_graph_val = kwargs.pop('flow_graph', None)
597
+ flow_graph_val = kwargs.pop("flow_graph", None)
575
598
 
576
599
  args_repr_val, pl_args_val, args_conv, args_func_sources = _process_arguments(
577
600
  args, param_can_be_expr_map, param_list_for_processing
@@ -586,12 +609,18 @@ def polars_function_wrapper(
586
609
  actual_polars_func_name, args_repr_val, kwargs_repr_val, all_func_sources
587
610
  )
588
611
 
589
- if determined_rt == 'FlowFrame':
612
+ if determined_rt == "FlowFrame":
590
613
  return _create_flowframe_result(actual_polars_func_name, full_repr_val, flow_graph_val)
591
614
  else: # Expr
592
615
  return _create_expr_result(
593
- polars_f, pl_args_val, pl_kwargs_val, actual_polars_func_name,
594
- full_repr_val, is_agg, conv_to_code, all_func_sources # Pass function sources
616
+ polars_f,
617
+ pl_args_val,
618
+ pl_kwargs_val,
619
+ actual_polars_func_name,
620
+ full_repr_val,
621
+ is_agg,
622
+ conv_to_code,
623
+ all_func_sources, # Pass function sources
595
624
  )
596
625
 
597
626
  wrapper.__name__ = wrapper_name
@@ -604,7 +633,7 @@ def polars_function_wrapper(
604
633
  else: # Used as @polars_function_wrapper("name", ...) or assigned
605
634
  actual_polars_func_name = cast(str, polars_func_name_or_callable)
606
635
 
607
- def decorator(func: Optional[Callable] = None): # func is the decorated placeholder
636
+ def decorator(func: Callable | None = None): # func is the decorated placeholder
608
637
  polars_f = getattr(pl, actual_polars_func_name, None)
609
638
  if polars_f is None:
610
639
  raise ValueError(f"Polars function '{actual_polars_func_name}' not found.")
@@ -620,56 +649,68 @@ def polars_function_wrapper(
620
649
  wrapper_return_annotation_str: str
621
650
 
622
651
  if determined_rt == "FlowFrame":
623
- wrapper_return_annotation_str = 'FlowFrame'
624
- if not any(p.name == 'flow_graph' for p in final_params_for_sig):
652
+ wrapper_return_annotation_str = "FlowFrame"
653
+ if not any(p.name == "flow_graph" for p in final_params_for_sig):
625
654
  flow_graph_param = inspect.Parameter(
626
- name='flow_graph',
655
+ name="flow_graph",
627
656
  kind=inspect.Parameter.KEYWORD_ONLY,
628
657
  default=None,
629
- annotation=Optional[FlowGraph] # Corrected annotation
658
+ annotation=Optional[FlowGraph], # Corrected annotation
630
659
  )
631
660
  var_kw_idx = next(
632
- (i for i, p in enumerate(final_params_for_sig) if p.kind == inspect.Parameter.VAR_KEYWORD), -1)
661
+ (i for i, p in enumerate(final_params_for_sig) if p.kind == inspect.Parameter.VAR_KEYWORD), -1
662
+ )
633
663
  if var_kw_idx != -1:
634
664
  final_params_for_sig.insert(var_kw_idx, flow_graph_param)
635
665
  else:
636
666
  final_params_for_sig.append(flow_graph_param)
637
667
  elif determined_rt == "Expr":
638
- wrapper_return_annotation_str = 'Expr'
668
+ wrapper_return_annotation_str = "Expr"
639
669
  else:
640
670
  wrapper_return_annotation_str = str(original_polars_sig.return_annotation)
641
671
 
642
672
  wrapper_signature = inspect.Signature(
643
- parameters=final_params_for_sig,
644
- return_annotation=wrapper_return_annotation_str
673
+ parameters=final_params_for_sig, return_annotation=wrapper_return_annotation_str
645
674
  )
646
675
 
647
676
  @wraps(polars_f)
648
677
  def wrapper(*args, **kwargs):
649
678
  flow_graph_val = None
650
679
  if determined_rt == "FlowFrame":
651
- flow_graph_val = kwargs.pop('flow_graph', None)
680
+ flow_graph_val = kwargs.pop("flow_graph", None)
652
681
 
653
682
  args_repr_val, pl_args_val, args_convertible_val, args_func_sources = _process_arguments(
654
683
  args, param_can_be_expr_map, param_list_for_processing
655
684
  )
656
- kwargs_repr_val, pl_kwargs_val, kwargs_convertible_val, kwargs_func_sources = _process_keyword_arguments(
657
- kwargs, param_can_be_expr_map
685
+ kwargs_repr_val, pl_kwargs_val, kwargs_convertible_val, kwargs_func_sources = (
686
+ _process_keyword_arguments(kwargs, param_can_be_expr_map)
658
687
  )
659
688
 
660
- convertible_to_code_val = args_convertible_val and kwargs_convertible_val # Correct variable for this scope
689
+ convertible_to_code_val = (
690
+ args_convertible_val and kwargs_convertible_val
691
+ ) # Correct variable for this scope
661
692
  all_func_sources = args_func_sources + kwargs_func_sources
662
693
 
663
694
  full_repr_val = _build_repr_string(
664
- actual_polars_func_name, args_repr_val, kwargs_repr_val, all_func_sources # Corrected variable
695
+ actual_polars_func_name,
696
+ args_repr_val,
697
+ kwargs_repr_val,
698
+ all_func_sources, # Corrected variable
665
699
  )
666
700
 
667
- if determined_rt == 'FlowFrame':
701
+ if determined_rt == "FlowFrame":
668
702
  return _create_flowframe_result(actual_polars_func_name, full_repr_val, flow_graph_val)
669
703
  else: # Expr
670
- return _create_expr_result(polars_f, pl_args_val, pl_kwargs_val, actual_polars_func_name,
671
- full_repr_val, is_agg, convertible_to_code_val,
672
- all_func_sources) # Pass function sources
704
+ return _create_expr_result(
705
+ polars_f,
706
+ pl_args_val,
707
+ pl_kwargs_val,
708
+ actual_polars_func_name,
709
+ full_repr_val,
710
+ is_agg,
711
+ convertible_to_code_val,
712
+ all_func_sources,
713
+ ) # Pass function sources
673
714
 
674
715
  wrapper.__name__ = wrapper_name
675
716
  wrapper.__doc__ = wrapper_doc
@@ -683,22 +724,23 @@ def polars_function_wrapper(
683
724
 
684
725
  # Example usage with the new decorator (from original snippet):
685
726
 
727
+
686
728
  # For functions that return FlowFrames
687
- @polars_function_wrapper('read_json', return_type="FlowFrame")
688
- def read_json(*args, flow_graph: Optional[FlowGraph] = None, **kwargs) -> FlowFrame:
729
+ @polars_function_wrapper("read_json", return_type="FlowFrame")
730
+ def read_json(*args, flow_graph: FlowGraph | None = None, **kwargs) -> FlowFrame:
689
731
  pass
690
732
 
691
733
 
692
- @polars_function_wrapper('read_avro', return_type="FlowFrame")
693
- def read_avro(*args, flow_graph: Optional[FlowGraph] = None, **kwargs) -> FlowFrame:
734
+ @polars_function_wrapper("read_avro", return_type="FlowFrame")
735
+ def read_avro(*args, flow_graph: FlowGraph | None = None, **kwargs) -> FlowFrame:
694
736
  pass
695
737
 
696
738
 
697
- @polars_function_wrapper('read_ndjson', return_type="FlowFrame")
698
- def read_ndjson(*args, flow_graph: Optional[FlowGraph] = None, **kwargs) -> FlowFrame:
739
+ @polars_function_wrapper("read_ndjson", return_type="FlowFrame")
740
+ def read_ndjson(*args, flow_graph: FlowGraph | None = None, **kwargs) -> FlowFrame:
699
741
  pass
700
742
 
701
743
 
702
- @polars_function_wrapper('fold', return_type="Expr")
703
- def fold(*args, **kwargs) -> 'Expr': # Type hint 'Expr' refers to flowfile_frame.expr.Expr
704
- pass
744
+ @polars_function_wrapper("fold", return_type="Expr")
745
+ def fold(*args, **kwargs) -> "Expr": # Type hint 'Expr' refers to flowfile_frame.expr.Expr
746
+ pass