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,376 @@
1
+ """
2
+ TaskManager.
3
+
4
+ Work with managing tasks, creation, deleting, listing, etc.
5
+ """
6
+ import asyncio
7
+ import json
8
+ import datetime
9
+ import uuid
10
+ from functools import partial
11
+ from uuid import UUID
12
+ import logging
13
+ import ast
14
+ from aiohttp import web
15
+ from navigator.views import DataView
16
+ from asyncdb.utils.encoders import BaseEncoder, DefaultEncoder
17
+ from querysource.utils.functions import format_date
18
+ from .tasks import task_state, execute_task, launch_task
19
+ from ...exceptions import (
20
+ NotSupported,
21
+ ComponentError,
22
+ TaskNotFound,
23
+ TaskDefinition,
24
+ TaskFailed,
25
+ FileError,
26
+ FileNotFound,
27
+ )
28
+
29
+
30
+ def is_boolean(value: str) -> bool:
31
+ if isinstance(value, bool):
32
+ return value
33
+ try:
34
+ return ast.literal_eval(value)
35
+ except ValueError:
36
+ return False
37
+
38
+
39
+ class TaskManager(DataView):
40
+ async def get(self):
41
+ """
42
+ GET Method.
43
+ ---
44
+ description: get all tasks, or a task by ID (or get status of execution)
45
+ tags:
46
+ - tasks
47
+ - DataIntegration
48
+ consumes:
49
+ - application/json
50
+ produces:
51
+ - application/json
52
+ responses:
53
+ "200":
54
+ description: Existing Task was retrieved.
55
+ "403":
56
+ description: Forbidden Call
57
+ "404":
58
+ description: No Task(s) were found
59
+ "406":
60
+ description: Query Error
61
+ """
62
+ try:
63
+ sql = "SELECT * FROM {program}.tasks"
64
+ await self.connect(self.request)
65
+ params = self.get_args()
66
+ print(params, sql)
67
+ # try:
68
+ # session = self.request['session']
69
+ # except KeyError:
70
+ # return self.error(request=self.request, response="Unknown User", state=403)
71
+ try:
72
+ program = params["program"]
73
+ except KeyError:
74
+ program = "troc"
75
+ try:
76
+ task = params["task_id"]
77
+ except KeyError:
78
+ task = None
79
+ sql = sql.format(program=program)
80
+ print(sql)
81
+ if task is not None:
82
+ sql = "{sql} WHERE task = '{id}' AND enabled = true".format(
83
+ sql=sql, id=task
84
+ )
85
+ print("SQL IS ", sql)
86
+ try:
87
+ result = await self.query(sql)
88
+ except Exception as e:
89
+ msg = {"error": str(e), "exception": str(e.__class__)}
90
+ return self.error(
91
+ request=self.request, response=msg, exception=e, state=400
92
+ )
93
+ if result:
94
+ data = []
95
+ for row in result:
96
+ data.append(dict(row))
97
+ for elements in data:
98
+ for key, value in elements.items():
99
+ elements[key] = (
100
+ str(value)
101
+ if isinstance(
102
+ value, (UUID, datetime.time, datetime.datetime)
103
+ )
104
+ else value
105
+ )
106
+ headers = {"X-STATUS": "OK", "X-MESSAGE": "Tasks List"}
107
+ return self.json_response(response=data, headers=headers)
108
+ else:
109
+ if self._lasterr:
110
+ msg = {"error": str(self._lasterr)}
111
+ return self.error(
112
+ request=self.request,
113
+ response=msg,
114
+ exception=self._lasterr,
115
+ state=400,
116
+ )
117
+ headers = {"X-STATUS": "EMPTY", "X-MESSAGE": "Data not Found"}
118
+ return self.no_content(headers=headers)
119
+ except Exception as e:
120
+ print(e)
121
+ return self.critical(self.request, e)
122
+ finally:
123
+ await self.close()
124
+
125
+ async def post(self):
126
+ """
127
+ POST Method.
128
+ description: inserting or updating a Task or executing a Task
129
+ tags:
130
+ - tasks
131
+ - DataIntegration
132
+ consumes:
133
+ - application/json
134
+ produces:
135
+ - application/json
136
+ responses:
137
+ "200":
138
+ description: Existing Task was updated or executed.
139
+ "201":
140
+ description: New Task was inserted
141
+ "202":
142
+ description: Task was accepted to run
143
+ "400":
144
+ description: Task Failed to execute
145
+ "403":
146
+ description: Forbidden Call
147
+ "404":
148
+ description: No Data was found
149
+ "406":
150
+ description: Query Error
151
+ "409":
152
+ description: Conflict, a constraint was violated
153
+ """
154
+ # using LOCATION header to return the URL of the API
155
+ await self.connect(self.request)
156
+ # get the URL parameters
157
+ params = self.get_args()
158
+ # get post Data
159
+ data = await self.post_data()
160
+ # long
161
+ longrunner = False
162
+ try:
163
+ program = params["program"]
164
+ del params["program"]
165
+ except KeyError:
166
+ # we need a program
167
+ try:
168
+ program = data["program"]
169
+ except KeyError:
170
+ headers = {
171
+ "X-STATUS": "Error",
172
+ "X-MESSAGE": "Resource Error: We need a Program Name",
173
+ }
174
+ msg = {
175
+ "state": "Failed",
176
+ "message": "Error: we need a program name",
177
+ "status": 400,
178
+ }
179
+ return self.error(
180
+ request=self.request, response=msg, headers=headers, state=400
181
+ )
182
+ try:
183
+ task_id = params["task_id"]
184
+ del params["task_id"]
185
+ except KeyError:
186
+ # we need a Task ID
187
+ try:
188
+ task_id = data["task_id"]
189
+ except KeyError:
190
+ headers = {
191
+ "X-STATUS": "Error",
192
+ "X-MESSAGE": "Resource Error: We need a Task Name",
193
+ }
194
+ msg = {
195
+ "state": "Failed",
196
+ "message": "Error: we need a Task ID",
197
+ "status": 400,
198
+ }
199
+ return self.error(
200
+ request=self.request, response=msg, headers=headers, state=400
201
+ )
202
+ try:
203
+ try:
204
+ longrunner = is_boolean(data["long_running"])
205
+ del data["long_running"]
206
+ except KeyError:
207
+ try:
208
+ longrunner = is_boolean(params["long_running"])
209
+ del params["long_running"]
210
+ except KeyError:
211
+ longrunner = False
212
+ try:
213
+ no_worker = is_boolean(data["no_worker"])
214
+ del data["no_worker"]
215
+ except KeyError:
216
+ no_worker = False
217
+ logging.debug(f"Long Runner: {longrunner}, No Worker: {no_worker}")
218
+ # cannot update or insert a Task, we need to Run that task
219
+ status = None
220
+ result = {}
221
+ try:
222
+ # TODO: passing arguments via URL to the task
223
+ args = {}
224
+ if isinstance(params, dict):
225
+ args = params
226
+ if data:
227
+ args = {**args, **data}
228
+ task_uuid = uuid.uuid4()
229
+ status, action, result = await launch_task(
230
+ program_slug=program,
231
+ task_id=task_id,
232
+ loop=self._loop,
233
+ task_uuid=task_uuid,
234
+ queued=longrunner,
235
+ no_worker=no_worker,
236
+ **args,
237
+ )
238
+ result = {"task": f"{program}.{task_id}", "task_execution": task_uuid}
239
+ if action == "Executed":
240
+ state = 200
241
+ else:
242
+ state = 202
243
+ response = {
244
+ "state": state,
245
+ "message": "Task {}.{} was {}".format(program, task_id, action),
246
+ **result,
247
+ }
248
+ headers = {
249
+ "X-STATUS": "Task OK",
250
+ "X-MESSAGE": "Execution of Task {}.{} on {}".format(
251
+ program, task_id, action
252
+ ),
253
+ }
254
+ return self.json_response(
255
+ response=response,
256
+ headers=headers,
257
+ state=response["state"],
258
+ cls=BaseEncoder,
259
+ )
260
+ except TaskNotFound as err:
261
+ error = "Error: on Task {}.{}".format(program, task_id)
262
+ msg = {"message": error}
263
+ return self.error(
264
+ request=self.request, response=msg, exception=err, state=401
265
+ )
266
+ except TaskFailed as err:
267
+ print(err)
268
+ error = "Error: Task {} Failed".format(task_id)
269
+ msg = {"message": error}
270
+ return self.error(
271
+ request=self.request, response=msg, exception=err, state=400
272
+ )
273
+ except (FileNotFound, FileError) as err:
274
+ print(err)
275
+ error = "Error on Task {} File Not Found: {}".format(task_id, str(err))
276
+ msg = {"message": error}
277
+ return self.error(
278
+ request=self.request, response=msg, exception=err, state=404
279
+ )
280
+ except Exception as err:
281
+ print(err)
282
+ return self.critical(request=self.request, exception=err, state=500)
283
+ headers = {"X-STATUS": "EMPTY", "X-MESSAGE": "Data not Found"}
284
+ return self.no_content(headers=headers)
285
+ except Exception as e:
286
+ print(f"Generic Error on POST Method: {e}")
287
+ return self.critical(self.request, e)
288
+ finally:
289
+ await self.close()
290
+
291
+ async def put(self):
292
+ """
293
+ PUT Method.
294
+ description: inserting or updating a Task
295
+ tags:
296
+ - tasks
297
+ - DataIntegration
298
+ produces:
299
+ - application/json
300
+ consumes:
301
+ - application/merge-patch+json
302
+ - application/json
303
+ responses:
304
+ "200":
305
+ description: Existing Task was updated.
306
+ "201":
307
+ description: New Task was inserted
308
+ "204":
309
+ description: success execution but no content on return (resource was deleted)
310
+ "400":
311
+ description: Invalid resource according data schema
312
+ "403":
313
+ description: Forbidden Call
314
+ "404":
315
+ description: No Data was found
316
+ "406":
317
+ description: Query Error
318
+ "409":
319
+ description: Conflict, a constraint was violated
320
+ """
321
+ pass
322
+
323
+ async def delete(self):
324
+ """
325
+ DELETE Method.
326
+ description: remove resource.
327
+ tags:
328
+ - tasks
329
+ - DataIntegration
330
+ produces:
331
+ - application/json
332
+ responses:
333
+ "200":
334
+ description: Existing Task was updated.
335
+ "201":
336
+ description: New Task was inserted
337
+ "403":
338
+ description: Forbidden Call
339
+ "404":
340
+ description: No Data was found
341
+ "406":
342
+ description: Query Error
343
+ "409":
344
+ description: Conflict, a constraint was violated
345
+ """
346
+ pass
347
+
348
+ async def patch(self):
349
+ """
350
+ PATCH Method.
351
+ description: updating partially info about a Task
352
+ tags:
353
+ - tasks
354
+ - DataIntegration
355
+ produces:
356
+ - application/json
357
+ responses:
358
+ "200":
359
+ description: Existing Task was updated.
360
+ "201":
361
+ description: New Task was inserted
362
+ "304":
363
+ description: Task not modified, its currently the actual version of Task
364
+ "403":
365
+ description: Forbidden Call
366
+ "404":
367
+ description: No Data was found
368
+ "406":
369
+ description: Query Error
370
+ "409":
371
+ description: Conflict, a constraint was violated
372
+ """
373
+ pass
374
+
375
+ async def head(self):
376
+ pass
@@ -0,0 +1,155 @@
1
+ from typing import Union
2
+ import asyncio
3
+ from concurrent.futures import ThreadPoolExecutor
4
+ import jsonpickle
5
+ import pandas as pd
6
+ from navconfig import config as ENV
7
+ from navconfig.logging import logging
8
+
9
+ # Queue Worker Client:
10
+ from qw.client import QClient
11
+ from qw.wrappers import TaskWrapper
12
+ from ...conf import DEBUG, WORKER_LIST, WORKER_HIGH_LIST
13
+ from ...exceptions import (
14
+ NotSupported,
15
+ TaskNotFound,
16
+ TaskFailed,
17
+ FileError,
18
+ FileNotFound,
19
+ DataNotFound,
20
+ )
21
+ from ...tasks.task import Task
22
+
23
+
24
+ if WORKER_LIST:
25
+ QW = QClient(worker_list=WORKER_LIST)
26
+ QW_high = QClient(worker_list=WORKER_HIGH_LIST)
27
+ else:
28
+ QW = QClient() # auto-discovering of workers
29
+ QW_high = QW
30
+
31
+
32
+ async def launch_task(
33
+ program_slug: str,
34
+ task_id: str,
35
+ loop: asyncio.AbstractEventLoop = None,
36
+ task_uuid: str = None,
37
+ queued: bool = False,
38
+ no_worker: bool = False,
39
+ priority: str = "low",
40
+ userid: Union[int, str] = None,
41
+ **kwargs,
42
+ ):
43
+ """launch_task.
44
+ Runs (or queued) a Task from Task Monitor.
45
+ """
46
+ state = None
47
+ result = {}
48
+
49
+ if no_worker is True:
50
+ # Running task in Local
51
+ print(f"RUNNING TASK {program_slug}.{task_id}")
52
+ task = Task(
53
+ task=task_id,
54
+ program=program_slug,
55
+ loop=loop,
56
+ ignore_results=False,
57
+ ENV=ENV,
58
+ debug=DEBUG,
59
+ userid=userid,
60
+ **kwargs,
61
+ )
62
+ try:
63
+ state = await task.start()
64
+ if not state:
65
+ logging.warning(
66
+ f"Task {program_slug}.{task_id} return False on Start Time."
67
+ )
68
+ except Exception as err:
69
+ logging.error(err)
70
+ raise
71
+ try:
72
+ state = await task.run()
73
+ try:
74
+ result["stats"] = task.stats.stats
75
+ except Exception as err:
76
+ result["stats"] = None
77
+ result["error"] = err
78
+ ### gettting the result of Task execution
79
+ if isinstance(state, pd.DataFrame):
80
+ numrows = len(state.index)
81
+ columns = list(state.columns)
82
+ num_cols = len(columns)
83
+ state = {
84
+ "type": "Dataframe",
85
+ "numrows": numrows,
86
+ "columns": columns,
87
+ "num_cols": num_cols,
88
+ }
89
+ else:
90
+ state = f"{state!r}"
91
+ result["result"] = state
92
+ return (state, "Executed", result)
93
+ except DataNotFound as err:
94
+ raise
95
+ except NotSupported as err:
96
+ raise
97
+ except TaskNotFound as err:
98
+ raise TaskNotFound(f"Task: {task_id}: {err}") from err
99
+ except TaskFailed as err:
100
+ raise TaskFailed(f"Task {task_id} failed: {err}") from err
101
+ except FileNotFound:
102
+ raise
103
+ except FileError as err:
104
+ raise FileError(f"Task {task_id}, File Not Found error: {err}") from err
105
+ except Exception as err:
106
+ raise TaskFailed(f"Error: Task {task_id} failed: {err}") from err
107
+ finally:
108
+ await task.close()
109
+ else:
110
+ if queued:
111
+ action = "Queued"
112
+ else:
113
+ action = "Dispatched"
114
+ # Task:
115
+ task = TaskWrapper(
116
+ program=program_slug, task=task_id, ignore_results=True, userid=userid, **kwargs
117
+ )
118
+ ### TODO: Add Publish into Broker
119
+ if action == "Queued":
120
+ if priority == "high":
121
+ result = await asyncio.wait_for(QW_high.queue(task), timeout=10)
122
+ else:
123
+ result = await asyncio.wait_for(QW.queue(task), timeout=10)
124
+ try:
125
+ result["message"] = result["message"].decode("utf-8")
126
+ except (TypeError, KeyError):
127
+ result["message"] = None
128
+ print(f"Task Queued: {result!s}")
129
+ return (task_uuid, action, result)
130
+ else:
131
+ try:
132
+ if priority == "high":
133
+ result = await QW_high.run(task)
134
+ else:
135
+ result = await QW.run(task)
136
+ if isinstance(result, str):
137
+ # check if can we unserialize the jsonpickle
138
+ try:
139
+ result = jsonpickle.decode(result)
140
+ except (TypeError, KeyError, ValueError, AttributeError) as ex:
141
+ result = {"message": result, "error": ex}
142
+ logging.debug(f"Executed Task: {result!s}")
143
+ try:
144
+ result["message"] = result["message"].decode("utf-8")
145
+ except (TypeError, KeyError):
146
+ result["message"] = None
147
+ except AttributeError:
148
+ pass
149
+ return (task_uuid, action, result)
150
+ except (NotSupported, TaskNotFound, TaskFailed, FileNotFound, FileError) as ex:
151
+ logging.error(ex)
152
+ raise
153
+ except Exception as exc:
154
+ logging.error(exc)
155
+ raise TaskFailed(f"Error: Task {task_id} failed: {exc}") from exc
@@ -0,0 +1,16 @@
1
+ """
2
+ Storages.
3
+
4
+ Storages covering the ways to store the data processed by the tasks and the task/hooks definitions.
5
+
6
+ FileStore: how Flowtask can store files in the filesystem.
7
+ TaskStorage: how Flowtask can store the task definitions (yaml, json files).
8
+ """
9
+ from .files import FileStore
10
+ from .tasks import (
11
+ FileTaskStorage,
12
+ RowTaskStorage,
13
+ MemoryTaskStorage,
14
+ DatabaseTaskStorage,
15
+ GitTaskStorage
16
+ )
@@ -0,0 +1,12 @@
1
+ """
2
+ Storage Exceptions.
3
+
4
+ This module provides the exceptions for the Storages.
5
+ """
6
+
7
+
8
+ class StoreError(Exception):
9
+ """
10
+ Base Exception Triggered for all Storages.
11
+ """
12
+ pass
@@ -0,0 +1,8 @@
1
+ """File Store.
2
+
3
+ Used to save files downloaded/created by tasks to a File Store.
4
+ """
5
+ from .filesystem import FileStore
6
+
7
+
8
+ __all__ = ("FileStore",)
@@ -0,0 +1,29 @@
1
+ from typing import Any
2
+ from abc import ABC, abstractmethod
3
+ from navconfig import DEBUG
4
+ from navconfig.logging import logging
5
+ from ..exceptions import StoreError
6
+
7
+
8
+ class AbstractStore(ABC):
9
+ """Abstract class for File Store."""
10
+
11
+ def __init__(self, *args, **kwargs) -> None:
12
+ self._name = self.__class__.__name__
13
+ self._program: Any = kwargs.pop("program", None)
14
+ self.logger = logging.getLogger(f"FlowTask.Files.{self._name}")
15
+ if DEBUG is True:
16
+ self.logger.notice(f":: Starting Store {self._name}")
17
+ self.kwargs = kwargs
18
+ self.args = args
19
+
20
+ def set_program(self, program: str) -> None:
21
+ self._program = program
22
+
23
+ @abstractmethod
24
+ def default_directory(self, directory: str):
25
+ pass
26
+
27
+ @abstractmethod
28
+ def get_directory(self, directory: str):
29
+ pass
@@ -0,0 +1,66 @@
1
+ from typing import Union, Optional
2
+ from pathlib import Path, PurePath
3
+ from .abstract import AbstractStore
4
+ from ..exceptions import StoreError
5
+ from ...exceptions import FileNotFound
6
+
7
+
8
+ class FileStore(AbstractStore):
9
+ """
10
+ FileStore: Saving files in local filesystem.
11
+ """
12
+
13
+ def __init__(
14
+ self, path: Union[str, PurePath], prefix: str, *args, **kwargs
15
+ ) -> None:
16
+ if isinstance(path, str):
17
+ path = Path(path)
18
+ if path.exists() and path.is_dir():
19
+ self.path: PurePath = path
20
+ else:
21
+ raise StoreError(
22
+ f"FileStore: directory doesn't exists: {path}"
23
+ )
24
+ self._prefix: str = prefix
25
+ super().__init__(*args, **kwargs)
26
+
27
+ def default_directory(self, directory: str):
28
+ return self.path.joinpath(self._program, self._prefix, directory)
29
+
30
+ def get_directory(self, directory: str, program: Optional[str] = None):
31
+ if not program:
32
+ program = self._program
33
+ if isinstance(directory, PurePath):
34
+ _dir = directory
35
+ if ":" in directory:
36
+ # relative directory to Storage:
37
+ _dir = self.path.joinpath(
38
+ program, self._prefix, directory.rsplit(":", 1)[1]
39
+ )
40
+ elif ".." in directory:
41
+ # relative directory to base directory:
42
+ _dir = self.path.joinpath(directory)
43
+ else:
44
+ _dir = Path(directory)
45
+ # If not relative, try to use as is:
46
+ if not _dir.is_absolute() or not _dir.exists():
47
+ # Try to use instead base directory:
48
+ _dir = self.path.joinpath(
49
+ program,
50
+ self._prefix,
51
+ directory
52
+ )
53
+ elif not _dir.exists():
54
+ _dir = Path(directory).resolve()
55
+ if _dir.exists() and _dir.is_dir():
56
+ self.logger.debug(
57
+ f"Directory: {_dir}"
58
+ )
59
+ return _dir
60
+ else:
61
+ self.logger.error(
62
+ f"Path doesn't exists: {_dir}"
63
+ )
64
+ raise FileNotFound(
65
+ f"Path doesn't exists: {_dir}"
66
+ )
@@ -0,0 +1,19 @@
1
+ """
2
+ Task Storage.
3
+
4
+ Saving Tasks on different Storages (Filesystem, S3 buckets, databases, etc)
5
+ """
6
+
7
+ from .filesystem import FileTaskStorage
8
+ from .database import DatabaseTaskStorage
9
+ from .row import RowTaskStorage
10
+ from .github import GitTaskStorage
11
+ from .memory import MemoryTaskStorage
12
+
13
+ __all__ = (
14
+ "FileTaskStorage",
15
+ "DatabaseTaskStorage",
16
+ "RowTaskStorage",
17
+ "GitTaskStorage",
18
+ "MemoryTaskStorage",
19
+ )