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,15 +1,14 @@
1
- from flowfile_worker import status_dict
2
- from time import sleep
3
1
  import gc
4
- from typing import List, Tuple
5
2
  from multiprocessing import Process, Queue
3
+ from time import sleep
4
+
5
+ from flowfile_worker import funcs, models, mp_context, status_dict, status_dict_lock
6
6
  from flowfile_worker.process_manager import ProcessManager
7
- from flowfile_worker import models, mp_context, funcs, status_dict_lock
8
7
 
9
8
  # Initialize ProcessManager
10
9
  process_manager = ProcessManager()
11
10
 
12
- flowfile_node_id_type = int|str
11
+ flowfile_node_id_type = int | str
13
12
 
14
13
 
15
14
  def handle_task(task_id: str, p: Process, progress: mp_context.Value, error_message: mp_context.Array, q: Queue):
@@ -48,7 +47,7 @@ def handle_task(task_id: str, p: Process, progress: mp_context.Value, error_mess
48
47
  with status_dict_lock:
49
48
  status_dict[task_id].status = "Error"
50
49
  with error_message.get_lock():
51
- status_dict[task_id].error_message = error_message.value.decode().rstrip('\x00')
50
+ status_dict[task_id].error_message = error_message.value.decode().rstrip("\x00")
52
51
  break
53
52
 
54
53
  p.join()
@@ -72,11 +71,15 @@ def handle_task(task_id: str, p: Process, progress: mp_context.Value, error_mess
72
71
  gc.collect()
73
72
 
74
73
 
75
- def start_process(polars_serializable_object: bytes, task_id: str,
76
- operation: models.OperationType,
77
- file_ref: str, flowfile_flow_id: int,
78
- flowfile_node_id: flowfile_node_id_type,
79
- kwargs: dict = None) -> None:
74
+ def start_process(
75
+ polars_serializable_object: bytes,
76
+ task_id: str,
77
+ operation: models.OperationType,
78
+ file_ref: str,
79
+ flowfile_flow_id: int,
80
+ flowfile_node_id: flowfile_node_id_type,
81
+ kwargs: dict = None,
82
+ ) -> None:
80
83
  """
81
84
  Starts a new process for handling Polars dataframe operations.
82
85
 
@@ -97,24 +100,31 @@ def start_process(polars_serializable_object: bytes, task_id: str,
97
100
  if kwargs is None:
98
101
  kwargs = {}
99
102
  process_task = getattr(funcs, operation)
100
- kwargs['polars_serializable_object'] = polars_serializable_object
101
- kwargs['progress'] = mp_context.Value('i', 0)
102
- kwargs['error_message'] = mp_context.Array('c', 1024)
103
- kwargs['queue'] = Queue(maxsize=1)
104
- kwargs['file_path'] = file_ref
105
- kwargs['flowfile_flow_id'] = flowfile_flow_id
106
- kwargs['flowfile_node_id'] = flowfile_node_id
103
+ kwargs["polars_serializable_object"] = polars_serializable_object
104
+ kwargs["progress"] = mp_context.Value("i", 0)
105
+ kwargs["error_message"] = mp_context.Array("c", 1024)
106
+ kwargs["queue"] = Queue(maxsize=1)
107
+ kwargs["file_path"] = file_ref
108
+ kwargs["flowfile_flow_id"] = flowfile_flow_id
109
+ kwargs["flowfile_node_id"] = flowfile_node_id
107
110
 
108
111
  p: Process = mp_context.Process(target=process_task, kwargs=kwargs)
109
112
  p.start()
110
113
 
111
114
  process_manager.add_process(task_id, p)
112
- handle_task(task_id=task_id, p=p, progress=kwargs['progress'], error_message=kwargs['error_message'], q=kwargs['queue'])
113
-
114
-
115
- def start_generic_process(func_ref: callable, task_id: str,
116
- file_ref: str, flowfile_flow_id: int,
117
- flowfile_node_id: flowfile_node_id_type, kwargs: dict = None) -> None:
115
+ handle_task(
116
+ task_id=task_id, p=p, progress=kwargs["progress"], error_message=kwargs["error_message"], q=kwargs["queue"]
117
+ )
118
+
119
+
120
+ def start_generic_process(
121
+ func_ref: callable,
122
+ task_id: str,
123
+ file_ref: str,
124
+ flowfile_flow_id: int,
125
+ flowfile_node_id: flowfile_node_id_type,
126
+ kwargs: dict = None,
127
+ ) -> None:
118
128
  """
119
129
  Starts a new process for handling generic function execution.
120
130
 
@@ -132,30 +142,33 @@ def start_generic_process(func_ref: callable, task_id: str,
132
142
  - Delegates to handle_task for process monitoring
133
143
  """
134
144
  kwargs = {} if kwargs is None else kwargs
135
- kwargs['func'] = func_ref
136
- kwargs['progress'] = mp_context.Value('i', 0)
137
- kwargs['error_message'] = mp_context.Array('c', 1024)
138
- kwargs['queue'] = Queue(maxsize=1)
139
- kwargs['file_path'] = file_ref
140
- kwargs['flowfile_flow_id'] = flowfile_flow_id
141
- kwargs['flowfile_node_id'] = flowfile_node_id
142
-
143
- process_task = getattr(funcs, 'generic_task')
145
+ kwargs["func"] = func_ref
146
+ kwargs["progress"] = mp_context.Value("i", 0)
147
+ kwargs["error_message"] = mp_context.Array("c", 1024)
148
+ kwargs["queue"] = Queue(maxsize=1)
149
+ kwargs["file_path"] = file_ref
150
+ kwargs["flowfile_flow_id"] = flowfile_flow_id
151
+ kwargs["flowfile_node_id"] = flowfile_node_id
152
+
153
+ process_task = funcs.generic_task
144
154
  p: Process = mp_context.Process(target=process_task, kwargs=kwargs)
145
155
  p.start()
146
156
 
147
157
  process_manager.add_process(task_id, p) # Add process to process manager
148
- handle_task(task_id=task_id, p=p, progress=kwargs['progress'],
149
- error_message=kwargs['error_message'], q=kwargs['queue'])
150
-
151
-
152
- def start_fuzzy_process(left_serializable_object: bytes,
153
- right_serializable_object: bytes,
154
- file_ref: str,
155
- fuzzy_maps: List[models.FuzzyMapping],
156
- task_id: str,
157
- flowfile_flow_id: int,
158
- flowfile_node_id: flowfile_node_id_type) -> None:
158
+ handle_task(
159
+ task_id=task_id, p=p, progress=kwargs["progress"], error_message=kwargs["error_message"], q=kwargs["queue"]
160
+ )
161
+
162
+
163
+ def start_fuzzy_process(
164
+ left_serializable_object: bytes,
165
+ right_serializable_object: bytes,
166
+ file_ref: str,
167
+ fuzzy_maps: list[models.FuzzyMapping],
168
+ task_id: str,
169
+ flowfile_flow_id: int,
170
+ flowfile_node_id: flowfile_node_id_type,
171
+ ) -> None:
159
172
  """
160
173
  Starts a new process for performing fuzzy joining operations on two datasets.
161
174
 
@@ -172,13 +185,31 @@ def start_fuzzy_process(left_serializable_object: bytes,
172
185
  - Initializes and starts a new process for fuzzy joining operation
173
186
  - Delegates to handle_task for process monitoring
174
187
  """
175
- progress = mp_context.Value('i', 0)
176
- error_message = mp_context.Array('c', 1024)
188
+ progress = mp_context.Value("i", 0)
189
+ error_message = mp_context.Array("c", 1024)
177
190
  q = Queue(maxsize=1)
178
191
 
179
- args: Tuple[bytes, bytes, List[models.FuzzyMapping], mp_context.Array, str, mp_context.Value, Queue, int, flowfile_node_id_type] = \
180
- (left_serializable_object, right_serializable_object, fuzzy_maps, error_message, file_ref, progress, q,
181
- flowfile_flow_id, flowfile_node_id)
192
+ args: tuple[
193
+ bytes,
194
+ bytes,
195
+ list[models.FuzzyMapping],
196
+ mp_context.Array,
197
+ str,
198
+ mp_context.Value,
199
+ Queue,
200
+ int,
201
+ flowfile_node_id_type,
202
+ ] = (
203
+ left_serializable_object,
204
+ right_serializable_object,
205
+ fuzzy_maps,
206
+ error_message,
207
+ file_ref,
208
+ progress,
209
+ q,
210
+ flowfile_flow_id,
211
+ flowfile_node_id,
212
+ )
182
213
 
183
214
  p: Process = mp_context.Process(target=funcs.fuzzy_join_task, args=args)
184
215
  p.start()
flowfile_worker/utils.py CHANGED
@@ -1,6 +1,7 @@
1
+ from dataclasses import dataclass
2
+
1
3
  import polars as pl
2
4
  from polars.exceptions import PanicException
3
- from dataclasses import dataclass
4
5
 
5
6
 
6
7
  def collect_lazy_frame(lf: pl.LazyFrame) -> pl.DataFrame:
@@ -12,7 +13,7 @@ def collect_lazy_frame(lf: pl.LazyFrame) -> pl.DataFrame:
12
13
 
13
14
  @dataclass
14
15
  class CollectStreamingInfo:
15
- __slots__ = 'df', 'streaming_collect_available'
16
+ __slots__ = "df", "streaming_collect_available"
16
17
  df: pl.DataFrame
17
18
  streaming_collect_available: bool
18
19
 
shared/__init__.py CHANGED
@@ -5,11 +5,6 @@ flowfile_core, flowfile_worker, and other components without creating
5
5
  circular dependencies.
6
6
  """
7
7
 
8
- from .storage_config import storage, get_cache_directory, get_temp_directory, get_flows_directory
8
+ from .storage_config import get_cache_directory, get_flows_directory, get_temp_directory, storage
9
9
 
10
- __all__ = [
11
- 'storage',
12
- 'get_cache_directory',
13
- 'get_temp_directory',
14
- 'get_flows_directory'
15
- ]
10
+ __all__ = ["storage", "get_cache_directory", "get_temp_directory", "get_flows_directory"]
shared/storage_config.py CHANGED
@@ -3,28 +3,40 @@
3
3
  Centralized storage configuration for Flowfile.
4
4
  This module can be imported by both core and worker without creating dependencies.
5
5
  """
6
+
6
7
  import os
7
8
  from pathlib import Path
8
- from typing import Optional, Literal
9
+ from typing import Literal
10
+
11
+ DirectoryOptions = Literal[
12
+ "temp_directory",
13
+ "logs_directory",
14
+ "system_logs_directory",
15
+ "database_directory",
16
+ "cache_directory",
17
+ "flows_directory",
18
+ "user_defined_nodes_directory",
19
+ ]
20
+
9
21
 
10
- DirectoryOptions = Literal["temp_directory", "logs_directory",
11
- "system_logs_directory", "database_directory",
12
- "cache_directory", "flows_directory", "user_defined_nodes_directory"]
22
+ def _is_docker_mode() -> bool:
23
+ """Check if running in Docker mode based on FLOWFILE_MODE."""
24
+ return os.environ.get("FLOWFILE_MODE") == "docker"
13
25
 
14
26
 
15
27
  class FlowfileStorage:
16
28
  """Centralized storage manager for Flowfile applications."""
17
29
 
18
30
  def __init__(self):
19
- self._base_dir: Optional[Path] = None
20
- self._user_data_dir: Optional[Path] = None
31
+ self._base_dir: Path | None = None
32
+ self._user_data_dir: Path | None = None
21
33
  self._ensure_directories()
22
34
 
23
35
  @property
24
36
  def base_directory(self) -> Path:
25
37
  """Get the base Flowfile storage directory (for internal container communication)."""
26
38
  if self._base_dir is None:
27
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
39
+ if _is_docker_mode():
28
40
  # In Docker, internal storage stays inside /app
29
41
  base_path = os.environ.get("FLOWFILE_STORAGE_DIR", "/app/internal_storage")
30
42
  else:
@@ -41,7 +53,7 @@ class FlowfileStorage:
41
53
  def user_data_directory(self) -> Path:
42
54
  """Get the user data directory (completely separate from application code)."""
43
55
  if self._user_data_dir is None:
44
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
56
+ if _is_docker_mode():
45
57
  # In Docker, user data is at /data/user (completely outside /app)
46
58
  user_data_path = os.environ.get("FLOWFILE_USER_DATA_DIR", "/data/user")
47
59
  else:
@@ -70,7 +82,7 @@ class FlowfileStorage:
70
82
  @property
71
83
  def flows_directory(self) -> Path:
72
84
  """Directory for flow storage (user-accessible)."""
73
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
85
+ if _is_docker_mode():
74
86
  # In Docker, flows are in separate user data area
75
87
  return self.user_data_directory / "flows"
76
88
  else:
@@ -80,7 +92,7 @@ class FlowfileStorage:
80
92
  @property
81
93
  def uploads_directory(self) -> Path:
82
94
  """Directory for user uploads (user-accessible)."""
83
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
95
+ if _is_docker_mode():
84
96
  # In Docker, uploads are in separate user data area
85
97
  return self.user_data_directory / "uploads"
86
98
  else:
@@ -90,7 +102,7 @@ class FlowfileStorage:
90
102
  @property
91
103
  def user_defined_nodes_directory(self) -> Path:
92
104
  """Directory for user-defined custom nodes (user-accessible)."""
93
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
105
+ if _is_docker_mode():
94
106
  return self.user_data_directory / "user_defined_nodes"
95
107
  else:
96
108
  return self.base_directory / "user_defined_nodes"
@@ -103,7 +115,7 @@ class FlowfileStorage:
103
115
  @property
104
116
  def outputs_directory(self) -> Path:
105
117
  """Directory for user outputs (user-accessible)."""
106
- if os.environ.get("RUNNING_IN_DOCKER") == "true":
118
+ if _is_docker_mode():
107
119
  # In Docker, outputs are in separate user data area
108
120
  return self.user_data_directory / "outputs"
109
121
  else:
@@ -184,8 +196,8 @@ class FlowfileStorage:
184
196
 
185
197
  def cleanup_directory(self, directory_option: DirectoryOptions, storage_duration_hours: int = 24) -> None:
186
198
  """Clean up any directory of the folder"""
187
- import time
188
199
  import shutil
200
+ import time
189
201
 
190
202
  if not hasattr(self, directory_option):
191
203
  raise Exception(f"Directory does not exist in {self.base_directory}")
@@ -6,8 +6,9 @@ to start and stop PostgreSQL containers with sample data.
6
6
  """
7
7
 
8
8
  import argparse
9
- import sys
10
9
  import logging
10
+ import sys
11
+
11
12
  from . import fixtures
12
13
 
13
14
  # Set up logging
@@ -106,4 +107,4 @@ if __name__ == "__main__":
106
107
  sys.exit(stop_postgres())
107
108
  else:
108
109
  print("Usage: python -m test_utils.postgres.commands [start|stop] [options]")
109
- sys.exit(1)
110
+ sys.exit(1)
@@ -5,13 +5,13 @@ This module provides utilities to set up, manage, and tear down PostgreSQL
5
5
  containers with sample data for testing.
6
6
  """
7
7
 
8
- import os
9
- import time
10
8
  import logging
11
- import subprocess
9
+ import os
12
10
  import shutil
11
+ import subprocess
12
+ import time
13
+ from collections.abc import Generator
13
14
  from contextlib import contextmanager
14
- from typing import Dict, Generator, Optional, Tuple
15
15
 
16
16
  # Configure logging
17
17
  logging.basicConfig(
@@ -208,7 +208,7 @@ def start_postgres_container(
208
208
  container_name: str = POSTGRES_CONTAINER_NAME,
209
209
  port: int = POSTGRES_PORT,
210
210
  image_tag: str = POSTGRES_IMAGE_TAG
211
- ) -> Tuple[Optional[subprocess.Popen], bool]:
211
+ ) -> tuple[subprocess.Popen | None, bool]:
212
212
  """
213
213
  Start the PostgreSQL container with sample data.
214
214
 
@@ -225,7 +225,7 @@ def start_postgres_container(
225
225
  logger.warning("Docker not available, skipping PostgreSQL container start")
226
226
  return None, False
227
227
 
228
- logger.info(f"Starting PostgreSQL container with sample data...")
228
+ logger.info("Starting PostgreSQL container with sample data...")
229
229
 
230
230
  # Check if container is already running
231
231
  if is_container_running(container_name):
@@ -345,12 +345,12 @@ def print_connection_info(
345
345
  print(f"Connection string: postgresql://{user}:{password}@{host}:{port}/{db}")
346
346
  print("=" * 50)
347
347
  print("\nTo stop the container, run:")
348
- print(f"poetry run stop_postgres")
348
+ print("poetry run stop_postgres")
349
349
  print("=" * 50 + "\n")
350
350
 
351
351
 
352
352
  @contextmanager
353
- def managed_postgres() -> Generator[Dict[str, any], None, None]:
353
+ def managed_postgres() -> Generator[dict[str, any], None, None]:
354
354
  """
355
355
  Context manager for PostgreSQL container management.
356
356
  Ensures proper cleanup even when tests fail.
@@ -414,4 +414,4 @@ def get_db_engine():
414
414
  return engine
415
415
  except ImportError:
416
416
  logger.error("SQLAlchemy not installed. Run: pip install sqlalchemy")
417
- raise
417
+ raise
test_utils/s3/commands.py CHANGED
@@ -43,4 +43,4 @@ def stop_minio():
43
43
  if fixtures.stop_minio_container():
44
44
  print("MinIO stopped successfully")
45
45
  return 0
46
- return 1
46
+ return 1
@@ -1,17 +1,16 @@
1
1
 
2
- import logging
3
2
  import io
3
+ import logging
4
4
  import os
5
5
 
6
6
  # Third-party libraries
7
7
  import boto3
8
- from botocore.client import Config
9
8
  import polars as pl
10
9
  import pyarrow as pa
10
+ from botocore.client import Config
11
11
  from deltalake import write_deltalake
12
12
  from pyiceberg.catalog import load_catalog
13
13
 
14
-
15
14
  # Configure logging
16
15
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
17
16
  logger = logging.getLogger(__name__)
@@ -289,4 +288,4 @@ if __name__ == '__main__':
289
288
  populate_test_data(endpoint_url=MINIO_ENDPOINT_URL,
290
289
  access_key=MINIO_ACCESS_KEY,
291
290
  secret_key=MINIO_SECRET_KEY,
292
- bucket_name="test-bucket")
291
+ bucket_name="test-bucket")
@@ -1,17 +1,14 @@
1
- import logging
2
1
  import io
2
+ import logging
3
3
  import os
4
- import tempfile
5
- import shutil
6
4
  import random
5
+ import tempfile
7
6
  from datetime import datetime, timedelta
8
7
 
9
8
  # Third-party libraries
10
9
  import boto3
11
- from botocore.client import Config
12
10
  import polars as pl
13
- import pyarrow as pa
14
- from pyarrow import parquet as pq
11
+ from botocore.client import Config
15
12
 
16
13
  # Configure logging
17
14
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
@@ -152,7 +149,7 @@ def create_demo_data(endpoint_url: str, access_key: str, secret_key: str, bucket
152
149
  unique_product_ids = sales_df["product_id"].unique().to_list()
153
150
  # Create a map of product_id to unit_price from the first occurrence in sales_df
154
151
  product_price_map = sales_df.group_by("product_id").agg(pl.first("unit_price")).to_dict(as_series=False)
155
- price_dict = dict(zip(product_price_map['product_id'], product_price_map['unit_price']))
152
+ price_dict = dict(zip(product_price_map['product_id'], product_price_map['unit_price'], strict=False))
156
153
 
157
154
  products_df = pl.DataFrame({
158
155
  "product_id": unique_product_ids,
test_utils/s3/fixtures.py CHANGED
@@ -1,12 +1,14 @@
1
+ import logging
1
2
  import os
2
- import time
3
+ import shutil
3
4
  import subprocess
4
- import logging
5
+ import time
6
+ from collections.abc import Generator
5
7
  from contextlib import contextmanager
6
- from typing import Dict, Generator
7
- import shutil
8
+
8
9
  import boto3
9
10
  from botocore.client import Config
11
+
10
12
  from test_utils.s3.data_generator import populate_test_data
11
13
  from test_utils.s3.demo_data_generator import create_demo_data
12
14
 
@@ -191,7 +193,7 @@ def start_minio_container() -> bool:
191
193
 
192
194
 
193
195
  @contextmanager
194
- def managed_minio() -> Generator[Dict[str, any], None, None]:
196
+ def managed_minio() -> Generator[dict[str, any], None, None]:
195
197
  """Context manager for MinIO container with full connection info"""
196
198
  if not start_minio_container():
197
199
  yield {}
tools/migrate/__init__.py CHANGED
@@ -9,4 +9,4 @@ Usage:
9
9
  python -m tools.migrate ./flows/ # migrate entire directory
10
10
  """
11
11
 
12
- __version__ = "1.0.0"
12
+ __version__ = "1.0.0"
tools/migrate/__main__.py CHANGED
@@ -28,13 +28,13 @@ import argparse
28
28
  import sys
29
29
  from pathlib import Path
30
30
 
31
- from tools.migrate.migrate import migrate_flowfile, migrate_directory
31
+ from tools.migrate.migrate import migrate_directory, migrate_flowfile
32
32
 
33
33
 
34
34
  def main():
35
35
  parser = argparse.ArgumentParser(
36
- prog='flowfile-migrate',
37
- description='Migrate old .flowfile pickles to YAML format',
36
+ prog="flowfile-migrate",
37
+ description="Migrate old .flowfile pickles to YAML format",
38
38
  formatter_class=argparse.RawDescriptionHelpFormatter,
39
39
  epilog="""
40
40
  Examples:
@@ -42,40 +42,26 @@ Examples:
42
42
  %(prog)s ./flows/ Migrate all files in directory
43
43
  %(prog)s flow.flowfile -o flow.yaml Specify output path
44
44
  %(prog)s ./flows/ --format json Output as JSON instead of YAML
45
- """
45
+ """,
46
46
  )
47
47
 
48
- parser.add_argument(
49
- 'path',
50
- type=Path,
51
- help='Path to .flowfile or directory containing .flowfile files'
52
- )
48
+ parser.add_argument("path", type=Path, help="Path to .flowfile or directory containing .flowfile files")
53
49
 
54
50
  parser.add_argument(
55
- '-o', '--output',
51
+ "-o",
52
+ "--output",
56
53
  type=Path,
57
54
  default=None,
58
- help='Output path (file or directory). Default: same location with new extension'
55
+ help="Output path (file or directory). Default: same location with new extension",
59
56
  )
60
57
 
61
58
  parser.add_argument(
62
- '-f', '--format',
63
- choices=['yaml', 'json'],
64
- default='yaml',
65
- help='Output format (default: yaml)'
59
+ "-f", "--format", choices=["yaml", "json"], default="yaml", help="Output format (default: yaml)"
66
60
  )
67
61
 
68
- parser.add_argument(
69
- '-v', '--verbose',
70
- action='store_true',
71
- help='Verbose output'
72
- )
62
+ parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
73
63
 
74
- parser.add_argument(
75
- '--dry-run',
76
- action='store_true',
77
- help='Show what would be migrated without actually migrating'
78
- )
64
+ parser.add_argument("--dry-run", action="store_true", help="Show what would be migrated without actually migrating")
79
65
 
80
66
  args = parser.parse_args()
81
67
 
@@ -88,18 +74,18 @@ Examples:
88
74
  if args.dry_run:
89
75
  if args.path.is_file():
90
76
  print(f"Would migrate: {args.path}")
91
- suffix = '.yaml' if args.format == 'yaml' else '.json'
77
+ suffix = ".yaml" if args.format == "yaml" else ".json"
92
78
  output = args.output or args.path.with_suffix(suffix)
93
79
  print(f" → {output}")
94
80
  else:
95
- flowfiles = list(args.path.glob('**/*.flowfile'))
81
+ flowfiles = list(args.path.glob("**/*.flowfile"))
96
82
  print(f"Would migrate {len(flowfiles)} file(s):")
97
83
  for f in flowfiles:
98
84
  print(f" - {f}")
99
85
  sys.exit(0)
100
86
 
101
87
  # Check for yaml dependency
102
- if args.format == 'yaml':
88
+ if args.format == "yaml":
103
89
  try:
104
90
  import yaml
105
91
  except ImportError:
@@ -121,11 +107,12 @@ Examples:
121
107
  print(f"Error: {e}", file=sys.stderr)
122
108
  if args.verbose:
123
109
  import traceback
110
+
124
111
  traceback.print_exc()
125
112
  sys.exit(1)
126
113
 
127
114
  print("\nMigration complete!")
128
115
 
129
116
 
130
- if __name__ == '__main__':
117
+ if __name__ == "__main__":
131
118
  main()