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,124 @@
1
+ import asyncio
2
+ from datetime import datetime
3
+ import traceback
4
+ import socket
5
+ from asyncdb import AsyncDB
6
+ from ...conf import (
7
+ ENVIRONMENT,
8
+ TASK_EXEC_BACKEND,
9
+ TASK_EXEC_CREDENTIALS,
10
+ TASK_EVENT_TABLE,
11
+ INFLUX_DATABASE,
12
+ TASK_EXEC_TABLE,
13
+ USE_TASK_EVENT,
14
+ )
15
+ from ...utils.json import json_encoder
16
+ from .abstract import AbstractEvent
17
+
18
+ EVENT_HOST = socket.gethostbyname(socket.gethostname())
19
+
20
+
21
+ class LogExecution(AbstractEvent):
22
+ """LogExecution.
23
+
24
+ Log the execution of a Task into a InfluxDB measurement bucket.
25
+ """
26
+
27
+ def get_influx(self):
28
+ return AsyncDB(
29
+ TASK_EXEC_BACKEND,
30
+ params=TASK_EXEC_CREDENTIALS,
31
+ loop=asyncio.get_event_loop(),
32
+ )
33
+
34
+ async def __call__(self, *args, **kwargs):
35
+ status = kwargs.pop("status", "event")
36
+ task = kwargs.pop("task", None)
37
+ cls = kwargs.pop("cls", None)
38
+ msg = kwargs.pop("message", str(cls))
39
+ if self.disable_notification is True:
40
+ return
41
+ if USE_TASK_EVENT is True:
42
+ try:
43
+ task_id = task.task_id
44
+ task_name = task.taskname
45
+ program = task.getProgram()
46
+ except (AttributeError, TypeError):
47
+ task_id = None
48
+ task_name = None
49
+ program = None
50
+ async with await self.get_influx().connection() as conn:
51
+ try:
52
+ # saving the log into metric database:
53
+ start_time = datetime.utcnow()
54
+ data = {
55
+ "measurement": TASK_EXEC_TABLE,
56
+ "location": ENVIRONMENT,
57
+ "timestamp": start_time,
58
+ "fields": {"status": status},
59
+ "tags": {
60
+ "host": EVENT_HOST,
61
+ "region": ENVIRONMENT,
62
+ "start_time": start_time,
63
+ "tenant": program,
64
+ "task": task_name,
65
+ "task_id": str(task_id),
66
+ "message": msg,
67
+ "traceback": str(traceback.format_exc()),
68
+ },
69
+ }
70
+ await conn.write(data, bucket=INFLUX_DATABASE)
71
+ except Exception as e:
72
+ self._logger.error(f"Flowtask: Error saving Task Execution: {e}")
73
+
74
+
75
+ class SaveExecution(LogExecution):
76
+ async def __call__(self, *args, **kwargs):
77
+ status = kwargs.pop("status", "event")
78
+ task = kwargs.pop("task", None)
79
+ cls = kwargs.pop("error", None)
80
+ err = getattr(cls, "message", str(cls))
81
+ msg = kwargs.pop("message", err)
82
+ if self.disable_notification is True:
83
+ return
84
+ if USE_TASK_EVENT is True:
85
+ try:
86
+ stat = task.stats # getting the stat object:
87
+ except AttributeError:
88
+ stats = None
89
+ if stat:
90
+ stats = json_encoder(stat.to_json())
91
+ start_time = stat.start_time
92
+ end_time = stat.finish_time
93
+ duration = stat.duration
94
+ else:
95
+ stats = {}
96
+ start_time = None
97
+ end_time = datetime.utcnow()
98
+ duration = None
99
+ async with await self.get_influx().connection() as conn:
100
+ try:
101
+ data = {
102
+ "measurement": TASK_EVENT_TABLE,
103
+ "location": ENVIRONMENT,
104
+ "timestamp": end_time,
105
+ "fields": {"status": status},
106
+ "tags": {
107
+ "host": EVENT_HOST,
108
+ "region": ENVIRONMENT,
109
+ "stats": stats,
110
+ "start_time": start_time,
111
+ "finish_time": end_time,
112
+ "duration": duration,
113
+ "tenant": task.getProgram(),
114
+ "task": task.taskname,
115
+ "id": task.task_id,
116
+ "traceback": traceback.format_exc(),
117
+ "message": msg,
118
+ },
119
+ }
120
+ await conn.write(data, bucket=INFLUX_DATABASE)
121
+ except Exception as e:
122
+ self._logger.error(
123
+ f"FlowTask: Error saving Task Execution: {e}"
124
+ )
@@ -0,0 +1,7 @@
1
+ from .delete import FileDelete
2
+ from .copy import FileCopy
3
+
4
+ __all__ = (
5
+ "FileDelete",
6
+ "FileCopy",
7
+ )
@@ -0,0 +1,51 @@
1
+ from abc import ABC
2
+ import glob
3
+ from pathlib import Path, PurePath
4
+ from ..abstract import AbstractEvent
5
+
6
+
7
+ class FileBase(AbstractEvent, ABC):
8
+ def __init__(self, *args, **kwargs):
9
+ self._filenames: list[PurePath] = []
10
+ super(FileBase, self).__init__(*args, **kwargs)
11
+
12
+ def start(self):
13
+ if hasattr(self, "directory"):
14
+ d = self.mask_replacement(
15
+ self.directory # pylint: disable=E0203
16
+ ) # pylint: disable=access-member-before-definition
17
+ p = Path(d) # pylint: disable=E0203
18
+ if p.exists() and p.is_dir():
19
+ self.directory = p
20
+ else:
21
+ self._logger.error(f"Path doesn't exists: {self.directory}")
22
+ if hasattr(self, "destination"):
23
+ d = self.mask_replacement(
24
+ self.destination # pylint: disable=E0203
25
+ ) # pylint: disable=access-member-before-definition
26
+ p = Path(d) # pylint: disable=E0203
27
+ if p.exists() and p.is_dir():
28
+ self.destination = p
29
+ else:
30
+ if hasattr(self, "create_destination"):
31
+ self.destination.mkdir(parents=True, exist_ok=True)
32
+ else:
33
+ self._logger.error(
34
+ f"Destination Path doesn't exists: {self.directory}"
35
+ )
36
+ if hasattr(self, "filename"):
37
+ if isinstance(self.filename, list):
38
+ for file in self.filename:
39
+ fname = self.mask_replacement(file)
40
+ self._filenames.append(self.directory.joinpath(fname))
41
+ elif isinstance(self.filename, PurePath):
42
+ self._filenames.append(self.filename)
43
+ elif isinstance(self.filename, str):
44
+ if "*" in self.filename:
45
+ path = self.directory.joinpath(self.filename)
46
+ listing = glob.glob(str(path)) # TODO using glob from pathlib
47
+ for fname in listing:
48
+ self._filenames.append(Path(fname))
49
+ else:
50
+ fname = self.mask_replacement(self.filename)
51
+ self._filenames.append(self.directory.joinpath(fname))
@@ -0,0 +1,23 @@
1
+ import shutil
2
+ from .base import FileBase
3
+
4
+
5
+ class FileCopy(FileBase):
6
+ def __init__(self, *args, **kwargs):
7
+ self.move = kwargs.pop("move", False)
8
+ super(FileCopy, self).__init__(*args, **kwargs)
9
+
10
+ async def __call__(self, *args, **kwargs):
11
+ self.start()
12
+ for src in self._filenames:
13
+ dest = self.destination.joinpath(src.name)
14
+ if self.move:
15
+ shutil.move(src, dest)
16
+ # self._logger.info(
17
+ # f"Moved file {src} to {dest}"
18
+ # )
19
+ else:
20
+ shutil.copy2(src, dest)
21
+ # self._logger.info(
22
+ # f"Copied file {src} to {dest}"
23
+ # )
@@ -0,0 +1,16 @@
1
+ from .base import FileBase
2
+
3
+
4
+ class FileDelete(FileBase):
5
+ async def __call__(self, *args, **kwargs):
6
+ self.start()
7
+ for filename in self._filenames:
8
+ if filename.exists() and filename.is_file():
9
+ try:
10
+ filename.unlink()
11
+ except Exception as e:
12
+ self._logger.error(f"Error deleting {filename}: {e}")
13
+ else:
14
+ self._logger.warning(
15
+ f"{filename} does not exist or is not a file."
16
+ )
@@ -0,0 +1,9 @@
1
+ from .credentials import CredentialsInterface
2
+ from .client import ClientInterface
3
+ from .notifications import Notification
4
+
5
+ __all__ = (
6
+ "ClientInterface",
7
+ "CredentialsInterface",
8
+ "Notification",
9
+ )
@@ -0,0 +1,67 @@
1
+ from abc import abstractmethod
2
+ from collections.abc import Callable
3
+ from typing import TypeVar
4
+ from typing_extensions import ParamSpec
5
+ from tqdm import tqdm
6
+ from navconfig.logging import logging
7
+ from .credentials import CredentialsInterface
8
+
9
+ P = ParamSpec("P")
10
+ T = TypeVar("T")
11
+
12
+
13
+ class ClientInterface(CredentialsInterface):
14
+ def __init__(self, *args: P.args, **kwargs: P.kwargs) -> None:
15
+ super(ClientInterface, self).__init__(*args, **kwargs)
16
+ # host and port (if needed)
17
+ self.host: str = kwargs.pop("host", None)
18
+ if not self.host:
19
+ self.host = kwargs.pop("hostname", None)
20
+ self.port: int = kwargs.pop("port", None)
21
+ self.define_host()
22
+ self._connection: Callable = None
23
+ # progress bar
24
+ self._pb: Callable = None
25
+ # any other argument
26
+ self._clientargs = {} # kwargs
27
+
28
+ def define_host(self):
29
+ try:
30
+ self.host = self.credentials["host"]
31
+ except KeyError:
32
+ self.host = self.host
33
+ try:
34
+ self.port = self.credentials["port"]
35
+ except KeyError:
36
+ self.port = self.port
37
+ # getting from environment:
38
+ self.host = self.get_env_value(self.host, default=self.host)
39
+ self.port = self.get_env_value(str(self.port), default=self.port)
40
+ if self.host:
41
+ logging.debug(f"<{__name__}>: HOST: {self.host}, PORT: {self.port}")
42
+
43
+ @abstractmethod
44
+ async def close(self, timeout: int = 5):
45
+ """close.
46
+ Closing the connection.
47
+ """
48
+
49
+ @abstractmethod
50
+ async def open(self, credentials: dict, **kwargs):
51
+ """open.
52
+ Starts (open) a connection to an external resource.
53
+ """
54
+
55
+ async def __aenter__(self) -> "ClientInterface":
56
+ await self.open(credentials=self.credentials, **self._clientargs)
57
+ return self
58
+
59
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
60
+ # clean up anything you need to clean up
61
+ return await self.close(timeout=1)
62
+
63
+ def start_progress(self, total: int = 1):
64
+ self._pb = tqdm(total=total)
65
+
66
+ def close_progress(self):
67
+ self._pb.close()
@@ -0,0 +1,28 @@
1
+ from abc import ABC
2
+ from typing import TypeVar
3
+ from typing_extensions import ParamSpec
4
+ from ....interfaces.mask import MaskSupport
5
+
6
+ P = ParamSpec("P")
7
+ T = TypeVar("T")
8
+
9
+
10
+ class CredentialsInterface(MaskSupport, ABC):
11
+ def __init__(self, *args: P.args, **kwargs: P.kwargs) -> None:
12
+ super(CredentialsInterface, self).__init__(*args, **kwargs)
13
+ self.credentials = self.set_credentials(kwargs.pop("credentials", {}))
14
+ if not self.credentials:
15
+ raise ValueError("Missing Credentials on Event Component")
16
+
17
+ def set_credentials(self, credentials: dict):
18
+ for key, default in credentials.items():
19
+ try:
20
+ # can process the credentials, extracted from environment or variables:
21
+ val = self.get_env_value(credentials[key], default=default)
22
+ if hasattr(self, "mask_replacement"):
23
+ val = self.mask_replacement(val)
24
+ credentials[key] = val
25
+ except (TypeError, KeyError) as ex:
26
+ self._logger.error(f"{__name__}: Wrong or missing Credentias")
27
+ raise ValueError(f"{__name__}: Wrong or missing Credentias") from ex
28
+ return credentials
@@ -0,0 +1,58 @@
1
+ from abc import ABC
2
+ from notify import Notify
3
+ from notify.providers.email import Email
4
+ from notify.providers.slack import Slack
5
+ from notify.providers.teams import Teams
6
+ from notify.models import Actor, Chat, Channel, TeamsChannel
7
+ from notify.conf import MS_TEAMS_DEFAULT_TEAMS_ID
8
+ from flowtask.conf import (
9
+ EVENT_CHAT_ID,
10
+ EVENT_CHAT_BOT,
11
+ DEFAULT_RECIPIENT,
12
+ EMAIL_USERNAME,
13
+ EMAIL_PASSWORD,
14
+ EMAIL_PORT,
15
+ EMAIL_HOST,
16
+ SLACK_DEFAULT_CHANNEL,
17
+ SLACK_DEFAULT_CHANNEL_NAME,
18
+ MS_TEAMS_NAVIGATOR_CHANNEL,
19
+ MS_TEAMS_NAVIGATOR_CHANNEL_ID,
20
+ )
21
+
22
+
23
+ class Notification(ABC):
24
+ def get_notify(self, _type, **kwargs):
25
+ if _type == "telegram":
26
+ # defining the Default chat object:
27
+ recipient = Chat(**{"chat_id": EVENT_CHAT_ID, "chat_name": "Navigator"})
28
+ # send notifications to Telegram bot
29
+ args = {"bot_token": EVENT_CHAT_BOT, **kwargs}
30
+ ntf = Notify("telegram", **args)
31
+ elif _type == "slack":
32
+ recipient = Channel(
33
+ channel_id=SLACK_DEFAULT_CHANNEL,
34
+ channel_name=SLACK_DEFAULT_CHANNEL_NAME,
35
+ )
36
+ ntf = Slack()
37
+ elif _type == "email":
38
+ account = {
39
+ "host": EMAIL_HOST,
40
+ "port": EMAIL_PORT,
41
+ "username": EMAIL_USERNAME,
42
+ "password": EMAIL_PASSWORD,
43
+ **kwargs,
44
+ }
45
+ recipient = Actor(**DEFAULT_RECIPIENT)
46
+ ntf = Email(debug=True, **account)
47
+ elif _type == "teams":
48
+ ntf = Teams(as_user=True)
49
+ recipient = TeamsChannel(
50
+ name=MS_TEAMS_NAVIGATOR_CHANNEL,
51
+ team_id=MS_TEAMS_DEFAULT_TEAMS_ID,
52
+ channel_id=MS_TEAMS_NAVIGATOR_CHANNEL_ID,
53
+ )
54
+ else:
55
+ # Any other Notify Provider:
56
+ recipient = Actor(**DEFAULT_RECIPIENT)
57
+ ntf = Notify(_type, **kwargs)
58
+ return [ntf, recipient]
@@ -0,0 +1,122 @@
1
+ import codecs
2
+ import traceback
3
+ from jira import JIRA
4
+ import orjson
5
+ from ...utils.json import json_encoder
6
+ from .abstract import AbstractEvent
7
+ from ...conf import (
8
+ JIRA_API_TOKEN,
9
+ JIRA_USERNAME,
10
+ JIRA_INSTANCE,
11
+ JIRA_PROJECT
12
+ )
13
+
14
+
15
+ class Jira(AbstractEvent):
16
+ """Jira.
17
+
18
+ Jira Event to create a new Ticket on Error/Exception.
19
+ """
20
+ def __init__(self, *args, **kwargs):
21
+ super(Jira, self).__init__(*args, **kwargs)
22
+ self.program = kwargs.pop("program", None)
23
+ self.task = kwargs.pop("task", None)
24
+ self.issue_type = kwargs.pop("issue_type", 'Bug')
25
+ self._status = kwargs.pop("status", "event")
26
+ self._summary = kwargs.get('summary', 'Error on: ')
27
+ self._assignee = kwargs.get('assignee', {})
28
+ # Initialize Jira Connection
29
+ try:
30
+ self.jira = JIRA(
31
+ server=JIRA_INSTANCE,
32
+ basic_auth=(JIRA_USERNAME, JIRA_API_TOKEN)
33
+ )
34
+ except Exception as err:
35
+ self._logger.error(
36
+ f"Cannot Connect to Jira {err}"
37
+ )
38
+ raise
39
+
40
+ async def __call__(self, *args, **kwargs):
41
+ project_id = kwargs.pop('project_id', JIRA_PROJECT)
42
+ _message = kwargs.get('message', '')
43
+ task = kwargs.pop("task", None)
44
+ status = kwargs.pop("status", "done")
45
+ program = task.getProgram()
46
+ task_name = f"{program}.{task.taskname}"
47
+ error = kwargs.get('error', None)
48
+ task_id = task.task_id
49
+ if status not in ("error", "failed", "exception", "task error"):
50
+ return True
51
+ # Operar el error
52
+ try:
53
+ stat = task.stats # getting the stat object:
54
+ stats = stat.to_json()
55
+ except AttributeError:
56
+ stats = []
57
+ description = {}
58
+ if stats:
59
+ # iterate over task stats:
60
+ for stat, value in stats["steps"].items():
61
+ description[stat] = value
62
+ # Create the Jira Ticket:
63
+ desc = orjson.dumps(description, option=orjson.OPT_INDENT_2).decode()
64
+ codereview = codecs.decode(json_encoder(stats['Review']), 'unicode_escape').replace("**", "*")
65
+ desc = f"""
66
+ {{code:json}}
67
+ {desc}
68
+ {{code}}\n\n
69
+ """
70
+ # Capture the stack trace
71
+ stack_trace = traceback.format_exc()
72
+ if stack_trace:
73
+ desc = f"""
74
+ {desc}
75
+
76
+ h2. *Error*:\n\n
77
+ {{panel:bgColor=#ffebe6}}\n
78
+ {error}
79
+ \n{{panel}}\n\n
80
+
81
+ h2. Stack Trace:\n\n
82
+ {{code:python}}
83
+ {stack_trace}
84
+ {{code}}
85
+ """
86
+ args = {
87
+ 'project': project_id,
88
+ 'summary': f"{self._summary} {task_name}",
89
+ 'description': (
90
+ f"{{color:#FF5630}}[ STATUS: {status.upper()} ]{{color}} \n\n"
91
+ f"{{panel:bgColor=#deebff}}\n*Task*: {task_name}\n{{panel}}\n\n"
92
+ f"{{panel:bgColor=#deebff}}\n*Task_id*: {task_id}\n{{panel}}\n\n"
93
+ f"{{panel:bgColor=#ffebe6}}\n*Message*: {_message}\n{{panel}}\n\n"
94
+ f"h2. *Task Stats*:\n\n"
95
+ f"{desc}"
96
+ f"\n\n----\n\n{{panel:bgColor=#eae6ff}}\nh2. *Code Review*\n\n{codereview}\n\n{{panel}}"
97
+ ),
98
+ 'issuetype': {
99
+ 'name': self.issue_type
100
+ }
101
+ }
102
+ try:
103
+ new_issue = self.jira.create_issue(**args)
104
+ self._logger.info(
105
+ f"Jira Issue Created: {new_issue}"
106
+ )
107
+ if self._assignee:
108
+ try:
109
+ new_issue.update(
110
+ assignee=self._assignee
111
+ )
112
+ except Exception as err:
113
+ print('ERROR > ', err)
114
+ self._logger.warning(
115
+ f"Error Assigning Jira Issue to {self._assignee}: {err}"
116
+ )
117
+ return new_issue
118
+ except Exception as err:
119
+ self._logger.error(
120
+ f"Cannot Create Jira Issue {err}"
121
+ )
122
+ raise
@@ -0,0 +1,26 @@
1
+ from navconfig import DEBUG
2
+ from navconfig.logging import logging
3
+ from .abstract import AbstractEvent
4
+
5
+
6
+ class LogEvent(AbstractEvent):
7
+ def __init__(self, *args, **kwargs):
8
+ super(LogEvent, self).__init__(*args, **kwargs)
9
+ self.use_notice: bool = kwargs.pop("use_notice", False)
10
+ self._logger = logging.getLogger(
11
+ "FlowTask.LogEvent"
12
+ )
13
+
14
+ async def __call__(self, *args, **kwargs):
15
+ msg = kwargs.pop("message", None)
16
+ cls = kwargs.pop("cls", None)
17
+ if not msg:
18
+ msg = getattr(cls, "message", str(cls))
19
+ if DEBUG:
20
+ self.echo(msg, level="WARN")
21
+ self._logger.debug(msg)
22
+ else:
23
+ if self.use_notice is True:
24
+ self._logger.notice(msg)
25
+ else:
26
+ self._logger.info(msg)
@@ -0,0 +1,52 @@
1
+ import socket
2
+ from datetime import datetime, timezone
3
+ from redis import asyncio as aioredis
4
+ from navconfig.logging import logging
5
+ from ...utils.json import json_encoder
6
+ from .abstract import AbstractEvent
7
+ from ...conf import ENVIRONMENT, PUBSUB_REDIS, ERROR_CHANNEL
8
+
9
+
10
+ EVENT_HOST = socket.gethostbyname(socket.gethostname())
11
+
12
+
13
+ class LogError(AbstractEvent):
14
+ def __init__(self, *args, **kwargs):
15
+ super(LogError, self).__init__(*args, **kwargs)
16
+ self._logger = logging.getLogger("FlowTask.LogError")
17
+
18
+ async def __call__(self, *args, **kwargs):
19
+ status = kwargs.pop("status", "event")
20
+ task = kwargs.pop("task", None)
21
+ program = task.getProgram()
22
+ task_name = task.taskname
23
+ task_id = task.task_id
24
+ msg = kwargs.pop("message", None)
25
+ cls = kwargs.pop("cls", None)
26
+ if not msg:
27
+ msg = getattr(cls, "message", str(cls))
28
+ redis = await aioredis.from_url(
29
+ PUBSUB_REDIS, encoding="utf-8", decode_responses=True
30
+ )
31
+ msg = {
32
+ "task": f"{program}.{task_name}",
33
+ "task_id": task_id,
34
+ "type": "error",
35
+ "status": status,
36
+ "environment": ENVIRONMENT,
37
+ "host": EVENT_HOST,
38
+ "end_time": datetime.now(timezone.utc),
39
+ }
40
+ message = json_encoder(msg)
41
+ try:
42
+ await redis.publish(ERROR_CHANNEL, message)
43
+ except Exception as e:
44
+ self._logger.warning(
45
+ f"Redis Publisher Error: {e}"
46
+ )
47
+ finally:
48
+ await redis.close()
49
+ try:
50
+ await redis.connection_pool.disconnect()
51
+ except Exception:
52
+ pass
@@ -0,0 +1,59 @@
1
+ from ...interfaces.notification import Notification
2
+ from ...exceptions import ActionError
3
+ from .abstract import AbstractEvent
4
+
5
+
6
+ class Notify(Notification, AbstractEvent):
7
+ async def __call__(self, *args, **kwargs):
8
+ default_message = self._kwargs.pop("message", None)
9
+ message = kwargs.pop("message", default_message)
10
+ # status = kwargs.pop('status', 'event')
11
+ task = kwargs.pop("task", None)
12
+ provider, recipient = self.get_notify(**self._kwargs)
13
+ # Mask transform of message
14
+ for key, value in self.message.items():
15
+ self.message[key] = self.mask_replacement(value)
16
+ ## TASK:
17
+ if self.provider == "email":
18
+ args = self.get_message(message)
19
+ if hasattr(self, "with_attachment") and self.with_attachment is True:
20
+ # check if result are files (build attachments)
21
+ _vars = task.get_variables()
22
+ if "FILENAMES" in _vars.keys():
23
+ result = _vars["FILENAMES"]
24
+ elif "FILENAME" in _vars.keys():
25
+ result = _vars["FILENAME"]
26
+ else:
27
+ result = kwargs.pop("result", [])
28
+ self.list_attachment = self.get_attachment_files(result)
29
+ elif self.provider == "telegram":
30
+ args = self.get_message(message)
31
+ if hasattr(self, "with_attachment") and self.with_attachment is True:
32
+ _vars = task.get_variables()
33
+ if "FILENAMES" in _vars.keys():
34
+ result = _vars["FILENAMES"]
35
+ elif "FILENAME" in _vars.keys():
36
+ result = _vars["FILENAME"]
37
+ else:
38
+ result = kwargs.pop("result", [])
39
+ self.list_attachment = self.get_attachment_files(result)
40
+ async with provider as notify:
41
+ result = await notify.send_document(
42
+ document=self.list_attachment[0],
43
+ caption=message,
44
+ disable_notification=True,
45
+ )
46
+ return result
47
+ else:
48
+ args = self.get_message(message)
49
+ if self._template:
50
+ args["template"] = self._template
51
+ try:
52
+ async with provider as notify:
53
+ args["recipient"] = recipient
54
+ if self.list_attachment:
55
+ args["attachments"] = self.list_attachment
56
+ result = await notify.send(**args)
57
+ self._logger.debug(f"Notification Status: {result}")
58
+ except Exception as err:
59
+ raise ActionError(f"Error Creating Notification App: {err}") from err