flowtask 5.8.4__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.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 (470) hide show
  1. flowtask/__init__.py +93 -0
  2. flowtask/__main__.py +38 -0
  3. flowtask/bots/__init__.py +6 -0
  4. flowtask/bots/check.py +93 -0
  5. flowtask/bots/codebot.py +51 -0
  6. flowtask/components/ASPX.py +148 -0
  7. flowtask/components/AddDataset.py +352 -0
  8. flowtask/components/Amazon.py +523 -0
  9. flowtask/components/AutoTask.py +314 -0
  10. flowtask/components/Azure.py +80 -0
  11. flowtask/components/AzureUsers.py +106 -0
  12. flowtask/components/BaseAction.py +91 -0
  13. flowtask/components/BaseLoop.py +198 -0
  14. flowtask/components/BestBuy.py +800 -0
  15. flowtask/components/CSVToGCS.py +120 -0
  16. flowtask/components/CompanyScraper/__init__.py +1 -0
  17. flowtask/components/CompanyScraper/parsers/__init__.py +6 -0
  18. flowtask/components/CompanyScraper/parsers/base.py +102 -0
  19. flowtask/components/CompanyScraper/parsers/explorium.py +192 -0
  20. flowtask/components/CompanyScraper/parsers/leadiq.py +206 -0
  21. flowtask/components/CompanyScraper/parsers/rocket.py +133 -0
  22. flowtask/components/CompanyScraper/parsers/siccode.py +109 -0
  23. flowtask/components/CompanyScraper/parsers/visualvisitor.py +130 -0
  24. flowtask/components/CompanyScraper/parsers/zoominfo.py +118 -0
  25. flowtask/components/CompanyScraper/scrapper.py +1054 -0
  26. flowtask/components/CopyTo.py +177 -0
  27. flowtask/components/CopyToBigQuery.py +243 -0
  28. flowtask/components/CopyToMongoDB.py +291 -0
  29. flowtask/components/CopyToPg.py +609 -0
  30. flowtask/components/CopyToRethink.py +207 -0
  31. flowtask/components/CreateGCSBucket.py +102 -0
  32. flowtask/components/CreateReport/CreateReport.py +228 -0
  33. flowtask/components/CreateReport/__init__.py +9 -0
  34. flowtask/components/CreateReport/charts/__init__.py +15 -0
  35. flowtask/components/CreateReport/charts/bar.py +51 -0
  36. flowtask/components/CreateReport/charts/base.py +66 -0
  37. flowtask/components/CreateReport/charts/pie.py +64 -0
  38. flowtask/components/CreateReport/utils.py +9 -0
  39. flowtask/components/CustomerSatisfaction.py +196 -0
  40. flowtask/components/DataInput.py +200 -0
  41. flowtask/components/DateList.py +255 -0
  42. flowtask/components/DbClient.py +163 -0
  43. flowtask/components/DialPad.py +146 -0
  44. flowtask/components/DocumentDBQuery.py +200 -0
  45. flowtask/components/DownloadFrom.py +371 -0
  46. flowtask/components/DownloadFromD2L.py +113 -0
  47. flowtask/components/DownloadFromFTP.py +181 -0
  48. flowtask/components/DownloadFromIMAP.py +315 -0
  49. flowtask/components/DownloadFromS3.py +198 -0
  50. flowtask/components/DownloadFromSFTP.py +265 -0
  51. flowtask/components/DownloadFromSharepoint.py +110 -0
  52. flowtask/components/DownloadFromSmartSheet.py +114 -0
  53. flowtask/components/DownloadS3File.py +229 -0
  54. flowtask/components/Dummy.py +59 -0
  55. flowtask/components/DuplicatePhoto.py +411 -0
  56. flowtask/components/EmployeeEvaluation.py +237 -0
  57. flowtask/components/ExecuteSQL.py +323 -0
  58. flowtask/components/ExtractHTML.py +178 -0
  59. flowtask/components/FileBase.py +178 -0
  60. flowtask/components/FileCopy.py +181 -0
  61. flowtask/components/FileDelete.py +82 -0
  62. flowtask/components/FileExists.py +146 -0
  63. flowtask/components/FileIteratorDelete.py +112 -0
  64. flowtask/components/FileList.py +194 -0
  65. flowtask/components/FileOpen.py +75 -0
  66. flowtask/components/FileRead.py +120 -0
  67. flowtask/components/FileRename.py +106 -0
  68. flowtask/components/FilterIf.py +284 -0
  69. flowtask/components/FilterRows/FilterRows.py +200 -0
  70. flowtask/components/FilterRows/__init__.py +10 -0
  71. flowtask/components/FilterRows/functions.py +4 -0
  72. flowtask/components/GCSToBigQuery.py +103 -0
  73. flowtask/components/GoogleA4.py +150 -0
  74. flowtask/components/GoogleGeoCoding.py +344 -0
  75. flowtask/components/GooglePlaces.py +315 -0
  76. flowtask/components/GoogleSearch.py +539 -0
  77. flowtask/components/HTTPClient.py +268 -0
  78. flowtask/components/ICIMS.py +146 -0
  79. flowtask/components/IF.py +179 -0
  80. flowtask/components/IcimsFolderCopy.py +173 -0
  81. flowtask/components/ImageFeatures/__init__.py +5 -0
  82. flowtask/components/ImageFeatures/process.py +233 -0
  83. flowtask/components/IteratorBase.py +251 -0
  84. flowtask/components/LangchainLoader/__init__.py +5 -0
  85. flowtask/components/LangchainLoader/loader.py +194 -0
  86. flowtask/components/LangchainLoader/loaders/__init__.py +22 -0
  87. flowtask/components/LangchainLoader/loaders/abstract.py +362 -0
  88. flowtask/components/LangchainLoader/loaders/basepdf.py +50 -0
  89. flowtask/components/LangchainLoader/loaders/docx.py +91 -0
  90. flowtask/components/LangchainLoader/loaders/html.py +119 -0
  91. flowtask/components/LangchainLoader/loaders/pdfblocks.py +146 -0
  92. flowtask/components/LangchainLoader/loaders/pdfmark.py +79 -0
  93. flowtask/components/LangchainLoader/loaders/pdftables.py +135 -0
  94. flowtask/components/LangchainLoader/loaders/qa.py +67 -0
  95. flowtask/components/LangchainLoader/loaders/txt.py +55 -0
  96. flowtask/components/LeadIQ.py +650 -0
  97. flowtask/components/Loop.py +253 -0
  98. flowtask/components/Lowes.py +334 -0
  99. flowtask/components/MS365Usage.py +156 -0
  100. flowtask/components/MSTeamsMessages.py +320 -0
  101. flowtask/components/MarketClustering.py +1051 -0
  102. flowtask/components/MergeFiles.py +362 -0
  103. flowtask/components/MilvusOutput.py +87 -0
  104. flowtask/components/NearByStores.py +175 -0
  105. flowtask/components/NetworkNinja/__init__.py +6 -0
  106. flowtask/components/NetworkNinja/models/__init__.py +52 -0
  107. flowtask/components/NetworkNinja/models/abstract.py +177 -0
  108. flowtask/components/NetworkNinja/models/account.py +39 -0
  109. flowtask/components/NetworkNinja/models/client.py +19 -0
  110. flowtask/components/NetworkNinja/models/district.py +14 -0
  111. flowtask/components/NetworkNinja/models/events.py +101 -0
  112. flowtask/components/NetworkNinja/models/forms.py +499 -0
  113. flowtask/components/NetworkNinja/models/market.py +16 -0
  114. flowtask/components/NetworkNinja/models/organization.py +34 -0
  115. flowtask/components/NetworkNinja/models/photos.py +125 -0
  116. flowtask/components/NetworkNinja/models/project.py +44 -0
  117. flowtask/components/NetworkNinja/models/region.py +28 -0
  118. flowtask/components/NetworkNinja/models/store.py +203 -0
  119. flowtask/components/NetworkNinja/models/user.py +151 -0
  120. flowtask/components/NetworkNinja/router.py +854 -0
  121. flowtask/components/Odoo.py +175 -0
  122. flowtask/components/OdooInjector.py +192 -0
  123. flowtask/components/OpenFromXML.py +126 -0
  124. flowtask/components/OpenWeather.py +41 -0
  125. flowtask/components/OpenWithBase.py +616 -0
  126. flowtask/components/OpenWithPandas.py +715 -0
  127. flowtask/components/PGPDecrypt.py +199 -0
  128. flowtask/components/PandasIterator.py +187 -0
  129. flowtask/components/PandasToFile.py +189 -0
  130. flowtask/components/Paradox.py +339 -0
  131. flowtask/components/ParamIterator.py +117 -0
  132. flowtask/components/ParseHTML.py +84 -0
  133. flowtask/components/PlacerStores.py +249 -0
  134. flowtask/components/Pokemon.py +507 -0
  135. flowtask/components/PositiveBot.py +62 -0
  136. flowtask/components/PowerPointSlide.py +400 -0
  137. flowtask/components/PrintMessage.py +127 -0
  138. flowtask/components/ProductCompetitors/__init__.py +5 -0
  139. flowtask/components/ProductCompetitors/parsers/__init__.py +7 -0
  140. flowtask/components/ProductCompetitors/parsers/base.py +72 -0
  141. flowtask/components/ProductCompetitors/parsers/bestbuy.py +86 -0
  142. flowtask/components/ProductCompetitors/parsers/lowes.py +103 -0
  143. flowtask/components/ProductCompetitors/scrapper.py +155 -0
  144. flowtask/components/ProductCompliant.py +169 -0
  145. flowtask/components/ProductInfo/__init__.py +1 -0
  146. flowtask/components/ProductInfo/parsers/__init__.py +5 -0
  147. flowtask/components/ProductInfo/parsers/base.py +83 -0
  148. flowtask/components/ProductInfo/parsers/brother.py +97 -0
  149. flowtask/components/ProductInfo/parsers/canon.py +167 -0
  150. flowtask/components/ProductInfo/parsers/epson.py +118 -0
  151. flowtask/components/ProductInfo/parsers/hp.py +131 -0
  152. flowtask/components/ProductInfo/parsers/samsung.py +97 -0
  153. flowtask/components/ProductInfo/scraper.py +319 -0
  154. flowtask/components/ProductPricing.py +118 -0
  155. flowtask/components/QS.py +261 -0
  156. flowtask/components/QSBase.py +201 -0
  157. flowtask/components/QueryIterator.py +273 -0
  158. flowtask/components/QueryToInsert.py +327 -0
  159. flowtask/components/QueryToPandas.py +432 -0
  160. flowtask/components/RESTClient.py +195 -0
  161. flowtask/components/RethinkDBQuery.py +189 -0
  162. flowtask/components/Rsync.py +74 -0
  163. flowtask/components/RunSSH.py +59 -0
  164. flowtask/components/RunShell.py +71 -0
  165. flowtask/components/SalesForce.py +20 -0
  166. flowtask/components/SaveImageBank/__init__.py +257 -0
  167. flowtask/components/SchedulingVisits.py +592 -0
  168. flowtask/components/ScrapPage.py +216 -0
  169. flowtask/components/ScrapSearch.py +79 -0
  170. flowtask/components/SendNotify.py +257 -0
  171. flowtask/components/SentimentAnalysis.py +694 -0
  172. flowtask/components/ServiceScrapper/__init__.py +5 -0
  173. flowtask/components/ServiceScrapper/parsers/__init__.py +1 -0
  174. flowtask/components/ServiceScrapper/parsers/base.py +94 -0
  175. flowtask/components/ServiceScrapper/parsers/costco.py +93 -0
  176. flowtask/components/ServiceScrapper/scrapper.py +199 -0
  177. flowtask/components/SetVariables.py +156 -0
  178. flowtask/components/SubTask.py +182 -0
  179. flowtask/components/SuiteCRM.py +48 -0
  180. flowtask/components/Switch.py +175 -0
  181. flowtask/components/TableBase.py +148 -0
  182. flowtask/components/TableDelete.py +312 -0
  183. flowtask/components/TableInput.py +143 -0
  184. flowtask/components/TableOutput/TableOutput.py +384 -0
  185. flowtask/components/TableOutput/__init__.py +3 -0
  186. flowtask/components/TableSchema.py +534 -0
  187. flowtask/components/Target.py +223 -0
  188. flowtask/components/ThumbnailGenerator.py +156 -0
  189. flowtask/components/ToPandas.py +67 -0
  190. flowtask/components/TransformRows/TransformRows.py +507 -0
  191. flowtask/components/TransformRows/__init__.py +9 -0
  192. flowtask/components/TransformRows/functions.py +559 -0
  193. flowtask/components/TransposeRows.py +176 -0
  194. flowtask/components/UPCDatabase.py +86 -0
  195. flowtask/components/UnGzip.py +171 -0
  196. flowtask/components/Uncompress.py +172 -0
  197. flowtask/components/UniqueRows.py +126 -0
  198. flowtask/components/Unzip.py +107 -0
  199. flowtask/components/UpdateOperationalVars.py +147 -0
  200. flowtask/components/UploadTo.py +299 -0
  201. flowtask/components/UploadToS3.py +136 -0
  202. flowtask/components/UploadToSFTP.py +160 -0
  203. flowtask/components/UploadToSharepoint.py +205 -0
  204. flowtask/components/UserFunc.py +122 -0
  205. flowtask/components/VivaTracker.py +140 -0
  206. flowtask/components/WSDLClient.py +123 -0
  207. flowtask/components/Wait.py +18 -0
  208. flowtask/components/Walmart.py +199 -0
  209. flowtask/components/Workplace.py +134 -0
  210. flowtask/components/XMLToPandas.py +267 -0
  211. flowtask/components/Zammad/__init__.py +41 -0
  212. flowtask/components/Zammad/models.py +0 -0
  213. flowtask/components/ZoomInfoScraper.py +409 -0
  214. flowtask/components/__init__.py +104 -0
  215. flowtask/components/abstract.py +18 -0
  216. flowtask/components/flow.py +530 -0
  217. flowtask/components/google.py +335 -0
  218. flowtask/components/group.py +221 -0
  219. flowtask/components/py.typed +0 -0
  220. flowtask/components/reviewscrap.py +132 -0
  221. flowtask/components/tAutoincrement.py +117 -0
  222. flowtask/components/tConcat.py +109 -0
  223. flowtask/components/tExplode.py +119 -0
  224. flowtask/components/tFilter.py +184 -0
  225. flowtask/components/tGroup.py +236 -0
  226. flowtask/components/tJoin.py +270 -0
  227. flowtask/components/tMap/__init__.py +9 -0
  228. flowtask/components/tMap/functions.py +54 -0
  229. flowtask/components/tMap/tMap.py +450 -0
  230. flowtask/components/tMelt.py +112 -0
  231. flowtask/components/tMerge.py +114 -0
  232. flowtask/components/tOrder.py +93 -0
  233. flowtask/components/tPandas.py +94 -0
  234. flowtask/components/tPivot.py +71 -0
  235. flowtask/components/tPluckCols.py +76 -0
  236. flowtask/components/tUnnest.py +82 -0
  237. flowtask/components/user.py +401 -0
  238. flowtask/conf.py +457 -0
  239. flowtask/download.py +102 -0
  240. flowtask/events/__init__.py +11 -0
  241. flowtask/events/events/__init__.py +20 -0
  242. flowtask/events/events/abstract.py +95 -0
  243. flowtask/events/events/alerts/__init__.py +362 -0
  244. flowtask/events/events/alerts/colfunctions.py +131 -0
  245. flowtask/events/events/alerts/functions.py +158 -0
  246. flowtask/events/events/dummy.py +12 -0
  247. flowtask/events/events/exec.py +124 -0
  248. flowtask/events/events/file/__init__.py +7 -0
  249. flowtask/events/events/file/base.py +51 -0
  250. flowtask/events/events/file/copy.py +23 -0
  251. flowtask/events/events/file/delete.py +16 -0
  252. flowtask/events/events/interfaces/__init__.py +9 -0
  253. flowtask/events/events/interfaces/client.py +67 -0
  254. flowtask/events/events/interfaces/credentials.py +28 -0
  255. flowtask/events/events/interfaces/notifications.py +58 -0
  256. flowtask/events/events/jira.py +122 -0
  257. flowtask/events/events/log.py +26 -0
  258. flowtask/events/events/logerr.py +52 -0
  259. flowtask/events/events/notify.py +59 -0
  260. flowtask/events/events/notify_event.py +160 -0
  261. flowtask/events/events/publish.py +54 -0
  262. flowtask/events/events/sendfile.py +104 -0
  263. flowtask/events/events/task.py +97 -0
  264. flowtask/events/events/teams.py +98 -0
  265. flowtask/events/events/webhook.py +58 -0
  266. flowtask/events/manager.py +287 -0
  267. flowtask/exceptions.c +39393 -0
  268. flowtask/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  269. flowtask/extensions/__init__.py +3 -0
  270. flowtask/extensions/abstract.py +82 -0
  271. flowtask/extensions/logging/__init__.py +65 -0
  272. flowtask/hooks/__init__.py +9 -0
  273. flowtask/hooks/actions/__init__.py +22 -0
  274. flowtask/hooks/actions/abstract.py +66 -0
  275. flowtask/hooks/actions/dummy.py +23 -0
  276. flowtask/hooks/actions/jira.py +74 -0
  277. flowtask/hooks/actions/rest.py +320 -0
  278. flowtask/hooks/actions/sampledata.py +37 -0
  279. flowtask/hooks/actions/sensor.py +23 -0
  280. flowtask/hooks/actions/task.py +9 -0
  281. flowtask/hooks/actions/ticket.py +37 -0
  282. flowtask/hooks/actions/zammad.py +55 -0
  283. flowtask/hooks/hook.py +62 -0
  284. flowtask/hooks/models.py +17 -0
  285. flowtask/hooks/service.py +187 -0
  286. flowtask/hooks/step.py +91 -0
  287. flowtask/hooks/types/__init__.py +23 -0
  288. flowtask/hooks/types/base.py +129 -0
  289. flowtask/hooks/types/brokers/__init__.py +11 -0
  290. flowtask/hooks/types/brokers/base.py +54 -0
  291. flowtask/hooks/types/brokers/mqtt.py +35 -0
  292. flowtask/hooks/types/brokers/rabbitmq.py +82 -0
  293. flowtask/hooks/types/brokers/redis.py +83 -0
  294. flowtask/hooks/types/brokers/sqs.py +44 -0
  295. flowtask/hooks/types/fs.py +232 -0
  296. flowtask/hooks/types/http.py +49 -0
  297. flowtask/hooks/types/imap.py +200 -0
  298. flowtask/hooks/types/jira.py +279 -0
  299. flowtask/hooks/types/mail.py +205 -0
  300. flowtask/hooks/types/postgres.py +98 -0
  301. flowtask/hooks/types/responses/__init__.py +8 -0
  302. flowtask/hooks/types/responses/base.py +5 -0
  303. flowtask/hooks/types/sharepoint.py +288 -0
  304. flowtask/hooks/types/ssh.py +141 -0
  305. flowtask/hooks/types/tagged.py +59 -0
  306. flowtask/hooks/types/upload.py +85 -0
  307. flowtask/hooks/types/watch.py +71 -0
  308. flowtask/hooks/types/web.py +36 -0
  309. flowtask/interfaces/AzureClient.py +137 -0
  310. flowtask/interfaces/AzureGraph.py +839 -0
  311. flowtask/interfaces/Boto3Client.py +326 -0
  312. flowtask/interfaces/DropboxClient.py +173 -0
  313. flowtask/interfaces/ExcelHandler.py +94 -0
  314. flowtask/interfaces/FTPClient.py +131 -0
  315. flowtask/interfaces/GoogleCalendar.py +201 -0
  316. flowtask/interfaces/GoogleClient.py +133 -0
  317. flowtask/interfaces/GoogleDrive.py +127 -0
  318. flowtask/interfaces/GoogleGCS.py +89 -0
  319. flowtask/interfaces/GoogleGeocoding.py +93 -0
  320. flowtask/interfaces/GoogleLang.py +114 -0
  321. flowtask/interfaces/GooglePub.py +61 -0
  322. flowtask/interfaces/GoogleSheet.py +68 -0
  323. flowtask/interfaces/IMAPClient.py +137 -0
  324. flowtask/interfaces/O365Calendar.py +113 -0
  325. flowtask/interfaces/O365Client.py +220 -0
  326. flowtask/interfaces/OneDrive.py +284 -0
  327. flowtask/interfaces/Outlook.py +155 -0
  328. flowtask/interfaces/ParrotBot.py +130 -0
  329. flowtask/interfaces/SSHClient.py +378 -0
  330. flowtask/interfaces/Sharepoint.py +496 -0
  331. flowtask/interfaces/__init__.py +36 -0
  332. flowtask/interfaces/azureauth.py +119 -0
  333. flowtask/interfaces/cache.py +201 -0
  334. flowtask/interfaces/client.py +82 -0
  335. flowtask/interfaces/compress.py +525 -0
  336. flowtask/interfaces/credentials.py +124 -0
  337. flowtask/interfaces/d2l.py +239 -0
  338. flowtask/interfaces/databases/__init__.py +5 -0
  339. flowtask/interfaces/databases/db.py +223 -0
  340. flowtask/interfaces/databases/documentdb.py +55 -0
  341. flowtask/interfaces/databases/rethink.py +39 -0
  342. flowtask/interfaces/dataframes/__init__.py +11 -0
  343. flowtask/interfaces/dataframes/abstract.py +21 -0
  344. flowtask/interfaces/dataframes/arrow.py +71 -0
  345. flowtask/interfaces/dataframes/dt.py +69 -0
  346. flowtask/interfaces/dataframes/pandas.py +167 -0
  347. flowtask/interfaces/dataframes/polars.py +60 -0
  348. flowtask/interfaces/db.py +263 -0
  349. flowtask/interfaces/env.py +46 -0
  350. flowtask/interfaces/func.py +137 -0
  351. flowtask/interfaces/http.py +1780 -0
  352. flowtask/interfaces/locale.py +40 -0
  353. flowtask/interfaces/log.py +75 -0
  354. flowtask/interfaces/mask.py +143 -0
  355. flowtask/interfaces/notification.py +154 -0
  356. flowtask/interfaces/playwright.py +339 -0
  357. flowtask/interfaces/powerpoint.py +368 -0
  358. flowtask/interfaces/py.typed +0 -0
  359. flowtask/interfaces/qs.py +376 -0
  360. flowtask/interfaces/result.py +87 -0
  361. flowtask/interfaces/selenium_service.py +779 -0
  362. flowtask/interfaces/smartsheet.py +154 -0
  363. flowtask/interfaces/stat.py +39 -0
  364. flowtask/interfaces/task.py +96 -0
  365. flowtask/interfaces/template.py +118 -0
  366. flowtask/interfaces/vectorstores/__init__.py +1 -0
  367. flowtask/interfaces/vectorstores/abstract.py +133 -0
  368. flowtask/interfaces/vectorstores/milvus.py +669 -0
  369. flowtask/interfaces/zammad.py +107 -0
  370. flowtask/models.py +193 -0
  371. flowtask/parsers/__init__.py +15 -0
  372. flowtask/parsers/_yaml.c +11978 -0
  373. flowtask/parsers/_yaml.cpython-310-x86_64-linux-gnu.so +0 -0
  374. flowtask/parsers/argparser.py +235 -0
  375. flowtask/parsers/base.c +15155 -0
  376. flowtask/parsers/base.cpython-310-x86_64-linux-gnu.so +0 -0
  377. flowtask/parsers/json.c +11968 -0
  378. flowtask/parsers/json.cpython-310-x86_64-linux-gnu.so +0 -0
  379. flowtask/parsers/maps.py +49 -0
  380. flowtask/parsers/toml.c +11968 -0
  381. flowtask/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  382. flowtask/plugins/__init__.py +16 -0
  383. flowtask/plugins/components/__init__.py +0 -0
  384. flowtask/plugins/handler/__init__.py +45 -0
  385. flowtask/plugins/importer.py +31 -0
  386. flowtask/plugins/sources/__init__.py +0 -0
  387. flowtask/runner.py +283 -0
  388. flowtask/scheduler/__init__.py +9 -0
  389. flowtask/scheduler/functions.py +493 -0
  390. flowtask/scheduler/handlers/__init__.py +8 -0
  391. flowtask/scheduler/handlers/manager.py +504 -0
  392. flowtask/scheduler/handlers/models.py +58 -0
  393. flowtask/scheduler/handlers/service.py +72 -0
  394. flowtask/scheduler/notifications.py +65 -0
  395. flowtask/scheduler/scheduler.py +993 -0
  396. flowtask/services/__init__.py +0 -0
  397. flowtask/services/bots/__init__.py +0 -0
  398. flowtask/services/bots/telegram.py +264 -0
  399. flowtask/services/files/__init__.py +11 -0
  400. flowtask/services/files/manager.py +522 -0
  401. flowtask/services/files/model.py +37 -0
  402. flowtask/services/files/service.py +767 -0
  403. flowtask/services/jira/__init__.py +3 -0
  404. flowtask/services/jira/jira_actions.py +191 -0
  405. flowtask/services/tasks/__init__.py +13 -0
  406. flowtask/services/tasks/launcher.py +213 -0
  407. flowtask/services/tasks/manager.py +323 -0
  408. flowtask/services/tasks/service.py +275 -0
  409. flowtask/services/tasks/task_manager.py +376 -0
  410. flowtask/services/tasks/tasks.py +155 -0
  411. flowtask/storages/__init__.py +16 -0
  412. flowtask/storages/exceptions.py +12 -0
  413. flowtask/storages/files/__init__.py +8 -0
  414. flowtask/storages/files/abstract.py +29 -0
  415. flowtask/storages/files/filesystem.py +66 -0
  416. flowtask/storages/tasks/__init__.py +19 -0
  417. flowtask/storages/tasks/abstract.py +26 -0
  418. flowtask/storages/tasks/database.py +33 -0
  419. flowtask/storages/tasks/filesystem.py +108 -0
  420. flowtask/storages/tasks/github.py +119 -0
  421. flowtask/storages/tasks/memory.py +45 -0
  422. flowtask/storages/tasks/row.py +25 -0
  423. flowtask/tasks/__init__.py +0 -0
  424. flowtask/tasks/abstract.py +526 -0
  425. flowtask/tasks/command.py +118 -0
  426. flowtask/tasks/pile.py +486 -0
  427. flowtask/tasks/py.typed +0 -0
  428. flowtask/tasks/task.py +778 -0
  429. flowtask/template/__init__.py +161 -0
  430. flowtask/tests.py +257 -0
  431. flowtask/types/__init__.py +8 -0
  432. flowtask/types/typedefs.c +11347 -0
  433. flowtask/types/typedefs.cpython-310-x86_64-linux-gnu.so +0 -0
  434. flowtask/utils/__init__.py +24 -0
  435. flowtask/utils/constants.py +117 -0
  436. flowtask/utils/encoders.py +21 -0
  437. flowtask/utils/executor.py +112 -0
  438. flowtask/utils/functions.cpp +14280 -0
  439. flowtask/utils/functions.cpython-310-x86_64-linux-gnu.so +0 -0
  440. flowtask/utils/json.cpp +13349 -0
  441. flowtask/utils/json.cpython-310-x86_64-linux-gnu.so +0 -0
  442. flowtask/utils/mail.py +63 -0
  443. flowtask/utils/parseqs.c +13324 -0
  444. flowtask/utils/parserqs.cpython-310-x86_64-linux-gnu.so +0 -0
  445. flowtask/utils/stats.py +308 -0
  446. flowtask/utils/transformations.py +74 -0
  447. flowtask/utils/uv.py +12 -0
  448. flowtask/utils/validators.py +97 -0
  449. flowtask/version.py +11 -0
  450. flowtask-5.8.4.dist-info/LICENSE +201 -0
  451. flowtask-5.8.4.dist-info/METADATA +209 -0
  452. flowtask-5.8.4.dist-info/RECORD +470 -0
  453. flowtask-5.8.4.dist-info/WHEEL +6 -0
  454. flowtask-5.8.4.dist-info/entry_points.txt +3 -0
  455. flowtask-5.8.4.dist-info/top_level.txt +2 -0
  456. plugins/components/CreateQR.py +39 -0
  457. plugins/components/TestComponent.py +28 -0
  458. plugins/components/Use1.py +13 -0
  459. plugins/components/Workplace.py +117 -0
  460. plugins/components/__init__.py +3 -0
  461. plugins/sources/__init__.py +0 -0
  462. plugins/sources/get_populartimes.py +78 -0
  463. plugins/sources/google.py +150 -0
  464. plugins/sources/hubspot.py +679 -0
  465. plugins/sources/icims.py +679 -0
  466. plugins/sources/mobileinsight.py +501 -0
  467. plugins/sources/newrelic.py +262 -0
  468. plugins/sources/uap.py +268 -0
  469. plugins/sources/venu.py +244 -0
  470. plugins/sources/vocinity.py +314 -0
