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,507 @@
1
+ import asyncio
2
+ from collections.abc import Callable
3
+ import math
4
+ import backoff
5
+ from uuid import uuid4
6
+ from urllib.parse import urlencode, urljoin
7
+ import httpx
8
+ from requests.models import PreparedRequest
9
+ import numpy as np
10
+ import pandas as pd
11
+ from .flow import FlowComponent
12
+ from ..interfaces.http import HTTPService
13
+ from ..exceptions import (
14
+ ComponentError,
15
+ DataError,
16
+ DataNotFound
17
+ )
18
+
19
+
20
+ class Pokemon(HTTPService, FlowComponent):
21
+ """
22
+ Pokémon Component
23
+
24
+ **Overview**
25
+
26
+ This component interacts with the Pokémon API to retrieve data about machines or their on-hand inventory.
27
+ It supports two main operations determined by the `type` parameter:
28
+
29
+ - **"machines"**: Retrieves a list of machines.
30
+ - **"inventory"**: Retrieves on-hand inventory data for specified machines.
31
+ - **sites**: Retrieves the Pokemon sites
32
+ - ****: Retrieves the Pokemon
33
+ - **warehouses**: Retrieves the Pokemon warehouses
34
+
35
+
36
+ The component handles authentication, constructs the necessary requests, processes the data,
37
+ and returns a pandas DataFrame suitable for further analysis in your data pipeline.
38
+
39
+ .. table:: Properties
40
+ :widths: auto
41
+
42
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
43
+ | Name | Required | Summary |
44
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
45
+ | credentials | Yes | Dictionary containing API credentials: `"BASE_URL"`, `"CLIENT_ID"`, and `"CLIENT_SECRET"`. |
46
+ | | | Credentials can be retrieved from environment variables. |
47
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
48
+ | type | Yes | Type of operation to perform. Accepts `"machines"` to retrieve machine data or `"inventory"` |
49
+ | | | to retrieve machine inventory data. |
50
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
51
+ | ids | No | List of machine IDs to retrieve inventory for when `type` is `"inventory"`. |
52
+ | | | Overrides IDs from the previous step if provided. |
53
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
54
+ | data | No | Data from the previous step, typically a pandas DataFrame containing machine |
55
+ | | | IDs in a column named `"machine_id"`. Used when `type` is `"inventory"`. |
56
+ +----------------------------+----------+----------------------------------------------------------------------------------------------+
57
+
58
+ **Returns**
59
+
60
+ This component returns a pandas DataFrame containing the retrieved data from the Pokémon API.
61
+ The structure of the DataFrame depends on the operation type:
62
+
63
+ - **For `type = "machines"`**: The DataFrame contains information about machines, with columns corresponding
64
+ to the machine attributes provided by the API.
65
+ - **For `type = "inventory"`**: The DataFrame contains on-hand inventory details for each machine,
66
+ including `machineId` and detailed slot information.
67
+
68
+
69
+ Example:
70
+
71
+ ```yaml
72
+ Pokemon:
73
+ credentials:
74
+ BASE_URL: POKEMON_BASE_URL
75
+ CLIENT_ID: POKEMON_CLIENT_ID
76
+ CLIENT_SECRET: POKEMON_CLIENT_SECRET
77
+ type: machines
78
+ ```
79
+
80
+ """ # noqa
81
+ accept: str = "application/json"
82
+ download = None
83
+ _credentials: dict = {
84
+ "BASE_URL": str,
85
+ "CLIENT_ID": str,
86
+ "CLIENT_SECRET": str,
87
+ }
88
+ ids: list = []
89
+ errors_df: pd.DataFrame = None
90
+
91
+ def __init__(
92
+ self,
93
+ loop: asyncio.AbstractEventLoop = None,
94
+ job: Callable = None,
95
+ stat: Callable = None,
96
+ **kwargs,
97
+ ):
98
+ self.type: str = kwargs.get('type')
99
+ self.machine_inventory: bool = kwargs.get('machine_inventory', False)
100
+ self._semaphore_limit = kwargs.get('semaphore_limit', 10)
101
+ self._chunk_size: int = kwargs.get('chunk_size', 2)
102
+ super().__init__(
103
+ loop=loop, job=job, stat=stat, **kwargs
104
+ )
105
+ self._semaphore = asyncio.Semaphore(self._semaphore_limit)
106
+
107
+ async def start(self, **kwargs):
108
+ if self.previous:
109
+ self.data = self.input
110
+ # Validate that machine_id column exists in the DataFrame
111
+ if "machine_id" not in self.data.columns:
112
+ raise ComponentError(
113
+ f'{__name__}: Input DataFrame must contain a "machine_id" column'
114
+ )
115
+
116
+ self.processing_credentials()
117
+
118
+ # Adding client_id and secret:
119
+ self.headers["client_id"] = self.credentials["CLIENT_ID"]
120
+ self.headers["client_secret"] = self.credentials["CLIENT_SECRET"]
121
+
122
+ return True
123
+
124
+ async def run(self):
125
+ type_call = getattr(self, f"{self.type}", None)
126
+
127
+ if not type_call:
128
+ raise ComponentError(
129
+ "incorrect or not provided type"
130
+ )
131
+
132
+ if not callable(type_call):
133
+ raise ComponentError(
134
+ f"Function {self.type} doesn't exist."
135
+ )
136
+
137
+ try:
138
+ result = await type_call()
139
+ except (ComponentError, DataError, DataNotFound) as e:
140
+ self._logger.error(f"Error: {str(e)}")
141
+ raise
142
+
143
+ if not isinstance(result, pd.DataFrame):
144
+ self._result = result
145
+ return self._result
146
+
147
+ self.add_metric("NUMROWS", len(result.index))
148
+ self.add_metric("NUMCOLS", len(result.columns))
149
+
150
+ self._result = result
151
+
152
+ if self._debug is True:
153
+ self._print_data("Result Data", self._result)
154
+
155
+ return self._result
156
+
157
+ async def close(self):
158
+ return True
159
+
160
+ def _print_data(self, title: str, data_df: pd.DataFrame):
161
+ """
162
+ Prints the data and its corresponding column types for a given DataFrame.
163
+
164
+ Parameters:
165
+ title (str): The title to print before the data.
166
+ data_df (pd.DataFrame): The DataFrame to print and inspect.
167
+ """
168
+ print(f"::: Printing {title} === ")
169
+ print("Data: ", data_df)
170
+ for column, t in data_df.dtypes.items():
171
+ print(f"{column} -> {t} -> {data_df[column].iloc[0]}")
172
+
173
+ def _create_url_arguments(self, method: str, path: str):
174
+ """
175
+ Creates the URL arguments for the given method and path.
176
+
177
+ Parameters:
178
+ method (str): The HTTP method for the request.
179
+ path (str): The path for the request.
180
+
181
+ Returns:
182
+ dict: The URL arguments for the request.
183
+ """
184
+ self.headers["request-id"] = str(uuid4())
185
+ url_args = {
186
+ "method": method,
187
+ "url": path,
188
+ "use_proxy": False
189
+ }
190
+ return url_args
191
+
192
+ @backoff.on_exception(
193
+ backoff.expo,
194
+ (httpx.TimeoutException, httpx.ConnectTimeout, httpx.HTTPStatusError),
195
+ max_time=60,
196
+ max_tries=3,
197
+ jitter=backoff.full_jitter,
198
+ giveup=lambda e: not isinstance(e, (DataError, httpx.ConnectTimeout)),
199
+ )
200
+ async def _get_pokemon_results(self, args, payload):
201
+ async with self._semaphore:
202
+ results, error = await self.session(**args, data=payload, use_json=True)
203
+ await asyncio.sleep(0.5) # Sleep to avoid rate limiting
204
+ if error:
205
+ raise ComponentError(
206
+ f"{__name__}: Error in request: {error}"
207
+ )
208
+
209
+ if not results:
210
+ raise ComponentError(
211
+ f"{__name__}: Empty response from API"
212
+ )
213
+
214
+ if "machines" in results:
215
+ machines_data = []
216
+ datetime_utc = results.get("dateTimeUTC")
217
+
218
+ column_names = []
219
+ for machine in results["machines"]:
220
+ machine_id = machine["machine"]
221
+ slots = machine["slots"]
222
+ if not column_names:
223
+ for s in slots:
224
+ if s.get("errorCode", None) is None:
225
+ column_names = list(s.keys())
226
+ break
227
+ try:
228
+ errorcode = slots[0].get("errorCode", None)
229
+ msg = slots[0].get("errorMessage", None)
230
+ if str(errorcode) == "404":
231
+ self._logger.warning(
232
+ f":: Retrying Vending Machine with Id {machine_id}"
233
+ )
234
+ new_payload = self.get_machines_inventory_payload([machine_id])
235
+ new_result, _ = await self.session(**args, data=new_payload, use_json=True)
236
+ if new_result and "machines" in new_result:
237
+ slots = new_result["machines"][0]["slots"]
238
+ errorcode = slots[0].get("errorCode", None)
239
+ msg = slots[0].get("errorMessage", None)
240
+ except (IndexError, AttributeError):
241
+ errorcode = None
242
+ msg = None
243
+ except Exception as e:
244
+ errorcode += f" , Error: {e}"
245
+
246
+ if errorcode:
247
+ response = {c: None for c in column_names}
248
+ machines_data.append({
249
+ "machine": machine_id,
250
+ **response,
251
+ "dateTimeUTC": datetime_utc,
252
+ "errorCode": errorcode,
253
+ "errorMessage": msg,
254
+ })
255
+ continue
256
+
257
+ for slot in slots:
258
+ machines_data.append({
259
+ "machine": machine_id,
260
+ **slot,
261
+ "dateTimeUTC": datetime_utc,
262
+ "errorCode": None,
263
+ "errorMessage": None
264
+ })
265
+
266
+ df = pd.DataFrame(machines_data)
267
+ return df
268
+ else:
269
+ raise ComponentError(
270
+ f"{__name__}: Unexpected response format: {results}"
271
+ )
272
+
273
+ def get_pokemon_url(self, resource, parameters: dict = None):
274
+ url = urljoin(self.credentials["BASE_URL"], resource)
275
+ if parameters:
276
+ url += "?" + urlencode(parameters)
277
+ return url
278
+
279
+ def get_machines_inventory_payload(self, machines: list):
280
+ """Create payload following API specification"""
281
+ return {
282
+ "requestFilter": {
283
+ "machines": machines
284
+ }
285
+ }
286
+
287
+ @staticmethod
288
+ def split_chunk_ids(items: pd.Series, chunk_size: str):
289
+ """
290
+ Splits a Series of IDs into chunks of a specified size.
291
+
292
+ Parameters:
293
+ items (pd.Series): A pandas Series containing the IDs to be split.
294
+ chunk_size (int): The maximum number of IDs per chunk.
295
+
296
+ Returns:
297
+ list: A list of NumPy arrays, each containing a chunk of IDs.
298
+ If the Series is empty or all IDs are NaN, returns an empty list or a list containing an empty array.
299
+ """
300
+ data = items.dropna().unique().astype(str)
301
+
302
+ if data.size > 0:
303
+ split_n = math.ceil(data.size / chunk_size)
304
+
305
+ # Split into chunks of n items
306
+ return np.array_split(data, split_n) # Convert to NumPy array and split
307
+
308
+ return [data]
309
+
310
+ async def inventory(self):
311
+ args = self._create_url_arguments(
312
+ method="post",
313
+ path=self.get_pokemon_url("machines/on-hand-inventory"),
314
+ )
315
+
316
+ # List of Machine IDs - Check both input sources
317
+ if hasattr(self, 'data') and isinstance(self.data, pd.DataFrame) and not self.data.empty:
318
+ if "machine_id" not in self.data.columns:
319
+ raise ComponentError(
320
+ f'{__name__}: Input DataFrame must contain a "machine_id" column'
321
+ )
322
+ self._logger.info(
323
+ f'{__name__}: Using machine_ids from previous step in column "machine_id"'
324
+ )
325
+ self.data_ids = self.data["machine_id"]
326
+ elif self.ids and len(self.ids) > 0:
327
+ self._logger.info(
328
+ f"{__name__}: Using machine_ids provided in Task arguments"
329
+ )
330
+ self.data_ids = pd.Series(self.ids)
331
+ else:
332
+ raise ComponentError(
333
+ f'{__name__}: No machine_ids provided. Either pass them through previous step with "machine_id" column or specify in task arguments' # noqa
334
+ )
335
+
336
+ # Validate we have valid IDs
337
+ if self.data_ids.empty:
338
+ raise ComponentError(f"{__name__}: No valid machine_ids found to process")
339
+
340
+ total_ids = len(self.data_ids)
341
+ self._logger.info(f"Processing {total_ids} machine_ids")
342
+
343
+ # Split into chunks of 3 (API limit)
344
+ ids_chunks = self.split_chunk_ids(
345
+ items=self.data_ids,
346
+ chunk_size=self._chunk_size,
347
+ )
348
+
349
+ total_chunks = len(ids_chunks)
350
+ self._logger.info(f"Split into {total_chunks} chunks of max 3 machines each")
351
+
352
+ # Process chunks with error handling and progress
353
+ df_items = pd.DataFrame()
354
+ errors = []
355
+
356
+ tasks = []
357
+ for _, ids_chunk in enumerate(ids_chunks, 1):
358
+ self._logger.info(f"Requesting inventory for machines: {ids_chunk.tolist()}")
359
+ payload = self.get_machines_inventory_payload(ids_chunk.tolist())
360
+ tasks.append(
361
+ self._get_pokemon_results(args, payload)
362
+ )
363
+
364
+ data = []
365
+ try:
366
+ results = await asyncio.gather(*tasks, return_exceptions=True)
367
+ for result in results:
368
+ if isinstance(result, pd.DataFrame):
369
+ data.append(result)
370
+ elif isinstance(result, Exception):
371
+ errors.append(
372
+ {
373
+ "error": str(result),
374
+ }
375
+ )
376
+
377
+ except Exception as e:
378
+ raise ComponentError(
379
+ f"{__name__}: Error processing inventory: {str(e)}"
380
+ )
381
+
382
+ # Log summary
383
+ if data:
384
+ df_items = pd.concat(data, ignore_index=True)
385
+ self._logger.info(f"Finished processing {len(df_items.index)}/{total_ids} machines")
386
+ else:
387
+ self._logger.warning(
388
+ "No data could be retrieved from any chunk"
389
+ )
390
+ raise DataNotFound(
391
+ "No data could be retrieved from any chunk"
392
+ )
393
+ if errors:
394
+ self._logger.warning(f"Found {len(errors)} errors during processing")
395
+ errors_df = pd.DataFrame(errors)
396
+ self.errors_df = errors_df # Save errors for later inspection
397
+
398
+ if df_items.empty:
399
+ raise DataNotFound(f"{__name__}: No data could be retrieved from any chunk")
400
+
401
+ return df_items
402
+
403
+ async def _get_pokemon_resource(self, resource: str = 'sites', response_key: str = None):
404
+ """Get a Pokemon Resource with optional Pagination (as sites, or )
405
+
406
+ Args:
407
+ resource (str, optional): The resource to get (default'sites').
408
+ response_key (str, optional): The key to look for in the API response. If None, uses the resource name.
409
+
410
+ Return:
411
+ pd.DataFrame: The DataFrame containing the requested resource.
412
+
413
+ """
414
+ result = []
415
+ offset = None
416
+ off_args = None
417
+
418
+ # If no response_key provided, use the resource name
419
+ response_key = response_key or resource
420
+
421
+ while True:
422
+ if offset:
423
+ off_args = {"offset": offset}
424
+ args = self._create_url_arguments(
425
+ method="get",
426
+ path=self.get_pokemon_url(resource, off_args),
427
+ )
428
+ results, error = await self.session(**args)
429
+ if error:
430
+ raise DataError(
431
+ f"Error getting Pokemon {resource.capitalize()} {error}"
432
+ )
433
+
434
+ if not results:
435
+ self._logger.warning(f"Empty response received for {resource}")
436
+ break
437
+
438
+ if r := results.get(response_key, []):
439
+
440
+ result.extend(r)
441
+ else:
442
+ break
443
+
444
+ offset = results.get('offset', None)
445
+ if offset is None:
446
+ break
447
+
448
+ if not result:
449
+ raise DataNotFound(f"No Pokemon {resource.capitalize()} found")
450
+ return await self.create_dataframe(result)
451
+
452
+ async def sites(self):
453
+ return await self._get_pokemon_resource('sites')
454
+
455
+ async def locations(self):
456
+ return await self._get_pokemon_resource('locations')
457
+
458
+ async def kiosks_history(self):
459
+ return await self._get_pokemon_resource('machines/installs', 'machineInstalls')
460
+
461
+ async def products(self):
462
+ return await self._get_pokemon_resource('products')
463
+
464
+ async def warehouses(self):
465
+ args = self._create_url_arguments(
466
+ method="get",
467
+ path=self.get_pokemon_url("warehouses/merch")
468
+ )
469
+ results, error = await self.session(**args)
470
+
471
+ if result := results.get("merchWarehouses", None):
472
+ return await self.create_dataframe(result)
473
+ else:
474
+ raise ComponentError(
475
+ f"{__name__}: Error in Machines request: {error} {results}"
476
+ )
477
+
478
+ async def machines(self):
479
+ args = self._create_url_arguments(
480
+ method="get",
481
+ path=self.get_pokemon_url("machines")
482
+ )
483
+ results, error = await self.session(**args)
484
+
485
+ if result := results.get("machines", None):
486
+ return await self.create_dataframe(result)
487
+ else:
488
+ raise ComponentError(
489
+ f"{__name__}: Error in Machines request: {error} {results}"
490
+ )
491
+
492
+ async def health(self):
493
+ args = self._create_url_arguments(
494
+ method="get",
495
+ path=self.get_pokemon_url("health-check")
496
+ )
497
+ result, error = await self.session(**args)
498
+
499
+ if message := result.get("message", None):
500
+ if message == "The ar-vending-prc-api is up and running":
501
+ return result
502
+ else:
503
+ return result
504
+ else:
505
+ raise ComponentError(
506
+ f"{__name__}: Error in Health request: {error}"
507
+ )
@@ -0,0 +1,62 @@
1
+ from collections.abc import Callable
2
+ import asyncio
3
+ from ..interfaces.ParrotBot import ParrotBot
4
+ from .flow import FlowComponent
5
+
6
+
7
+ class PositiveBot(ParrotBot, FlowComponent):
8
+ """
9
+ PositiveBot.
10
+
11
+ Overview
12
+
13
+ The PositiveBot class is a component for interacting with an IA Agent for making Customer Satisfaction Analysis.
14
+ It extends the FlowComponent class.
15
+
16
+ .. table:: Properties
17
+ :widths: auto
18
+
19
+ +------------------+----------+--------------------------------------------------------------------------------------------------+
20
+ | Name | Required | Description |
21
+ +------------------+----------+--------------------------------------------------------------------------------------------------+
22
+ | output_column | Yes | Column for saving the Customer Satisfaction information. |
23
+ +------------------+----------+--------------------------------------------------------------------------------------------------+
24
+ Return
25
+
26
+ A Pandas Dataframe with the Customer Satisfaction statistics.
27
+
28
+ """ # noqa
29
+
30
+ def __init__(
31
+ self,
32
+ loop: asyncio.AbstractEventLoop = None,
33
+ job: Callable = None,
34
+ stat: Callable = None,
35
+ **kwargs,
36
+ ):
37
+ super().__init__(
38
+ loop=loop, job=job, stat=stat, **kwargs
39
+ )
40
+ self._goal: str = 'Your task is to provide a concise and insightful analysis of positive reviews'
41
+
42
+ def format_question(self, product_name, reviews):
43
+ question = f"""
44
+ Product: {product_name}
45
+
46
+ Question:
47
+ "What are the primary positive aspects, features, and customer sentiments based on these positive product reviews for {product_name}?"
48
+
49
+ Positive Customer Reviews:
50
+
51
+ """ # noqa
52
+ for review in reviews:
53
+ question += f"* {review}\n"
54
+ return question
55
+
56
+ async def run(self):
57
+ self._result = await self.bot_evaluation()
58
+ self._print_data_(self._result, 'PositiveBot')
59
+ return self._result
60
+
61
+ async def close(self):
62
+ pass