flowtask 5.8.4__cp312-cp312-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-312-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-312-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-312-x86_64-linux-gnu.so +0 -0
  377. flowtask/parsers/json.c +11968 -0
  378. flowtask/parsers/json.cpython-312-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-312-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-312-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-312-x86_64-linux-gnu.so +0 -0
  440. flowtask/utils/json.cpp +13349 -0
  441. flowtask/utils/json.cpython-312-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-312-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,176 @@
1
+ import asyncio
2
+ from collections.abc import Callable
3
+ import pandas as pd
4
+ import numpy as np
5
+ from ..exceptions import ComponentError
6
+ from .flow import FlowComponent
7
+
8
+
9
+ class TransposeRows(FlowComponent):
10
+ """
11
+ TransposeRows
12
+
13
+ Overview
14
+
15
+ The TransposeRows class is a component for transposing specified rows in a DataFrame by converting row values
16
+ into new columns based on pivot settings. This component supports options for preserving the original data,
17
+ handling empty results, and custom column configurations for the transposition.
18
+
19
+ .. table:: Properties
20
+ :widths: auto
21
+
22
+ +------------------+----------+-----------+---------------------------------------------------------------+
23
+ | Name | Required | Summary |
24
+ +------------------+----------+-----------+---------------------------------------------------------------+
25
+ | pivot | Yes | List of columns to use as the pivot index for transposition. |
26
+ +------------------+----------+-----------+---------------------------------------------------------------+
27
+ | columns | Yes | Dictionary mapping row values to their target column names. |
28
+ +------------------+----------+-----------+---------------------------------------------------------------+
29
+ | preserve_original| No | Boolean indicating if the original rows should be preserved. |
30
+ +------------------+----------+-----------+---------------------------------------------------------------+
31
+ | allow_empty | No | Boolean indicating if empty columns should be allowed in the output. |
32
+ +------------------+----------+-----------+---------------------------------------------------------------+
33
+
34
+ Returns
35
+
36
+ This component returns a DataFrame with specified rows transposed into columns according to the provided pivot
37
+ and column configurations. If `preserve_original` is set to False, the original rows used in transposition
38
+ are removed. Any errors in column mapping or pivoting are raised with descriptive error messages.
39
+
40
+
41
+ Example:
42
+
43
+ ```yaml
44
+ TransposeRows:
45
+ column: column_name
46
+ value: data
47
+ pivot:
48
+ - formid
49
+ - form_id
50
+ - orgid
51
+ preserve_original: true
52
+ allow_empty: true
53
+ columns:
54
+ '000_001': ad_hoc
55
+ '000_003': creation_timestamp
56
+ '000_004': user_device
57
+ 000_008: geoloc
58
+ 000_009: visit_length
59
+ '000_012': store_name
60
+ '000_013': store_id
61
+ '000_023': account_name
62
+ '000_024': store_designation
63
+ '000_026': region_name
64
+ 000_029: store_timezone
65
+ '000_037': visitor_username
66
+ 000_038: visitor_name
67
+ 000_039: visitor_email
68
+ '000_045': visitor_role
69
+ '000_055': updated_timestamp
70
+ '000_065': activity_item_id
71
+ '000_063': time_in
72
+ '000_064': time_out
73
+ '000_066': position_id
74
+ '000_067': position_manager
75
+ '000_070': visit_status
76
+ '194834': retailer
77
+ VisitDateLocal: visit_timestamp
78
+ ```
79
+
80
+ """ #noqa
81
+
82
+ def __init__(
83
+ self,
84
+ loop: asyncio.AbstractEventLoop = None,
85
+ job: Callable = None,
86
+ stat: Callable = None,
87
+ **kwargs,
88
+ ):
89
+ """Init Method."""
90
+ self._pivot: list = kwargs.pop("pivot")
91
+ self.preserve: bool = kwargs.pop("preserve_original", False)
92
+ self.allow_empty: bool = kwargs.pop("allow_empty", False)
93
+ if not self._pivot:
94
+ raise ComponentError("Missing List of Pivot Columns")
95
+ # columns to be transposed:
96
+ # TODO: if not, then all columns not in Pivot list.
97
+ self._columns = kwargs.pop("columns")
98
+ super(TransposeRows, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
99
+
100
+ async def start(self, **kwargs):
101
+ if self.previous:
102
+ self.data = self.input
103
+ else:
104
+ raise ComponentError("Data Not Found", status=404)
105
+ if not isinstance(self.data, pd.DataFrame):
106
+ raise ComponentError("Transpose: Incompatible Pandas Dataframe", status=404)
107
+ if not hasattr(self, "column"):
108
+ raise ComponentError(
109
+ "Transpose: Missing Column name for extracting row values"
110
+ )
111
+ if not hasattr(self, "value"):
112
+ raise ComponentError("Transpose: Missing Column for Values")
113
+ return True
114
+
115
+ async def close(self):
116
+ pass
117
+
118
+ def row_to_column(self, df: pd.DataFrame, row_to_pivot: str, new_name: str):
119
+ """
120
+ Add a pivoted column to the dataframe based on the given column name.
121
+
122
+ Parameters:
123
+ - df: The input dataframe.
124
+ - row_to_pivot: The column name to be pivoted.
125
+ - new_name: The name of the column to be transposed.
126
+
127
+ Returns:
128
+ - Dataframe with the new pivoted column.
129
+ """
130
+ # Filter the dataframe to only include rows with the desired column_name
131
+ df_filtered = df[df[self.column] == row_to_pivot]
132
+ if df_filtered.empty is True:
133
+ # there is no data to be filtered:
134
+ if self.allow_empty is True:
135
+ df[new_name] = np.nan
136
+ return df
137
+ # Pivot the filtered dataframe
138
+ df_pivot = df_filtered.pivot_table(
139
+ index=self._pivot,
140
+ columns=self.column,
141
+ values=self.value,
142
+ aggfunc="first",
143
+ dropna=False, # Preserve NaN values
144
+ ).reset_index()
145
+ df_pivot = df_pivot.rename(columns={row_to_pivot: new_name})
146
+ # Merge the pivoted dataframe with the original dataframe
147
+ df_merged = pd.merge(df, df_pivot, on=self._pivot, how="left")
148
+ if self.preserve is False:
149
+ # Drop the original column_name and value columns for the pivoted rows
150
+ df_merged = df_merged.drop(
151
+ df_merged[(df_merged[self.column] == row_to_pivot)].index
152
+ )
153
+ return df_merged
154
+
155
+ async def run(self):
156
+ try:
157
+ df = self.data
158
+ for column, value in self._columns.items():
159
+ try:
160
+ df_pivot = self.row_to_column(df, column, value)
161
+ except Exception as err:
162
+ print(err)
163
+ df = df_pivot
164
+ if self._debug is True:
165
+ print("=== TRANSPOSE ===")
166
+ print(" = Data Types: = ")
167
+ print(df.dtypes)
168
+ print("::: Printing Column Information === ")
169
+ for column, t in df.dtypes.items():
170
+ print(column, "->", t, "->", df[column].iloc[0])
171
+ self._result = df
172
+ return self._result
173
+ except (ValueError, KeyError) as err:
174
+ raise ComponentError(f"Crosstab Error: {err!s}") from err
175
+ except Exception as err:
176
+ raise ComponentError(f"Unknown error {err!s}") from err
@@ -0,0 +1,86 @@
1
+ from datetime import date
2
+ from .RESTClient import AbstractREST
3
+
4
+
5
+ class UPCDatabase(AbstractREST):
6
+ """
7
+ UPCDatabase.
8
+
9
+ Querying UPC Database for Product information.
10
+
11
+
12
+ Example:
13
+
14
+ ```yaml
15
+ UPCDatabase:
16
+ method: currency
17
+ base: USD
18
+ credentials:
19
+ apikey: UPC_API_KEY
20
+ ```
21
+
22
+ """
23
+
24
+ base_url: str = "https://api.upcdatabase.org/"
25
+ _default_method: str = "currency"
26
+
27
+ async def start(self, **kwargs):
28
+ if not self.credentials:
29
+ # obtengo las credenciales
30
+ self.credentials["apikey"] = self._environment.get("UPC_API_KEY")
31
+ if not self.credentials["apikey"]:
32
+ raise ValueError("UPC Database: Missing Credentials")
33
+ # calling method for this element:
34
+ await super(UPCDatabase, self).start(**kwargs)
35
+
36
+ async def currency(self):
37
+ """currency.
38
+
39
+ Currency information and exchange rates supported by UPC
40
+ """
41
+ self.method = "get"
42
+ self.url = self.base_url + "currency/latest/"
43
+ try:
44
+ self.parameters["base"] = self.base
45
+ except (ValueError, TypeError):
46
+ self.parameters["base"] = "USD"
47
+
48
+ async def currency_history(self):
49
+ """currency.
50
+
51
+ Retrieves the currency conversion rates for a specific date.
52
+ """
53
+ self.method = "get"
54
+ self.url = self.base_url + "currency/history"
55
+ try:
56
+ self.parameters["base"] = self.base
57
+ except (ValueError, TypeError):
58
+ self.parameters["base"] = "USD"
59
+ try:
60
+ self.parameters["date"] = self.date
61
+ except (ValueError, AttributeError):
62
+ today = date.today()
63
+ self.parameters["date"] = today.strftime("%Y-%m-%d")
64
+
65
+ async def product(self):
66
+ """product.
67
+
68
+ Product information based on UPC barcode
69
+ """
70
+ self.method = "get"
71
+ if not "barcode" in self._args:
72
+ raise ValueError("UPC Database: Missing Barcode")
73
+ self.url = self.base_url + "product/{barcode}"
74
+
75
+ async def search(self):
76
+ """product.
77
+
78
+ Search for a product based on item parameters.
79
+ """
80
+ self.method = "get"
81
+ self.url = self.base_url + "search/"
82
+ self.parameters["page"] = 1
83
+ try:
84
+ self.parameters["query"] = self.query
85
+ except (ValueError, TypeError) as e:
86
+ raise ValueError("UPC Database: Missing or wrong *query* Search.") from e
@@ -0,0 +1,171 @@
1
+ import os
2
+ import logging
3
+ import asyncio
4
+ from typing import List
5
+ from collections.abc import Callable
6
+ from pathlib import PosixPath, Path, PurePath
7
+ import tarfile
8
+ from ..exceptions import FileError, ComponentError, FileNotFound
9
+ from .FileCopy import FileCopy
10
+ from ..utils import check_empty
11
+ from ..interfaces.compress import CompressSupport
12
+
13
+
14
+ class UnGzip(CompressSupport, FileCopy):
15
+ """
16
+ UnGzip
17
+
18
+ Overview
19
+
20
+ The UnGzip class is a component for decompressing Gzip (.gz) files, including compressed tarballs (e.g., .tar.gz, .tar.bz2, .tar.xz).
21
+ This component extracts the specified Gzip or tarball file into a target directory and supports optional source file deletion
22
+ after extraction.
23
+
24
+ .. table:: Properties
25
+ :widths: auto
26
+
27
+ +----------------+----------+-----------+---------------------------------------------------------------+
28
+ | Name | Required | Summary |
29
+ +----------------+----------+-----------+---------------------------------------------------------------+
30
+ | filename | Yes | The path to the Gzip file to uncompress. |
31
+ +----------------+----------+-----------+---------------------------------------------------------------+
32
+ | directory | Yes | The target directory where files will be extracted. |
33
+ +----------------+----------+-----------+---------------------------------------------------------------+
34
+ | delete_source | No | Boolean indicating if the source file should be deleted post-extraction. |
35
+ +----------------+----------+-----------+---------------------------------------------------------------+
36
+ | extract | No | Dictionary specifying filenames to extract and/or output directory. |
37
+ +----------------+----------+-----------+---------------------------------------------------------------+
38
+
39
+ Returns
40
+
41
+ This component extracts files from a specified Gzip or tarball archive into the designated directory
42
+ and returns a list of paths to the extracted files. It tracks metrics for the output directory and the source
43
+ Gzip file. If configured, the original compressed file is deleted after extraction. Errors encountered during
44
+ extraction or directory creation are logged and raised as exceptions.
45
+
46
+
47
+ Example:
48
+
49
+ ```yaml
50
+ UnGzip:
51
+ source:
52
+ directory: /home/ubuntu/symbits/mso/files/commissions_statements/pr/
53
+ filename: STATEMENT_STATEMENT-*.CSV.gz
54
+ destination:
55
+ directory: /home/ubuntu/symbits/mso/files/commissions_statements/pr/
56
+ delete_source: true
57
+ ```
58
+
59
+ """ # noqa
60
+
61
+ _namelist = []
62
+ _directory = ""
63
+
64
+ def __init__(
65
+ self,
66
+ loop: asyncio.AbstractEventLoop = None,
67
+ job: Callable = None,
68
+ stat: Callable = None,
69
+ **kwargs,
70
+ ):
71
+ """Init Method."""
72
+ self._output: PurePath = None
73
+ self._filenames: List = []
74
+ self.delete_source: bool = False
75
+ self._as_list: bool = kwargs.pop('as_list', False)
76
+ self._binary_sources: dict = None
77
+ super(UnGzip, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
78
+
79
+ async def start(self, **kwargs):
80
+ if self.previous and not check_empty(self.input) and getattr(self, "ignore_previous", False) is False:
81
+ if isinstance(self.input, dict):
82
+ self._binary_sources = self.input.get('files', {})
83
+ return True
84
+ await super().start(**kwargs)
85
+ # Handle extraction settings
86
+ if hasattr(self, "destination"):
87
+ # New format using destination
88
+ if isinstance(self.destination, dict) and "directory" in self.destination:
89
+ self._destination = Path(self.destination["directory"]).resolve()
90
+ else:
91
+ self._destination = Path(self.destination).resolve()
92
+ elif hasattr(self, "extract"):
93
+ # Legacy format using extract
94
+ for _, filename in enumerate(self.extract["filenames"]):
95
+ filename = self.mask_replacement(filename)
96
+ self._filenames.append(filename)
97
+ if "directory" in self.extract:
98
+ self._destination = Path(self.extract["directory"]).resolve()
99
+ else:
100
+ # same directory as source
101
+ self._destination = Path(self.directory)
102
+ else:
103
+ # If no destination specified, use source directory
104
+ self._destination = Path(self.directory)
105
+ # Create destination directory if it doesn't exist
106
+ try:
107
+ self._destination.mkdir(parents=True, exist_ok=True)
108
+ except Exception as err:
109
+ logging.error(f"Error creating directory {self._destination}: {err}")
110
+ raise ComponentError(
111
+ f"Error creating directory {self._destination}: {err}"
112
+ ) from err
113
+ # For backwards compatibility
114
+ self._output = self._destination
115
+ return True
116
+
117
+ async def close(self):
118
+ pass
119
+
120
+ async def run(self):
121
+ # Check if file exists
122
+ self._result = {}
123
+ filenames = []
124
+ if self._binary_sources:
125
+ for filename, contents in self._binary_sources.items():
126
+ # get binary contents:
127
+ data = contents.get('data')
128
+ data.seek(0) # restarts from beginning
129
+ # Uncompress gzip contents in memory:
130
+ try:
131
+ f = await self.uncompress_gzip(
132
+ source=data,
133
+ destination=None
134
+ )
135
+ filenames.append(
136
+ {"filename": filename, "data": f}
137
+ )
138
+ except RuntimeError as err:
139
+ raise FileError(f"UnGzip failed: {err}")
140
+ self._result = filenames
141
+ elif self._sources:
142
+ for file in self._sources:
143
+ if not file.exists() or not file.is_file():
144
+ raise FileNotFound(
145
+ f"Compressed File doesn't exist: {file}"
146
+ )
147
+ # Uncompress the gzip/tar.gz file
148
+ try:
149
+ files = await self.uncompress_gzip(
150
+ source=file,
151
+ destination=self._destination,
152
+ remove_source=self.delete_source,
153
+ )
154
+ except (FileNotFoundError, ComponentError) as err:
155
+ raise FileError(f"UnGzip failed: {err}")
156
+ except RuntimeError as err:
157
+ raise FileError(f"UnGzip failed: {err}")
158
+
159
+ if self.delete_source:
160
+ file.unlink(missing_ok=True)
161
+
162
+ filenames = []
163
+ for filename in files:
164
+ filenames.append(filename)
165
+ self._result[str(file)] = filenames
166
+ if self._as_list is True:
167
+ self._result = filenames
168
+ self.add_metric("OUTPUT_DIRECTORY", self._destination)
169
+ self.add_metric("FILES_UNCOMPRESS", len(filenames))
170
+ # Support both metrics for backwards compatibility
171
+ return self._result
@@ -0,0 +1,172 @@
1
+ import os
2
+ import logging
3
+ import asyncio
4
+ from typing import List
5
+ from collections.abc import Callable
6
+ from pathlib import PosixPath, Path, PurePath
7
+ from zipfile import ZipFile, BadZipFile
8
+ from ..exceptions import FileError, ComponentError, FileNotFound
9
+ from .flow import FlowComponent
10
+ from ..interfaces.compress import CompressSupport
11
+
12
+
13
+ class Uncompress(CompressSupport, FlowComponent):
14
+ """
15
+ Uncompress
16
+
17
+ Overview
18
+
19
+ The Uncompress class is a component for decompressing files in various archive formats, including but not limited to:
20
+ 7z (.7z), ACE (.ace), ALZIP (.alz), AR (.a), ARC (.arc), ARJ (.arj), BZIP2 (.bz2), CAB (.cab), compress (.Z),
21
+ CPIO (.cpio), DEB (.deb), DMS (.dms), GZIP (.gz), LRZIP (.lrz), LZH (.lha, .lzh), LZIP (.lz), LZMA (.lzma),
22
+ LZOP (.lzo), RPM (.rpm), RAR (.rar), RZIP (.rz), TAR (.tar), XZ (.xz), ZIP (.zip, .jar), and ZOO (.zoo).
23
+ It extracts the specified compressed file into a target directory and can optionally delete the source file
24
+ upon successful extraction.
25
+
26
+ .. table:: Properties
27
+ :widths: auto
28
+
29
+ +----------------+----------+-----------+---------------------------------------------------------------+
30
+ | Name | Required | Summary |
31
+ +----------------+----------+-----------+---------------------------------------------------------------+
32
+ | filename | Yes | The path to the compressed file to be decompressed. |
33
+ +----------------+----------+-----------+---------------------------------------------------------------+
34
+ | directory | Yes | The target directory where files will be extracted. |
35
+ +----------------+----------+-----------+---------------------------------------------------------------+
36
+ | delete_source | No | Boolean indicating if the source file should be deleted post-extraction. |
37
+ +----------------+----------+-----------+---------------------------------------------------------------+
38
+ | extract | No | Dictionary specifying filenames to extract and/or output directory. |
39
+ +----------------+----------+-----------+---------------------------------------------------------------+
40
+ | password | No | Optional password for encrypted files in supported formats. |
41
+ +----------------+----------+-----------+---------------------------------------------------------------+
42
+
43
+ Returns
44
+
45
+ This component extracts files from the specified compressed archive into the designated directory and returns
46
+ a list of paths to the extracted files. It tracks metrics for the output directory and compressed file name.
47
+ If configured, the original compressed file is deleted after extraction. Errors related to file corruption
48
+ or extraction issues are logged and raised as exceptions.
49
+
50
+
51
+ Example:
52
+
53
+ ```yaml
54
+ Uncompress:
55
+ filename: organizational_unit_ancestors_{yesterday}.zip
56
+ masks:
57
+ yesterday:
58
+ - yesterday
59
+ - mask: '%Y-%m-%d'
60
+ directory: /home/ubuntu/symbits/polestar/files/organizational_unit_ancestors/
61
+ extract:
62
+ filenames:
63
+ - OrganizationalUnitAncestors.csv
64
+ directory: /home/ubuntu/symbits/polestar/files/organizational_unit_ancestors/
65
+ delete_source: false
66
+ ```
67
+
68
+ """ #noqa
69
+
70
+ _namelist = []
71
+ _directory = ""
72
+
73
+ def __init__(
74
+ self,
75
+ loop: asyncio.AbstractEventLoop = None,
76
+ job: Callable = None,
77
+ stat: Callable = None,
78
+ **kwargs,
79
+ ):
80
+ """Init Method."""
81
+ self.filename: str = None
82
+ self.directory: PurePath = None
83
+ self._path: PurePath = None
84
+ self._output: PurePath = None
85
+ self._filenames: List = []
86
+ self.delete_source: bool = False
87
+ super(Uncompress, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
88
+
89
+ async def start(self, **kwargs):
90
+ if isinstance(self.directory, str):
91
+ self.directory = PosixPath(self.directory).resolve()
92
+ self._path = PosixPath(self.directory, self.filename)
93
+ if self.filename is not None:
94
+ if hasattr(self, "masks"):
95
+ self.filename = self.mask_replacement(self.filename)
96
+ self._path = PosixPath(self.directory, self.filename)
97
+ elif self.previous:
98
+ if isinstance(self.input, PosixPath):
99
+ self.filename = self.input
100
+ elif isinstance(self.input, list):
101
+ self.filename = PosixPath(self.input[0])
102
+ elif isinstance(self.input, str):
103
+ self.filename = PosixPath(self.input)
104
+ else:
105
+ filenames = list(self.input.keys())
106
+ if filenames:
107
+ try:
108
+ self.filename = PosixPath(filenames[0])
109
+ except IndexError as err:
110
+ raise FileError("File is empty or doesnt exists") from err
111
+ self._variables["__FILEPATH__"] = self.filename
112
+ self._variables["__FILENAME__"] = os.path.basename(self.filename)
113
+ self._path = self.filename
114
+ else:
115
+ raise FileError("UnCompress: File is empty or doesn't exists")
116
+ if hasattr(self, "extract"):
117
+ for _, filename in enumerate(self.extract["filenames"]):
118
+ filename = self.mask_replacement(filename)
119
+ self._filenames.append(filename)
120
+ if "directory" in self.extract:
121
+ self._output = Path(self.extract["directory"]).resolve()
122
+ # Create directory if not exists
123
+ try:
124
+ self._output.mkdir(parents=True, exist_ok=True)
125
+ except Exception as err:
126
+ logging.error(f"Error creating directory {self._output}: {err}")
127
+ raise ComponentError(
128
+ f"Error creating directory {self._output}: {err}"
129
+ ) from err
130
+ else:
131
+ # same directory:
132
+ self._output = Path(self.directory)
133
+ self.add_metric("OUTPUT_DIRECTORY", self._output)
134
+ self.add_metric("ZIP_FILE", self.filename)
135
+ return True
136
+
137
+ async def close(self):
138
+ pass
139
+
140
+ async def run(self):
141
+ # Check if File exists
142
+ self._result = None
143
+ if not self._path.exists() or not self._path.is_file():
144
+ raise FileNotFound(
145
+ f"Compressed File doesn't exists: {self._path}"
146
+ )
147
+ with ZipFile(self._path) as zfp:
148
+ status = zfp.testzip()
149
+ if not status: # Si no hay status
150
+ # If not exists namelist, extract all files
151
+ members = self._filenames if self._filenames else None
152
+ # If not exists password return None
153
+ pwd = self.password if hasattr(self, "password") else None
154
+ try:
155
+ zfp.extractall(path=self._output, members=members, pwd=pwd)
156
+ if self.delete_source is True:
157
+ self._path.unlink()
158
+ except BadZipFile as err:
159
+ # The error raised for bad ZIP files.
160
+ raise ComponentError(f"Bad Zip File: {err}") from err
161
+ except Exception as err:
162
+ # Undefined error
163
+ raise ComponentError(f"{self.__name__} ZIP Error: {err}") from err
164
+ result = self._filenames if self._filenames else zfp.namelist()
165
+ filenames = []
166
+ for filename in result:
167
+ f = self._output.joinpath(filename)
168
+ filenames.append(f)
169
+ self._result = filenames
170
+ else: # Si hay status devuelve el primer archivo corrupto
171
+ raise ComponentError(f"Zip File {status} is corrupted")
172
+ return self._result