@@ -0,0 +1,136 @@
1
+ import os
2
+ import asyncio
3
+ import logging
4
+ from collections.abc import Callable
5
+ import aiofiles
6
+ from ..exceptions import FileError
7
+ from .UploadTo import UploadToBase
8
+ from ..interfaces.Boto3Client import Boto3Client
9
+
10
+
11
+ class UploadToS3(Boto3Client, UploadToBase):
12
+ """
13
+ UploadToS3
14
+
15
+ Overview
16
+
17
+ The `UploadToS3` class is a specialized component that facilitates the uploading of files to an Amazon S3 bucket.
18
+ This class extends both the `Boto3Client` and `UploadToBase` classes, providing integration with AWS S3 for file
19
+ storage operations. The component supports the upload of individual files, multiple files, or entire directories.
20
+
21
+ .. table:: Properties
22
+ :widths: auto
23
+
24
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
25
+ | Name | Required | Description |
26
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
27
+ | bucket | Yes | The name of the S3 bucket to which files will be uploaded. |
28
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
29
+ | directory | Yes | The S3 directory path where files will be uploaded. |
30
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
31
+ | source_dir | Yes | The local directory containing the files to be uploaded. |
32
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
33
+ | _filenames | Yes | A list of filenames to be uploaded. |
34
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
35
+ | whole_dir | No | A flag indicating whether to upload all files in the source directory. |
36
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
37
+ | ContentType | No | The MIME type of the files to be uploaded. Defaults to "binary/octet-stream".|
38
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
39
+ | credentials | Yes | A dictionary containing the credentials necessary for AWS authentication. |
40
+ +-------------------------+----------+-----------+--------------------------------------------------------------------------+
41
+
42
+ Return
43
+
44
+ The `run` method uploads files to the specified S3 bucket, returning a dictionary containing the list of successfully
45
+ uploaded files and any errors encountered during the upload process.
46
+
47
+ """
48
+
49
+ def __init__(
50
+ self,
51
+ loop: asyncio.AbstractEventLoop = None,
52
+ job: Callable = None,
53
+ stat: Callable = None,
54
+ **kwargs,
55
+ ):
56
+ self.mdate = None
57
+ self.local_name = None
58
+ self.filename: str = ""
59
+ self.whole_dir: bool = False
60
+ self.preserve = True
61
+ self.ContentType: str = "binary/octet-stream"
62
+ super().__init__(loop=loop, job=job, stat=stat, **kwargs)
63
+
64
+ async def start(self, **kwargs):
65
+ """start Method."""
66
+ await super(UploadToS3, self).start(**kwargs)
67
+ if hasattr(self, "destination"):
68
+ self.directory = self.destination["directory"]
69
+ if not self.directory.endswith("/"):
70
+ self.directory = self.source_dir + "/"
71
+ self.directory = self.mask_replacement(self.destination["directory"])
72
+ if hasattr(self, "source"):
73
+ self.whole_dir = (
74
+ self.source["whole_dir"] if "whole_dir" in self.source else False
75
+ )
76
+ if self.whole_dir is True:
77
+ # if whole dir, is all files in source directory
78
+ logging.debug(f"Uploading all files on directory {self.source_dir}")
79
+ p = self.source_dir.glob("**/*")
80
+ self._filenames = [x for x in p if x.is_file()]
81
+ else:
82
+ if "filename" in self.source:
83
+ p = self.source_dir.glob(self.filename)
84
+ self._filenames = [x for x in p if x.is_file()]
85
+ try:
86
+ if self.previous and self.input:
87
+ self._filenames = self.input
88
+ if hasattr(self, "file"):
89
+ filenames = []
90
+ for f in self._filenames:
91
+ p = self.source_dir.glob(f)
92
+ fp = [x for x in p if x.is_file()]
93
+ filenames = filenames + fp
94
+ self._filenames = filenames
95
+ except (NameError, KeyError):
96
+ pass
97
+ return self
98
+
99
+ async def close(self):
100
+ pass
101
+
102
+ async def run(self):
103
+ """Running Upload file to S3."""
104
+ self._result = None
105
+ try:
106
+ use_credentials = self.credentials["use_credentials"]
107
+ # del self.credentials['use_credentials']
108
+ except KeyError:
109
+ use_credentials = False
110
+ async with self.get_client(
111
+ use_credentials, credentials=self.credentials, service=self.service
112
+ ) as s3_client:
113
+ errors = {}
114
+ files = {}
115
+ for file in self._filenames:
116
+ key = os.path.basename(file)
117
+ filename = f"{self.directory}{key}"
118
+ print("FILENAME ", filename)
119
+ # TODO: making async with chunks (part data)
120
+ async with aiofiles.open(file, mode="rb") as f:
121
+ content = await f.read()
122
+ response = await s3_client.put_object(
123
+ Bucket=self.bucket,
124
+ Key=filename,
125
+ Body=content,
126
+ ContentType=self.ContentType,
127
+ )
128
+ rsp = response["ResponseMetadata"]
129
+ status_code = int(rsp["HTTPStatusCode"])
130
+ if status_code == 200:
131
+ files[file] = filename
132
+ else:
133
+ errors[file] = FileError(f"S3: Upload Error: {rsp!s}")
134
+ self._result = {"files": files, "errors": errors}
135
+ self.add_metric("S3_UPLOADED", files)
136
+ return self._result
@@ -0,0 +1,160 @@
1
+ import asyncio
2
+ from collections.abc import Callable
3
+ import asyncssh
4
+ from ..exceptions import ComponentError, FileNotFound
5
+ from .UploadTo import UploadToBase
6
+ from ..interfaces.SSHClient import SSHClient
7
+
8
+
9
+ class UploadToSFTP(SSHClient, UploadToBase):
10
+ """
11
+ UploadToSFTP
12
+
13
+ Overview
14
+
15
+ The UploadToSFTP class is a component for uploading files or entire directories to an SSH/SFTP server.
16
+ It supports various configurations, including recursive directory uploads, customizable transfer settings,
17
+ and real-time upload progress tracking.
18
+
19
+ .. table:: Properties
20
+ :widths: auto
21
+
22
+ +----------------+----------+-----------+---------------------------------------------------------------+
23
+ | Name | Required | Summary |
24
+ +----------------+----------+-----------+---------------------------------------------------------------+
25
+ | source | Yes | A dictionary specifying the source directory, filename, and/or |
26
+ | | | recursive setting for selecting files to upload. |
27
+ +----------------+----------+-----------+---------------------------------------------------------------+
28
+ | destination | Yes | A dictionary defining the target directory on the SFTP server. |
29
+ +----------------+----------+-----------+---------------------------------------------------------------+
30
+ | whole_dir | No | Boolean indicating if the entire source directory should be uploaded. |
31
+ +----------------+----------+-----------+---------------------------------------------------------------+
32
+ | block_size | No | Integer defining the block size for file transfer, defaults to 65356. |
33
+ +----------------+----------+-----------+---------------------------------------------------------------+
34
+ | max_requests | No | Integer setting the max number of parallel requests, defaults to 1. |
35
+ +----------------+----------+-----------+---------------------------------------------------------------+
36
+
37
+ Returns
38
+
39
+ This component uploads files to the specified SFTP directory and returns a list of uploaded files on success.
40
+ If no files are found or a connection error occurs, it raises a relevant exception. Metrics on the number of
41
+ files uploade
42
+
43
+
44
+ Example:
45
+
46
+ ```yaml
47
+ UploadToSFTP:
48
+ host: sftp.example.com
49
+ port: 22
50
+ credentials:
51
+ username: sftpuser
52
+ password: abcd1234
53
+ destination:
54
+ directory: /incoming/
55
+ ```
56
+
57
+ """ #noqa
58
+ def __init__(
59
+ self,
60
+ loop: asyncio.AbstractEventLoop = None,
61
+ job: Callable = None,
62
+ stat: Callable = None,
63
+ **kwargs,
64
+ ):
65
+ self.mdate = None
66
+ self.local_name = None
67
+ self.filename: str = ""
68
+ self.whole_dir: bool = False
69
+ self.preserve = True
70
+ self.block_size: int = 65356
71
+ self.max_requests: int = 1
72
+ super().__init__(loop=loop, job=job, stat=stat, **kwargs)
73
+
74
+ async def start(self, **kwargs):
75
+ """start Method."""
76
+ await super(UploadToSFTP, self).start(**kwargs)
77
+ if hasattr(self, "source"):
78
+ self.whole_dir = (
79
+ self.source["whole_dir"] if "whole_dir" in self.source else False
80
+ )
81
+ if hasattr(self, "destination"):
82
+ self.directory = self.destination["directory"]
83
+ try:
84
+ if self.previous and self.input:
85
+ self.filename = self.input
86
+ elif self.file:
87
+ self.filename = self.process_pattern("file")
88
+ except (NameError, KeyError):
89
+ pass
90
+ return self
91
+
92
+ def upload_progress(self, srcpath, dstpath, bytes_copied, total_bytes):
93
+ self._pb.reset(total=total_bytes)
94
+ self._pb.update(bytes_copied)
95
+ self._pb.refresh()
96
+
97
+ async def run(self):
98
+ """Running Download file."""
99
+ self._result = None
100
+ status = False
101
+ try:
102
+ async with await self.open(
103
+ host=self.host,
104
+ port=self.port,
105
+ tunnel=self.tunnel,
106
+ credentials=self.credentials,
107
+ ):
108
+ async with self._connection.start_sftp_client() as sftp:
109
+ # check all versions of functionalities
110
+ args = {
111
+ "block_size": self.block_size,
112
+ "max_requests": self.max_requests,
113
+ "progress_handler": self.upload_progress,
114
+ "error_handler": self.err_handler,
115
+ }
116
+ if self.whole_dir is True:
117
+ self._logger.debug(
118
+ f"Uploading all files on directory {self.source_dir}"
119
+ )
120
+ file = "{}/*".format(self.source_dir)
121
+ p = self.source_dir.glob("**/*")
122
+ self.filename = [x for x in p if x.is_file()]
123
+ else:
124
+ file = self.filename
125
+ args["remotepath"] = self.directory
126
+ if hasattr(self, "source"):
127
+ args["recurse"] = True if "recursive" in self.source else False
128
+ if not file:
129
+ raise FileNotFound(f"There is no local File: {file}")
130
+ self.start_progress(total=len(file))
131
+ try:
132
+ self._logger.debug(f"Uploading file: {file} to {self.directory}")
133
+ status = await sftp.mput(file, **args)
134
+ self.close_progress()
135
+ except OSError as err:
136
+ self._logger.error(f"Upload SFTP local error: {err}")
137
+ return False
138
+ except asyncssh.sftp.SFTPError as err:
139
+ self._logger.error(f"SFTP UploadTo Server error: {err}")
140
+ return False
141
+ except asyncssh.Error as err:
142
+ self._logger.error(f"Upload 2 SFTP: connection failed: {err}")
143
+ except Exception as err:
144
+ self._logger.exception(err)
145
+ raise
146
+ except asyncio.CancelledError:
147
+ self._logger.info(
148
+ f"{self.host} CANCELED~"
149
+ )
150
+ # break
151
+ except (asyncio.TimeoutError, ComponentError) as err:
152
+ raise ComponentError(f"{err!s}") from err
153
+ except Exception as err:
154
+ raise ComponentError(f"{err!s}") from err
155
+ if status is False:
156
+ return False
157
+ else:
158
+ self.add_metric("SFTP_FILES", self.filename)
159
+ self._result = self.filename
160
+ return self._result
@@ -0,0 +1,205 @@
1
+ import os
2
+ from collections.abc import Callable
3
+ import asyncio
4
+ import logging
5
+ from pathlib import Path
6
+ from ..exceptions import (
7
+ FileError,
8
+ ConfigError
9
+ )
10
+ from .UploadTo import UploadToBase
11
+ from ..interfaces.Sharepoint import SharepointClient
12
+
13
+
14
+ class UploadToSharepoint(SharepointClient, UploadToBase):
15
+ """
16
+ UploadToSharepoint
17
+
18
+ Overview
19
+
20
+ The UploadToSharepoint class is a component for uploading files or entire directories to a SharePoint site.
21
+ It supports various configuration options for selecting files by name, extension, or pattern, and includes
22
+ functionality for recursive directory searches.
23
+
24
+ .. table:: Properties
25
+ :widths: auto
26
+
27
+ +----------------+----------+-----------+---------------------------------------------------------------+
28
+ | Name | Required | Summary |
29
+ +----------------+----------+-----------+---------------------------------------------------------------+
30
+ | credentials | Yes | A dictionary with SharePoint credentials: `username`, `password`, |
31
+ | | | `tenant`, and `site`. |
32
+ +----------------+----------+-----------+---------------------------------------------------------------+
33
+ | source | Yes | A dictionary specifying the source directory, filename, and/or file |
34
+ | | | extension for selecting files to upload. |
35
+ +----------------+----------+-----------+---------------------------------------------------------------+
36
+ | destination | Yes | A dictionary defining the SharePoint destination directory. |
37
+ +----------------+----------+-----------+---------------------------------------------------------------+
38
+ | whole_dir | No | Boolean indicating if the entire source directory should be uploaded. |
39
+ +----------------+----------+-----------+---------------------------------------------------------------+
40
+ | recursive | No | Boolean specifying whether to search recursively within directories. |
41
+ +----------------+----------+-----------+---------------------------------------------------------------+
42
+
43
+ Returns
44
+
45
+ This component uploads files to a specified SharePoint directory and returns the upload result status.
46
+ It logs the upload activity and records metrics for the number of files uploaded. If no files are found
47
+ or the configuration is incomplete, it raises an error. The upload can handle both individual files and
48
+ entire folders, depending on configuration.
49
+
50
+
51
+ Example:
52
+
53
+ ```yaml
54
+ UploadToSharepoint:
55
+ credentials:
56
+ username: sharepoint_username
57
+ password: sharepoint_password
58
+ tenant: symbits
59
+ site: trocstorage
60
+ destination:
61
+ directory: Shared Documents/Optimum Sales Files
62
+ masks:
63
+ '{today}':
64
+ - today
65
+ - mask: '%Y%m%d%H%M%S'
66
+ ```
67
+
68
+ """ # noqa
69
+
70
+ # dict of expected credentials
71
+ _credentials: dict = {
72
+ "username": str,
73
+ "password": str,
74
+ "tenant": str,
75
+ "site": str
76
+ }
77
+
78
+ def __init__(
79
+ self,
80
+ loop: asyncio.AbstractEventLoop = None,
81
+ job: Callable = None,
82
+ stat: Callable = None,
83
+ **kwargs,
84
+ ):
85
+ self.mdate = None
86
+ self.local_name = None
87
+ self.filename: str = ""
88
+ self.whole_dir: bool = False
89
+ self.preserve = True
90
+ self.ContentType: str = "binary/octet-stream"
91
+ self.recursive: bool = kwargs.get('recursive', False)
92
+ super().__init__(
93
+ loop=loop,
94
+ job=job,
95
+ stat=stat,
96
+ **kwargs
97
+ )
98
+ self.define_host = None
99
+
100
+ async def start(self, **kwargs):
101
+ """start Method."""
102
+ await super(UploadToSharepoint, self).start(**kwargs)
103
+ if hasattr(self, "source"):
104
+ self.source_dir = self.source.get('directory')
105
+ if isinstance(self.source_dir, str):
106
+ self.source_dir = Path(self.source_dir).resolve()
107
+ self.filename = self.source.get("filename", None)
108
+ self.whole_dir = (
109
+ self.source["whole_dir"] if "whole_dir" in self.source else False
110
+ )
111
+ if self.whole_dir is True:
112
+ # if whole dir, is all files in source directory
113
+ logging.debug(
114
+ f"Uploading all files on directory {self.source_dir}"
115
+ )
116
+ p = self.source_dir.glob("**/*")
117
+ self._filenames = [
118
+ x for x in p if x.is_file()
119
+ ]
120
+ else:
121
+ if "filename" in self.source:
122
+ filename = self.source_dir.joinpath(self.source_file)
123
+ if filename.is_dir():
124
+ p = self.source_dir.glob(filename)
125
+ self._filenames = [
126
+ x for x in p if x.is_file()
127
+ ]
128
+ else:
129
+ self._filenames = [filename]
130
+ elif 'extension' in self.source:
131
+ extension = self.source["extension"]
132
+ pattern = self.source.get("pattern", None)
133
+ if pattern:
134
+ # TODO: fix recursive problem from Glob
135
+ if self.recursive is True:
136
+ p = self.source_dir.rglob(f"**/*{pattern}*{extension}")
137
+ else:
138
+ p = self.source_dir.glob(f"*{pattern}*{extension}")
139
+ else:
140
+ if self.recursive is True:
141
+ p = self.source_dir.rglob(f"**/*{extension}")
142
+ else:
143
+ p = self.source_dir.glob(f"*{pattern}*{extension}")
144
+ self._filenames = [
145
+ x for x in p if x.is_file()
146
+ ]
147
+ else:
148
+ raise ConfigError(
149
+ "UploadToSharepoint: No filename or extension in source"
150
+ )
151
+ if hasattr(self, "destination"):
152
+ # Destination in Sharepoint:
153
+ self.directory = self.destination["directory"]
154
+ if not self.directory.endswith("/"):
155
+ self.directory = str(self.directory) + "/"
156
+ self.directory = self.mask_replacement(self.destination["directory"])
157
+ else:
158
+ if self.previous and self.input:
159
+ self._filenames = self.input
160
+ if hasattr(self, "file"):
161
+ filenames = []
162
+ for f in self._filenames:
163
+ p = self.source_dir.glob(f)
164
+ fp = [x for x in p if x.is_file()]
165
+ filenames = filenames + fp
166
+ self._filenames = filenames
167
+ elif 'extension' in self.source:
168
+ extension = self.source["extension"]
169
+ pattern = self.source.get("pattern", None)
170
+ # check if files in self._filenames ends with extension
171
+ filenames = []
172
+ for f in self._filenames:
173
+ if f.suffix == extension:
174
+ # check if pattern is in the filename
175
+ if pattern:
176
+ if pattern in f.name:
177
+ filenames.append(f)
178
+ continue
179
+ else:
180
+ filenames.append(f)
181
+ self._filenames = filenames
182
+ return self
183
+
184
+ async def close(self):
185
+ pass
186
+
187
+ async def run(self):
188
+ """Upload a File to Sharepoint"""
189
+ self._result = None
190
+ async with self.connection():
191
+ if not self.context:
192
+ self.context = self.get_context(self.url)
193
+ if not self._filenames:
194
+ raise FileError("No files to upload")
195
+ if self.whole_dir is True:
196
+ # Using Upload entire Folder:
197
+ self._result = await self.upload_folder(
198
+ local_folder=self.source_dir
199
+ )
200
+ else:
201
+ self._result = await self.upload_files(
202
+ filenames=self._filenames
203
+ )
204
+ self.add_metric("SHAREPOINT_UPLOADED", self._result)
205
+ return self._result
@@ -0,0 +1,122 @@
1
+ from typing import Union
2
+ import importlib
3
+ import asyncio
4
+ import logging
5
+ from collections.abc import Callable, Awaitable
6
+ from ..exceptions import ComponentError
7
+ from settings.settings import TASK_STORAGES
8
+ from .flow import FlowComponent
9
+
10
+
11
+ def getFunction(program, function):
12
+ """getFunction.
13
+
14
+ Example:
15
+
16
+ ```yaml
17
+ UserFunc:
18
+ function: scheduling_visits
19
+ args:
20
+ max_distance: 400
21
+ max_stores: 5
22
+ year: 2024
23
+ month: 11
24
+ ```
25
+
26
+ """
27
+ ## TODO: detect TaskStorage of the task
28
+ storage = TASK_STORAGES["default"]
29
+ fn_path = storage.path.joinpath(program, "functions", f"{function}.py")
30
+ try:
31
+ spec = importlib.util.spec_from_file_location(function, fn_path)
32
+ module = importlib.util.module_from_spec(spec)
33
+ spec.loader.exec_module(module)
34
+ obj = getattr(module, function)
35
+ return obj
36
+ except ImportError as e:
37
+ logging.error(f"UserFunc: No Function {function} was Found")
38
+ raise ComponentError(
39
+ f"UserFunc: No Python Function {function} was Found on {fn_path}"
40
+ ) from e
41
+
42
+
43
+ class UserFunc(FlowComponent):
44
+ """
45
+ UserFunc.
46
+
47
+ Overview
48
+
49
+ Run a arbitrary user function and return result
50
+
51
+ .. table:: Properties
52
+ :widths: auto
53
+
54
+
55
+ +--------------+----------+-----------+-------------------------------------------------------+
56
+ | Name | Required | Summary |
57
+ +--------------+----------+-----------+-------------------------------------------------------+
58
+ | function | Yes | Name function |
59
+ +--------------+----------+-----------+-------------------------------------------------------+
60
+ | params | Yes | Allows you to set parameters |
61
+ +--------------+----------+-----------+-------------------------------------------------------+
62
+ | foo | Yes | Variable name |
63
+ +--------------+----------+-----------+-------------------------------------------------------+
64
+ | api_keys | Yes | Api password to query |
65
+ +--------------+----------+-----------+-------------------------------------------------------+
66
+
67
+ Return the list of arbitrary days
68
+
69
+
70
+
71
+
72
+ """
73
+
74
+ def __init__(
75
+ self,
76
+ loop: asyncio.AbstractEventLoop = None,
77
+ job: Callable = None,
78
+ stat: Callable = None,
79
+ **kwargs,
80
+ ):
81
+ """Init Method."""
82
+ self._fn: Union[Callable, Awaitable] = None
83
+ self.data = None
84
+ self.params = None
85
+ self.function: Callable = None
86
+ self._kwargs = kwargs.get('args', {})
87
+ super(UserFunc, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
88
+
89
+ async def start(self, **kwargs):
90
+ """Obtain Previous data."""
91
+ if self.previous:
92
+ self.data = self.input
93
+ try:
94
+ self._fn = getFunction(self._program, self.function)
95
+ except ComponentError as err:
96
+ raise ComponentError(
97
+ f"UserFunc: Error getting Function from {self.function}"
98
+ ) from err
99
+
100
+ async def close(self):
101
+ """Close Method."""
102
+
103
+ async def run(self):
104
+ """Run Method."""
105
+ self._result = None
106
+ params = {"data": self.data, "variables": self._variables, **self._kwargs}
107
+ if self.params:
108
+ params = {**params, **self.params}
109
+ try:
110
+ if asyncio.iscoroutinefunction(self._fn):
111
+ result = await self._fn(
112
+ self, loop=self._loop, env=self._environment, **params
113
+ )
114
+ else:
115
+ result = self._fn(
116
+ self, loop=self._loop, env=self._environment, **params
117
+ )
118
+ self._result = result
119
+ self.add_metric("UDF", f"{self._fn!s}")
120
+ return self._result
121
+ except ComponentError as err:
122
+ raise ComponentError(f"UserFunc: Error calling {self._fn}: {err}") from err