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,207 @@
1
+ import asyncio
2
+ from collections.abc import Callable
3
+ import math
4
+ import pandas as pd
5
+ from asyncdb import AsyncDB
6
+ from asyncdb.exceptions import (
7
+ StatementError,
8
+ DataError
9
+ )
10
+ from .CopyTo import CopyTo
11
+ from ..interfaces.dataframes import PandasDataframe
12
+ from ..exceptions import (
13
+ ComponentError,
14
+ DataNotFound
15
+ )
16
+ from ..conf import (
17
+ RT_DRIVER,
18
+ RT_HOST,
19
+ RT_PORT,
20
+ RT_USER,
21
+ RT_PASSWORD,
22
+ RT_DATABASE
23
+ )
24
+
25
+
26
+ class CopyToRethink(CopyTo, PandasDataframe):
27
+ """
28
+ CopyToRethink.
29
+
30
+ Overview
31
+
32
+ This component allows copy data into a RethinkDB table,
33
+ Copy into main rethinkdb using write functionality.
34
+
35
+ .. table:: Properties
36
+ :widths: auto
37
+
38
+
39
+ +--------------+----------+-----------+--------------------------------------------+
40
+ | Name | Required | Summary |
41
+ +--------------+----------+-----------+--------------------------------------------+
42
+ | tablename | Yes | Name of the table in |
43
+ | | | the database |
44
+ +--------------+----------+-----------+--------------------------------------------+
45
+ | schema | Yes | Name of the schema |
46
+ | | | where is to the table, alias: database |
47
+ +--------------+----------+-----------+--------------------------------------------+
48
+ | truncate | Yes | This option indicates if the component should empty |
49
+ | | | before coping the new data to the table. If set to true|
50
+ | | | the table will be truncated before saving the new data.|
51
+ +--------------+----------+-----------+--------------------------------------------+
52
+ | use_buffer | No | When activated, this option allows optimizing the |
53
+ | | | performance of the task, when dealing with large |
54
+ | | | volumes of data. |
55
+ +--------------+----------+-----------+--------------------------------------------+
56
+ | credentials | No | Supporting manual rethinkdb credentials |
57
+ | | | |
58
+ +--------------+----------+-----------+--------------------------------------------+
59
+ | datasource | No | Using a Datasource instead manual credentials |
60
+ | | | |
61
+ +--------------+----------+-----------+--------------------------------------------+
62
+
63
+
64
+ Example:
65
+
66
+ ```yaml
67
+ CopyToRethink:
68
+ tablename: product_availability
69
+ schema: bose
70
+ ```
71
+
72
+ """
73
+ def __init__(
74
+ self,
75
+ loop: asyncio.AbstractEventLoop = None,
76
+ job: Callable = None,
77
+ stat: Callable = None,
78
+ **kwargs,
79
+ ):
80
+ self.pk = []
81
+ self.truncate: bool = False
82
+ self.data = None
83
+ self._engine = None
84
+ self.tablename: str = ""
85
+ self.schema: str = ""
86
+ self.use_chunks = False
87
+ self._chunksize: int = kwargs.pop('chunksize', 10)
88
+ self._connection: Callable = None
89
+ try:
90
+ self.multi = bool(kwargs["multi"])
91
+ del kwargs["multi"]
92
+ except KeyError:
93
+ self.multi = False
94
+ super().__init__(
95
+ loop=loop,
96
+ job=job,
97
+ stat=stat,
98
+ **kwargs
99
+ )
100
+ self._driver: str = RT_DRIVER
101
+
102
+ def default_connection(self):
103
+ """default_connection.
104
+
105
+ Default Connection to RethinkDB.
106
+ """
107
+ try:
108
+ kwargs: dict = {
109
+ "host": RT_HOST,
110
+ "port": int(RT_PORT),
111
+ "db": RT_DATABASE,
112
+ "user": RT_USER,
113
+ "password": RT_PASSWORD
114
+ }
115
+ self._connection = AsyncDB(
116
+ RT_DRIVER,
117
+ params=kwargs,
118
+ loop=self._loop,
119
+ **kwargs
120
+ )
121
+ return self._connection
122
+ except Exception as err:
123
+ raise ComponentError(
124
+ f"Error configuring Pg Connection: {err!s}"
125
+ ) from err
126
+
127
+ # Function to clean invalid float values
128
+ def clean_floats(self, data):
129
+ def sanitize_value(value):
130
+ if isinstance(value, float) and (math.isnan(value) or math.isinf(value)):
131
+ return None # Replace invalid floats with None or other default
132
+ return value
133
+
134
+ if isinstance(data, dict):
135
+ return {k: sanitize_value(v) for k, v in data.items()}
136
+ elif isinstance(data, list):
137
+ return [self.clean_floats(item) for item in data]
138
+ return data
139
+
140
+ async def _create_table(self):
141
+ # Create a Table using Model
142
+ async with await self._connection.connection() as conn:
143
+ await conn.use(self.schema)
144
+ await self._connection.create_table(
145
+ table=self.tablename
146
+ )
147
+
148
+ async def _truncate_table(self):
149
+ async with await self._connection.connection() as conn:
150
+ await conn.use(self.schema)
151
+ await self._connection.delete(
152
+ table=self.tablename
153
+ )
154
+
155
+ async def _copy_dataframe(self):
156
+ # saving directly the dataframe with write
157
+ try:
158
+ # can remove NAT from str fields:
159
+ u = self.data.select_dtypes(include=["string"])
160
+ if not u.empty:
161
+ self.data[u.columns] = u.astype(object).where(
162
+ pd.notnull(u), None
163
+ )
164
+ # Convert the DataFrame to list of dictionaries and clean it
165
+ data_records = self.data.to_dict(orient='records')
166
+ cleaned_data = self.clean_floats(data_records)
167
+ async with await self._connection.connection() as conn:
168
+ await conn.use(self.schema)
169
+ await self._connection.write(
170
+ table=self.tablename,
171
+ data=cleaned_data,
172
+ batch_size=self._chunksize,
173
+ on_conflict="replace",
174
+ changes=True,
175
+ durability="soft",
176
+ )
177
+ except StatementError as err:
178
+ raise ComponentError(
179
+ f"Statement error: {err}"
180
+ ) from err
181
+ except DataError as err:
182
+ raise ComponentError(
183
+ f"Data error: {err}"
184
+ ) from err
185
+ except Exception as err:
186
+ raise ComponentError(
187
+ f"{self.StepName} Error: {err!s}"
188
+ ) from err
189
+
190
+ async def _copy_iterable(self):
191
+ """Copy an iterable to RethinkDB."""
192
+ try:
193
+ async with await self._connection.connection() as conn:
194
+ await conn.use(self.schema)
195
+ await conn.write(
196
+ data=self.data,
197
+ table=self.tablename,
198
+ database=self.schema,
199
+ batch_size=self._chunksize,
200
+ on_conflict="replace",
201
+ changes=True,
202
+ durability="soft",
203
+ )
204
+ except Exception as err:
205
+ raise ComponentError(
206
+ f"Error copying iterable to RethinkDB: {err}"
207
+ ) from err
@@ -0,0 +1,102 @@
1
+ import asyncio
2
+ from typing import Callable, Tuple
3
+ from asyncdb import AsyncDB
4
+ from querysource.datasources.drivers.bigquery import bigquery_default
5
+ from .flow import FlowComponent
6
+ from ..exceptions import ComponentError
7
+
8
+
9
+ class CreateGCSBucket(FlowComponent):
10
+ """
11
+ CreateGCSBucket.
12
+
13
+ Este componente crea un bucket en Google Cloud Storage (GCS).
14
+
15
+ Properties:
16
+
17
+ - bucket_name: Nombre único para el bucket de GCS. (Requerido)
18
+ - location: Región geográfica donde se creará el bucket. (Opcional, por defecto 'US')
19
+ - storage_class: Clase de almacenamiento del bucket. (Opcional, por defecto 'STANDARD')
20
+ - overwrite: Permite proceder si el bucket ya existe. (Opcional, por defecto 'False')
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ loop: asyncio.AbstractEventLoop = None,
26
+ job: Callable = None,
27
+ stat: Callable = None,
28
+ **kwargs,
29
+ ):
30
+ self.bucket_name: str = kwargs.pop('bucket_name')
31
+ self.location: str = kwargs.pop('location', 'US')
32
+ self.storage_class: str = kwargs.pop('storage_class', 'STANDARD')
33
+ self.overwrite: bool = kwargs.pop('overwrite', False)
34
+ self.bq = None # Instancia de AsyncDB
35
+ super(CreateGCSBucket, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
36
+
37
+ async def start(self, **kwargs):
38
+ """Inicializa el componente configurando la conexión AsyncDB."""
39
+ # Validar parámetro requerido
40
+ if not self.bucket_name:
41
+ raise ComponentError("CreateGCSBucket: 'bucket_name' es un parámetro requerido.")
42
+
43
+ if not bigquery_default:
44
+ raise ComponentError("CreateGCSBucket: 'bigquery_default' no está configurado correctamente.")
45
+
46
+ # Obtener credenciales y parámetros del driver
47
+ credentials = bigquery_default.get_credentials()
48
+
49
+ # Inicializar AsyncDB con el driver de BigQuery
50
+ try:
51
+ self.bq = AsyncDB("bigquery", params=credentials)
52
+ self._logger.info("CreateGCSBucket: Instancia de AsyncDB creada exitosamente.")
53
+ except Exception as e:
54
+ raise ComponentError(f"CreateGCSBucket: Error al inicializar AsyncDB: {e}") from e
55
+
56
+ async def run(self) -> Tuple[str, str]:
57
+ """Ejecuta la creación del bucket en GCS."""
58
+ if not self.bq:
59
+ raise ComponentError("CreateGCSBucket: AsyncDB no está inicializado. Asegúrate de ejecutar 'start' antes de 'run'.")
60
+
61
+ try:
62
+ async with await self.bq.connection() as conn:
63
+ # Verificar si el bucket existe
64
+ bucket_exists = await conn.bucket_exists(self.bucket_name)
65
+ if not bucket_exists:
66
+ # Crear el bucket
67
+ await conn.create_bucket(
68
+ bucket_name=self.bucket_name,
69
+ location=self.location,
70
+ storage_class=self.storage_class
71
+ )
72
+ message = f"Bucket '{self.bucket_name}' creado exitosamente en la región '{self.location}' con clase de almacenamiento '{self.storage_class}'."
73
+ self._logger.info(message)
74
+ else:
75
+ if self.overwrite:
76
+ message = f"CreateGCSBucket: El bucket '{self.bucket_name}' ya existe."
77
+ self._logger.warning(message)
78
+ else:
79
+ raise ComponentError(f"CreateGCSBucket: El bucket '{self.bucket_name}' ya existe y 'overwrite' está establecido en False.")
80
+
81
+ # Generar bucket_uri
82
+ bucket_uri = f"gs://{self.bucket_name}"
83
+
84
+ # Guardar bucket_name y bucket_uri en las variables de la tarea
85
+ self.setTaskVar("bucket_name", self.bucket_name)
86
+ self.setTaskVar("bucket_uri", bucket_uri)
87
+
88
+ return bucket_uri, message
89
+
90
+ except ComponentError as ce:
91
+ raise ce # Re-lanzar errores específicos de componentes
92
+ except Exception as e:
93
+ raise ComponentError(f"CreateGCSBucket: Error durante la creación del bucket: {e}") from e
94
+
95
+ async def close(self):
96
+ """Cierra la conexión AsyncDB."""
97
+ try:
98
+ if self.bq:
99
+ await self.bq.close()
100
+ self._logger.info("CreateGCSBucket: AsyncDB cerrado exitosamente.")
101
+ except Exception as e:
102
+ self._logger.error(f"CreateGCSBucket: Error al cerrar AsyncDB: {e}")
@@ -0,0 +1,228 @@
1
+ """
2
+ CreateReport.
3
+
4
+ Using a Jinja2 Template to crete a Report and, optionally, send via Email.
5
+
6
+
7
+ Example:
8
+
9
+ ```yaml
10
+ CreateReport:
11
+ template_file: echelon_program_overview_raw.html
12
+ create_pdf: true
13
+ masks:
14
+ '{today}':
15
+ - today
16
+ - mask: '%m/%d/%Y'
17
+ '{created}':
18
+ - today
19
+ - mask: '%Y-%m-%d %H:%M:%s'
20
+ '{firstdate}':
21
+ - date_diff
22
+ - value: today
23
+ diff: 8
24
+ mode: days
25
+ mask: '%b %d, %Y'
26
+ '{lastdate}':
27
+ - yesterday
28
+ - mask: '%b %d, %Y'
29
+ send:
30
+ via: email
31
+ list: echelon_program_overview
32
+ message:
33
+ subject: 'Echelon Kohl''s VIBA Report for: ({today})'
34
+ arguments:
35
+ today_report: '{today}'
36
+ generated_at: '{created}'
37
+ firstdate: '{firstdate}'
38
+ lastdate: '{lastdate}'
39
+ ```
40
+
41
+ """
42
+ import asyncio
43
+ import datetime
44
+ from typing import Dict, List, Callable
45
+ from pathlib import Path
46
+ from navconfig.logging import logging
47
+ from notify import Notify
48
+ from notify.models import Actor
49
+ from ..flow import FlowComponent
50
+ from ...template import getTemplateHandler
51
+ from ...exceptions import ComponentError, FileNotFound
52
+ from ...conf import BASE_DIR, TASK_PATH
53
+ from .charts import loadChart
54
+ from ..support import DBSupport
55
+
56
+
57
+ class CreateReport(FlowComponent, DBSupport):
58
+ """
59
+ CreateReport
60
+
61
+ Overview
62
+
63
+ The CreateReport class is a component for creating rich reports and sending them via the Notify service. It uses
64
+ template handling and chart creation to generate the content of the reports and sends them to a list of recipients.
65
+
66
+ .. table:: Properties
67
+ :widths: auto
68
+
69
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
70
+ | Name | Required | Description |
71
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
72
+ | _data | Yes | A dictionary containing the input data for the report. |
73
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
74
+ | _parser | Yes | The template parser for generating the report content. |
75
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
76
+ | _chartparser | Yes | The template parser for generating charts. |
77
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
78
+ | template_file | Yes | The file name of the template to use for the report. |
79
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
80
+ | recipients | Yes | A list of recipients to send the report to. |
81
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
82
+ | send | Yes | A dictionary containing the sending options and configurations. |
83
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
84
+ | message | No | The message content for the report. |
85
+ +------------------+----------+-----------+--------------------------------------------------------------------------------------+
86
+
87
+ Returns:
88
+ The input data after sending the report.
89
+
90
+ """
91
+
92
+ def __init__(
93
+ self,
94
+ loop: asyncio.AbstractEventLoop = None,
95
+ job: Callable = None,
96
+ stat: Callable = None,
97
+ **kwargs,
98
+ ):
99
+ """Init Method."""
100
+ self._data: Dict = {}
101
+ self._parser: Callable = None
102
+ self._chartparser: Callable = None
103
+ self.template_file: str = None
104
+ self.recipients = []
105
+ self.send: Dict = None
106
+ self.message: str = None
107
+ super().__init__(loop=loop, job=job, stat=stat, **kwargs)
108
+
109
+ async def start(self, **kwargs):
110
+ template_dir = Path(TASK_PATH, self._program, "templates")
111
+ echart_dir = Path(BASE_DIR, "DataIntegration", "dataintegration", "templates")
112
+ if self.previous:
113
+ self._data = self.input
114
+ try:
115
+ self._parser = getTemplateHandler(newdir=template_dir)
116
+ self._chartparser = getTemplateHandler(newdir=echart_dir)
117
+ except Exception as err:
118
+ logging.exception(err)
119
+ raise ComponentError(
120
+ f"CreateReport: Unable to load Template Parser: {err}"
121
+ ) from err
122
+ template_file = template_dir.joinpath(self.template_file)
123
+ if not template_file.is_file():
124
+ raise FileNotFound(f"CreateReport: Missing Template File: {template_file}")
125
+ if hasattr(self, "masks"):
126
+ for key, value in self.send.items():
127
+ self.send[key] = self.mask_replacement(value)
128
+ # getting the mailing list:
129
+ try:
130
+ lst = self.send["list"]
131
+ except AttributeError:
132
+ lst = "owner"
133
+ sql = f"SELECT * FROM troc.get_mailing_list('{lst!s}')"
134
+ db = self.get_connection()
135
+ async with await db.connection() as conn:
136
+ try:
137
+ result, error = await conn.query(sql)
138
+ if error:
139
+ raise ComponentError(
140
+ f"CreateReport: Error on Recipients: {error!s}."
141
+ )
142
+ for r in result:
143
+ actor = Actor(**dict(r))
144
+ self.recipients.append(actor)
145
+ except Exception as err:
146
+ logging.exception(err)
147
+ if not self.recipients:
148
+ raise ComponentError("CreateReport: Invalid Number of Recipients.")
149
+
150
+ def status_sent(self, recipient, message, result, *args, **kwargs):
151
+ print(f"Notification status {result!s} to {recipient.account!s}")
152
+ # logger:
153
+ logging.info(f"Notification status {result!s} to {recipient.account!s}")
154
+ # TODO: register sent on a logger database
155
+
156
+ async def send_message(self, recipients: List, data: Dict = None):
157
+ try:
158
+ emailService = Notify(self.send["via"], loop=self._loop)
159
+ except Exception as err:
160
+ raise ComponentError(f"Error loading Notify Service: {err!s}") from err
161
+ # add event for sent function
162
+ emailService.sent = self.status_sent
163
+ self.message = self.send["message"]
164
+ # create echart graph based on template
165
+ graph = {}
166
+ if hasattr(self, "echarts"):
167
+ for dataset, chart in self.echarts["charts"].items():
168
+ ds = self._data[dataset]
169
+ graph_name = chart["name"]
170
+ try:
171
+ graphtype = chart["type"]
172
+ del chart["type"]
173
+ except KeyError:
174
+ graphtype = "bar"
175
+ try:
176
+ title = chart["title"]
177
+ del chart["title"]
178
+ except KeyError:
179
+ title = dataset
180
+ chart = loadChart(graphtype, data=ds, title=title, **chart)
181
+ img = chart.image()
182
+ graph[graph_name] = img
183
+ # else:
184
+ emailTemplate = self._parser.get_template(self.template_file)
185
+ for user in recipients:
186
+ # TODO: add dot notation to Actor Model
187
+ email = user.account["address"]
188
+ args = {
189
+ "user": user,
190
+ "html": emailTemplate,
191
+ "email": email,
192
+ "created_at": datetime.datetime.now(),
193
+ **graph,
194
+ }
195
+ self.message["created_at"] = datetime.datetime.now()
196
+ other = {}
197
+ if "arguments" in self.send:
198
+ other = self.send["arguments"]
199
+ args = {**data, **args, **other}
200
+ content = emailTemplate.render(args)
201
+ try:
202
+ logging.debug(f"Sending Email to {user} via {email}")
203
+ # TODO: Send email via Worker or thread (async)
204
+ await emailService.send(
205
+ recipient=user, template=None, message=content, **self.message
206
+ )
207
+ except Exception as err:
208
+ logging.exception(err)
209
+ raise ComponentError(f"Error Sending Email: {err}") from err
210
+ finally:
211
+ try:
212
+ await emailService.close()
213
+ except Exception as err:
214
+ logging.error(err)
215
+
216
+ def close(self):
217
+ pass
218
+
219
+ async def run(self):
220
+ try:
221
+ await self.send_message(self.recipients, self._data)
222
+ self._result = self.data
223
+ return self._result
224
+ except Exception as err:
225
+ logging.exception(err)
226
+ raise ComponentError(
227
+ f"CreateReport: Error sending Report: {err!s}"
228
+ ) from err
@@ -0,0 +1,9 @@
1
+ """
2
+ CreateReport.
3
+
4
+ Component for creating Rich Reports and send via Notify.
5
+ """
6
+
7
+ from .CreateReport import CreateReport
8
+
9
+ __all__ = ["CreateReport"]
@@ -0,0 +1,15 @@
1
+ """Chart utilities using PyEcharts."""
2
+ from typing import Any
3
+ from .pie import pieChart
4
+ from .bar import barChart
5
+
6
+ __all__ = ["pieChart", "barChart"]
7
+
8
+
9
+ def loadChart(charttype: str, title: str, data: Any, **kwargs):
10
+ if charttype == "bar":
11
+ return barChart(title, data, **kwargs)
12
+ elif charttype == "pie":
13
+ return pieChart(title, data, **kwargs)
14
+ else:
15
+ raise RuntimeError("CreateReport: Invalid Chart Type")
@@ -0,0 +1,51 @@
1
+ from typing import Any, Union, List, Dict
2
+ import orjson
3
+ from pyecharts.charts import Bar
4
+ from borax.datasets.fetch import fetch
5
+ import pyecharts.options as opts
6
+ from .base import baseChart
7
+
8
+
9
+ class barChart(baseChart):
10
+ rosetype: str = "radius"
11
+ formatter: str = "{c}"
12
+ axis_type: str = "category"
13
+
14
+ def __init__(self, title: str, data: Union[List, Dict], **kwargs):
15
+ fields = kwargs["fields"]
16
+ self._x = fields["x_axis"]
17
+ self._y = fields["y_axis"]
18
+ super(barChart, self).__init__(title, data, **kwargs)
19
+
20
+ def get_chart(self):
21
+ return Bar(init_opts=self.init_opts)
22
+
23
+ def set_chart(self, data: Any, title: str, **kwargs):
24
+ # x, y = Base.cast(o_data)
25
+ dst = self._encoder(data)
26
+ dst = orjson.loads(dst)
27
+ names = fetch(dst, self._x)
28
+ self.chart.add_xaxis(names)
29
+ for y in self._y:
30
+ values = fetch(dst, y)
31
+ self.chart.add_yaxis(y, values)
32
+ self.chart.set_global_opts(
33
+ **self.get_global_opts(title, **kwargs)
34
+ ).set_series_opts(**self.get_series_opts(**kwargs))
35
+
36
+ def get_basic_args(self, **kwargs):
37
+ return {}
38
+
39
+ def get_series_opts(self, **kwargs):
40
+ return {
41
+ "label_opts": opts.LabelOpts(
42
+ position="outside", formatter=self.formatter, is_show=True
43
+ )
44
+ }
45
+
46
+ def get_global_opts(self, title: str, **kwargs):
47
+ return {
48
+ "title_opts": opts.TitleOpts(title=title),
49
+ "legend_opts": opts.LegendOpts(is_show=True, pos_right="15%"),
50
+ "xaxis_opts": opts.AxisOpts(type_=self.axis_type),
51
+ }
@@ -0,0 +1,66 @@
1
+ """Base Class for all Chart types."""
2
+ from abc import (
3
+ ABC,
4
+ abstractmethod,
5
+ )
6
+ from typing import Any, Union, List, Dict
7
+ from pyecharts.globals import ThemeType
8
+ import pyecharts.options as opts
9
+ from pyecharts.render import make_snapshot
10
+ from snapshot_selenium import snapshot as driver
11
+ from asyncdb.utils.encoders import DefaultEncoder
12
+
13
+
14
+ class baseChart(ABC):
15
+ theme: str = "LIGHT"
16
+
17
+ def __init__(self, title: str, data: Union[List, Dict], **kwargs):
18
+ self.formatter = None
19
+ if "theme" in kwargs:
20
+ self.theme = kwargs["theme"]
21
+ del kwargs["theme"]
22
+ try:
23
+ self._fields = kwargs["fields"]
24
+ except KeyError:
25
+ self._fields = ["name", "value"]
26
+ self._encoder = DefaultEncoder(sort_keys=False)
27
+ self._theme = getattr(ThemeType, self.theme)
28
+ # TODO: making more initializations
29
+ self.init_opts = opts.InitOpts(theme=self._theme, width="620px", height="420px")
30
+ self.chart = self.get_chart()
31
+ self.args = self.get_basic_args(**kwargs)
32
+ self.set_chart(data, title, **kwargs)
33
+
34
+ @abstractmethod
35
+ def get_chart(self):
36
+ pass
37
+
38
+ @abstractmethod
39
+ def set_chart(self, data: Any, title: str, **kwargs):
40
+ pass
41
+
42
+ @abstractmethod
43
+ def get_basic_args(self, **kwargs):
44
+ pass
45
+
46
+ @abstractmethod
47
+ def get_global_opts(self, title: str, **kwargs):
48
+ pass
49
+
50
+ def get_series_opts(self, **kwargs):
51
+ return {
52
+ "label_opts": opts.LabelOpts(
53
+ position="outside", formatter=self.formatter, is_show=True
54
+ )
55
+ }
56
+
57
+ def chart(self):
58
+ return self.chart
59
+
60
+ def image(self):
61
+ """Returns the Base64 version of Image."""
62
+ img = None
63
+ make_snapshot(driver, self.chart.render(), "graph.base64")
64
+ with open("graph.base64", "r", encoding="utf-8") as f:
65
+ img = f.read()
66
+ return img