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,362 @@
1
+ import builtins
2
+ import traceback
3
+ ## Notify System
4
+ from notify import Notify
5
+ from notify.providers.email import Email
6
+ from notify.providers.slack import Slack
7
+ from notify.providers.teams import Teams
8
+ from notify.models import (
9
+ Actor,
10
+ Chat,
11
+ Channel,
12
+ TeamsCard,
13
+ TeamsChannel
14
+ )
15
+ import querysource.utils.functions as qsfunctions
16
+ from ....conf import (
17
+ EVENT_CHAT_ID,
18
+ EVENT_CHAT_BOT,
19
+ DEFAULT_RECIPIENT,
20
+ NOTIFY_ON_ERROR,
21
+ EMAIL_USERNAME,
22
+ EMAIL_PASSWORD,
23
+ EMAIL_PORT,
24
+ EMAIL_HOST,
25
+ ENVIRONMENT,
26
+ SLACK_DEFAULT_CHANNEL,
27
+ SLACK_DEFAULT_CHANNEL_NAME,
28
+ MS_TEAMS_DEFAULT_TEAMS_ID,
29
+ MS_TEAMS_DEFAULT_CHANNEL_ID,
30
+ MS_TEAMS_DEFAULT_CHANNEL_NAME,
31
+ )
32
+ from ....utils import cPrint, check_empty
33
+ from ....exceptions import ConfigError, EventError
34
+ from . import functions as alertfunc
35
+ from . import colfunctions as colfunc
36
+ from ..abstract import AbstractEvent
37
+ from ....interfaces.notification import Notification
38
+
39
+
40
+ def recursive_lookup(d, target_key):
41
+ """
42
+ Recursively finds the first dictionary that contains a given key inside a nested dictionary.
43
+
44
+ :param d: Dictionary to search
45
+ :param target_key: Key to find ("result" by default)
46
+ :return: The dictionary containing the key, or None if not found
47
+ """
48
+ """
49
+ Recursively finds the first dictionary that contains the given key.
50
+
51
+ :param d: Dictionary to search
52
+ :param target_key: Key to find dynamically (e.g., "result" or any other key)
53
+ :return: The dictionary containing the key, or None if not found
54
+ """
55
+ if isinstance(d, dict):
56
+ if target_key in d:
57
+ return d # Return the entire dictionary that contains the target key
58
+ for _, value in d.items():
59
+ if isinstance(value, dict): # Recurse into nested dictionaries
60
+ found = recursive_lookup(value, target_key)
61
+ if found is not None:
62
+ return found
63
+ return None
64
+
65
+
66
+ class Alert(Notification, AbstractEvent):
67
+ def __init__(self, *args, **kwargs):
68
+ # adding checks:
69
+ self.system_checks: list = kwargs.pop("system_checks", [])
70
+ self.result_checks: list = kwargs.pop("result_checks", [])
71
+ self.column_checks: list = kwargs.pop("column_checks", [])
72
+ self.stat_checks: list = kwargs.pop("stat_checks", [])
73
+ self._channel: str = kwargs.pop("channel", NOTIFY_ON_ERROR)
74
+ super().__init__(*args, **kwargs)
75
+
76
+ async def __call__(self, *args, **kwargs):
77
+ task = kwargs.get("task", None)
78
+ program = task.getProgram()
79
+ task_name = f"{program}.{task.taskname}"
80
+ try:
81
+ stats = task.stats.to_json()
82
+ except AttributeError:
83
+ stats = None
84
+
85
+ df = task.resultset()
86
+
87
+ errors = []
88
+
89
+ if self.system_checks:
90
+ rst = await self.process_checks(self.system_checks, stats, task_name)
91
+ if rst:
92
+ errors += rst
93
+
94
+ if self.stat_checks:
95
+ if check_empty(stats):
96
+ self._logger.warning(f"No statistics found for the task {task_name}")
97
+ return None
98
+ steps = stats.get("steps", [])
99
+ rst = await self.stats_checks(self.stat_checks, stats, steps, task_name)
100
+ if rst:
101
+ errors += rst
102
+
103
+ if self.result_checks:
104
+ if check_empty(df):
105
+ return None
106
+ data = {
107
+ "num_rows": len(df),
108
+ "num_columns": df.shape[1],
109
+ "shape": df.shape,
110
+ "columns": df.columns.values.tolist()
111
+ }
112
+ rst = await self.process_checks(self.result_checks, data, task_name)
113
+ if rst:
114
+ errors += rst
115
+
116
+ if self.column_checks:
117
+ # Get the summary statistics of the DataFrame
118
+ desc = df.describe()
119
+ err = []
120
+ for check in self.column_checks:
121
+ fname, colname, fn, params = self.get_pandas_function(check)
122
+ # Check if the column exists in the DataFrame
123
+ if colname not in df.columns:
124
+ self._logger.warning(f"Column {colname} not found in DataFrame.")
125
+ continue
126
+ # execute the function:
127
+ self._logger.debug(f"Exec {fname} with args {params}")
128
+ actual_value, result = fn(df, desc, colname, **params)
129
+ if result is False:
130
+ # threshold was reached
131
+ self._logger.error(
132
+ f"{task_name}: Threshold for {fname} was reached with: {actual_value} on {colname}"
133
+ )
134
+ err.append(
135
+ {
136
+ "function": fname,
137
+ "column": colname,
138
+ "value": actual_value,
139
+ "expected": params.get("value", "Unknown")
140
+ }
141
+ )
142
+
143
+ if errors:
144
+ # TODO: send a notification about threshold violation.
145
+ await self.notify(task_name, program, errors, **kwargs)
146
+
147
+ def get_pandas_function(self, payload: dict):
148
+ fname = list(payload.keys())[0]
149
+ func = None
150
+ try:
151
+ params = payload[fname]
152
+ except KeyError:
153
+ params = {}
154
+ # Extract the column name from the parameters
155
+ col_name = params.pop("column")
156
+ try:
157
+ func = getattr(colfunc, fname)
158
+ except AttributeError:
159
+ self._logger.warning(f"Function {fname} does not exist on Alert System")
160
+ return fname, col_name, func, params
161
+
162
+ def get_function(self, payload: dict):
163
+ """Get the function name, function object and parameters from the payload."""
164
+ fname = list(payload.keys())[0]
165
+ try:
166
+ params = payload[fname]
167
+ except KeyError:
168
+ params = {}
169
+ try:
170
+ func = getattr(alertfunc, fname)
171
+ except AttributeError:
172
+ try:
173
+ func = getattr(qsfunctions, fname)
174
+ except AttributeError:
175
+ try:
176
+ func = globals()[fname]
177
+ except (KeyError, AttributeError):
178
+ try:
179
+ func = getattr(builtins, fname)
180
+ except AttributeError:
181
+ func = None
182
+ if not func:
183
+ raise ConfigError(
184
+ f"Function {fname} doesn't exist on Flowtask."
185
+ )
186
+ return fname, func, params
187
+
188
+ def exec_function(self, fname, func, data, **kwargs):
189
+ self._logger.debug(f"Exec {fname} with args {kwargs}")
190
+ try:
191
+ return func(data, **kwargs)
192
+ except (TypeError, ValueError) as err:
193
+ self._logger.exception(str(err), exc_info=True, stack_info=True)
194
+ traceback.print_exc()
195
+ return None
196
+
197
+ async def process_checks(self, checks, data, task_name):
198
+ errors = []
199
+ for check in checks:
200
+ fname, fn, params = self.get_function(check)
201
+ colname, value, result = self.exec_function(fname, fn, data, **params)
202
+ if result is False:
203
+ # threshold was reached
204
+ self._logger.error(
205
+ f"{task_name}: Threshold was reached for {fname} {colname} = {value}"
206
+ )
207
+ errors.append(
208
+ {
209
+ "function": fname,
210
+ "column": colname,
211
+ "value": value,
212
+ "expected": params.get("value", "Unknown")
213
+ }
214
+ )
215
+ return errors
216
+
217
+ async def stats_checks(self, checks, stats: dict, steps: list, task_name: str):
218
+ errors = []
219
+ for fn in checks:
220
+ result = False
221
+ fname, fn, params = self.get_function(fn)
222
+ if "column" in params:
223
+ # extract the column from stats:
224
+ current_value = stats.get(params["column"], None)
225
+ if current_value is None:
226
+ self._logger.warning(f"Column {params['column']} not found in stats.")
227
+ continue
228
+ current_value = stats
229
+ elif 'component' in params:
230
+ component_name = params.pop('component')
231
+ component_dict = stats['steps'].get(component_name, {})
232
+ if component_dict is None:
233
+ self._logger.warning(f"Component {component_name} not found in stats.")
234
+ continue
235
+ if not params:
236
+ self._logger.warning(f"No key provided after 'component' for {component_name}.")
237
+ continue
238
+ dynamic_key, dyn_value = params.popitem()
239
+ # Recursively find the dictionary containing this key
240
+ result_dict = recursive_lookup(component_dict, dynamic_key)
241
+ if result_dict is None:
242
+ self._logger.warning(
243
+ f"No Dict containing '{dynamic_key}' found in {component_name}."
244
+ )
245
+ continue
246
+ current_value = result_dict
247
+ params = {
248
+ "column": dynamic_key,
249
+ "value": dyn_value
250
+ }
251
+ # Execute the query:
252
+ component, value, result = self.exec_function(fname, fn, current_value, **params)
253
+ if result is False:
254
+ # threshold was reached
255
+ self._logger.error(
256
+ f"{task_name}: Threshold for {fname} was reached with: {value} on {component}"
257
+ )
258
+ errors.append(
259
+ {
260
+ "function": fname,
261
+ "column": component,
262
+ "value": value,
263
+ "expected": params.get("value", "Unknown")
264
+ }
265
+ )
266
+ return errors
267
+
268
+ def getNotify(self, notify, **kwargs):
269
+ if notify == "telegram":
270
+ # defining the Default chat object:
271
+ recipient = Chat(**{"chat_id": EVENT_CHAT_ID, "chat_name": "Navigator"})
272
+ # send notifications to Telegram bot
273
+ args = {"bot_token": EVENT_CHAT_BOT, **kwargs}
274
+ ntf = Notify("telegram", **args)
275
+ elif notify == "slack":
276
+ recipient = Channel(
277
+ channel_id=SLACK_DEFAULT_CHANNEL,
278
+ channel_name=SLACK_DEFAULT_CHANNEL_NAME,
279
+ )
280
+ ntf = Slack()
281
+ elif notify == "email":
282
+ account = {
283
+ "host": EMAIL_HOST,
284
+ "port": EMAIL_PORT,
285
+ "username": EMAIL_USERNAME,
286
+ "password": EMAIL_PASSWORD,
287
+ **kwargs,
288
+ }
289
+ recipient = Actor(**DEFAULT_RECIPIENT)
290
+ ntf = Email(debug=True, **account)
291
+ elif notify == 'teams':
292
+ team_id = kwargs.pop("team_id", MS_TEAMS_DEFAULT_TEAMS_ID)
293
+ recipient = TeamsChannel(
294
+ name=MS_TEAMS_DEFAULT_CHANNEL_NAME,
295
+ team_id=team_id,
296
+ channel_id=MS_TEAMS_DEFAULT_CHANNEL_ID
297
+ )
298
+ ntf = Teams(
299
+ as_user=True,
300
+ team_id=team_id,
301
+ )
302
+ else:
303
+ # Any other Notify Provider:
304
+ recipient = Actor(**DEFAULT_RECIPIENT)
305
+ ntf = Notify(notify, **kwargs)
306
+ return [ntf, recipient]
307
+
308
+ async def notify(
309
+ self,
310
+ task_name: str,
311
+ program: str,
312
+ errors: list,
313
+ **kwargs
314
+ ):
315
+ for error in errors:
316
+ fname = error.get("function", "Unknown")
317
+ colname = error.get("column", "Unknown")
318
+ value = error.get("value", "Unknown")
319
+ expected = error.get("expected", "Unknown")
320
+ cPrint(
321
+ "------------"
322
+ )
323
+ cPrint(
324
+ f"- {task_name}: {fname} reached for {colname} with value: {value}, expected: {expected}",
325
+ level='CRITICAL'
326
+ )
327
+ cPrint(
328
+ "------------"
329
+ )
330
+ # Getting a Notify component based on Alert configuration:
331
+ ntf, recipients = self.getNotify(self._channel, **kwargs)
332
+ # build notification message:
333
+ err_info = '\n'.join(
334
+ [
335
+ f"- {error.get('column', 'Unknown')}: {error.get('value', 'Unknown')}"
336
+ for error in errors
337
+ ]
338
+ )
339
+ message = f"🛑 ::{ENVIRONMENT} - Task {program}.{task_name}, Error on: {err_info}"
340
+ # send the notification:
341
+ args = {"recipient": [recipients], "message": message}
342
+ if self._channel == 'teams':
343
+ channel = recipients
344
+ msg = TeamsCard(
345
+ text=str(message),
346
+ summary=f"Task Summary: {program}.{task_name}",
347
+ title=f"Task {program}.{task_name}",
348
+ )
349
+ async with ntf as conn:
350
+ return await conn.send(
351
+ recipient=channel,
352
+ message=msg
353
+ )
354
+ elif ntf.provider_type == "email":
355
+ args["subject"] = message
356
+ elif ntf.provider == "telegram":
357
+ args["disable_notification"] = True
358
+ else:
359
+ args["subject"] = message
360
+ async with ntf as t:
361
+ result = await t.send(**args)
362
+ return result
@@ -0,0 +1,131 @@
1
+ from typing import Union, Any
2
+ import pandas as pd
3
+ from navconfig.logging import logging
4
+
5
+
6
+ def average(
7
+ df: pd.DataFrame,
8
+ desc: Any,
9
+ column_name: str,
10
+ threshold: Union[int, float],
11
+ deviation: Union[int, float] = 2,
12
+ allow_below: bool = False,
13
+ allow_above: bool = False,
14
+ ) -> tuple:
15
+ """average.
16
+
17
+ Args:
18
+ df (pd.DataFrame): Dataframe.
19
+ desc (Any): Description of the DataFrame.
20
+ colname (str): Column Name.
21
+ threshold (Union[int, float]): Threshold value.
22
+ deviation (Union[int, float]): percent of deviation from the threshold
23
+ allow_below (bool): how many percent below the threshold is allowed
24
+ allow_above (bool): how many percent above the threshold is allowed
25
+
26
+ Returns:
27
+ [type]: [description]
28
+ """
29
+ value = desc.loc["mean", column_name]
30
+ allowed_deviation = threshold * deviation / 100
31
+ _min = threshold - allowed_deviation
32
+ _max = threshold + allowed_deviation
33
+ print("MIN ", _min, "MAX ", _max)
34
+ val = bool(_min <= value <= _max)
35
+ logging.debug(f"Current Average value: {value}")
36
+ if value <= _min and allow_below is True:
37
+ val = True
38
+ if value >= _max and allow_above is True:
39
+ val = True
40
+ return value, val
41
+
42
+
43
+ def between(df: pd.DataFrame, desc: Any, column_name: str, values: tuple) -> tuple:
44
+ """
45
+ Check if the values in a DataFrame column are between the given min and max values.
46
+
47
+ Args:
48
+ - df (pd.DataFrame): The DataFrame to check.
49
+ - desc (Any): The description (usually from df.describe()) of the DataFrame.
50
+ - column_name (str): The name of the column to check.
51
+ - values (tuple): A tuple containing the (min, max) values.
52
+
53
+ """
54
+ min_value = desc.loc["min", column_name]
55
+ max_value = desc.loc["max", column_name]
56
+ min_threshold, max_threshold = values
57
+ val = min_threshold <= min_value and max_value <= max_threshold
58
+ return (min_value, max_value), val
59
+
60
+
61
+ def equal(df: pd.DataFrame, desc: Any, column_name: str, values: tuple) -> tuple:
62
+ """
63
+ Check if all values in a DataFrame column are within the provided list of strings.
64
+
65
+ Args:
66
+ - df (pd.DataFrame): The DataFrame to check.
67
+ - desc (Any): The description (usually from df.describe()) of the DataFrame.
68
+ - column_name (str): The name of the column to check.
69
+ - values (tuple): A tuple containing the allowed strings.
70
+
71
+ """
72
+ return values, bool(df[column_name].isin(values).all())
73
+
74
+
75
+ def count_nulls(df: pd.DataFrame, desc: Any, column_name: str, value: int) -> tuple:
76
+ """
77
+ Check if the number of non-null values in a column is greater than a given threshold.
78
+
79
+ Args:
80
+ - df (pd.DataFrame): The DataFrame to check.
81
+ - desc (Any): The description (usually from df.describe()) of the DataFrame.
82
+ - column_name (str): The name of the column to check.
83
+ - min_length (int): The minimum number of non-null values required.
84
+
85
+ Returns:
86
+ tuple: (min_length, True/False)
87
+ """
88
+ actual_length = df[column_name].notnull().sum() # Count non-null values
89
+ return actual_length, actual_length < value
90
+
91
+ def not_null(df: pd.DataFrame, desc: Any, column_name: str):
92
+ """
93
+ Check if a DataFrame column contains only non-null values.
94
+
95
+ Args:
96
+ - df (pd.DataFrame): The DataFrame to check.
97
+ - desc (Any): The description (usually from df.describe()) of the DataFrame.
98
+ - column_name (str): The name of the column to check.
99
+
100
+ Returns:
101
+ tuple: (column_name, True/False)
102
+ """
103
+ return column_name, df[column_name].notnull().all()
104
+
105
+ def column_size(df: pd.DataFrame, desc: Any, column_name: str, min_length: int, max_length: int) -> tuple:
106
+ """
107
+ Check if all values in a string column have lengths within the specified range.
108
+
109
+ Args:
110
+ df (pd.DataFrame): The DataFrame to check.
111
+ desc (Any): Ignored, used for compatibility.
112
+ column_name (str): The name of the column to check.
113
+ min_length (int): The minimum length allowed for strings.
114
+ max_length (int): The maximum length allowed for strings.
115
+
116
+ Returns:
117
+ tuple: (column_name, min_length, max_length, True/False)
118
+ """
119
+ # Ensure the column exists
120
+ if column_name not in df.columns:
121
+ return column_name, min_length, max_length, False
122
+
123
+ # Ensure all values are strings
124
+ if not df[column_name].map(lambda x: isinstance(x, str)).all():
125
+ return column_name, min_length, max_length, False
126
+
127
+ # Check string lengths
128
+ lengths = df[column_name].str.len()
129
+ within_range = (lengths >= min_length) & (lengths <= max_length)
130
+
131
+ return (min_length, max_length), within_range.all()
@@ -0,0 +1,158 @@
1
+ from typing import Union, Tuple
2
+
3
+
4
+ def average(
5
+ data: dict,
6
+ column: str,
7
+ threshold: Union[int, float],
8
+ deviation: Union[int, float],
9
+ allow_below: bool = False,
10
+ ):
11
+ """average.
12
+
13
+ Calculates the average of a value compared with a threshold.
14
+ Args:
15
+ data (dict): extract column from data.
16
+ column (str): column to calculate.
17
+ threshold (float): value to be used for threshold
18
+ deviation (float): max deviation acceptable for threshold
19
+ allow_below (bool): if True, the threshold is not evaluated on minimum values.
20
+ """
21
+ value = data.get(column, None)
22
+ allowed_deviation = threshold * deviation / 100
23
+ _min = threshold - allowed_deviation
24
+ _max = threshold + allowed_deviation
25
+ print("MIN ", _min, "MAX ", _max)
26
+ val = _min <= value <= _max
27
+ if value <= _min and allow_below is True:
28
+ val = True
29
+ return column, value, val
30
+
31
+
32
+ def max_value(
33
+ data: dict, column: str, value: Union[int, float]
34
+ ) -> Tuple[str, Union[int, float], bool]:
35
+ """
36
+ Checks if the actual value of a specified column in the data is less than or equal to the
37
+ given threshold value.
38
+
39
+ Args:
40
+ data (dict): Dictionary containing the data to be checked.
41
+ column (str): Name of the column in the data whose value needs to be checked.
42
+ value (Union[int, float]): The threshold value. The actual value in the data
43
+ should be less than or equal to this.
44
+
45
+ Returns:
46
+ tuple: A tuple containing:
47
+ - column (str): Name of the column that was checked.
48
+ - actual_value (Union[int, float]): The actual value from the data for the specified column.
49
+ - val (bool): True if the actual value is less than or equal to the threshold, False otherwise.
50
+ """
51
+ actual_value = data.get(column, None)
52
+ val = actual_value <= value
53
+ return column, actual_value, val
54
+
55
+
56
+ def min_value(
57
+ data: dict, column: str, value: Union[int, float]
58
+ ) -> Tuple[str, Union[int, float], bool]:
59
+ """
60
+ Checks if the actual value of a specified column in the data is greater than or
61
+ equal to the given threshold value.
62
+
63
+ Args:
64
+ data (dict): Dictionary containing the data to be checked.
65
+ column (str): Name of the column in the data whose value needs to be checked.
66
+ value (Union[int, float]): The threshold value. The actual value in the data
67
+ should be greater than or equal to this.
68
+
69
+ Returns:
70
+ tuple: A tuple containing:
71
+ - column (str): Name of the column that was checked.
72
+ - actual_value (Union[int, float]): The actual value from the data for the specified column.
73
+ - val (bool): True if the actual value is greater than or equal
74
+ to the threshold, False otherwise.
75
+ """
76
+ actual_value = data.get(column, None)
77
+ val = actual_value >= value
78
+ return column, actual_value, val
79
+
80
+ def has_columns(data: dict, column: str = 'columns', value: list = []) -> Tuple[str, Union[int, float], bool]:
81
+ """
82
+ Check if the actual value on a specified column in the data is equal to the given threshold value.
83
+ """
84
+ actual_value = data.get(column, None)
85
+ val = actual_value in value
86
+ return column, actual_value, val
87
+
88
+ def missing_columns(data: dict, column: str = 'columns', value: list = []) -> Tuple[str, Union[int, float], bool]:
89
+ """
90
+ Check if all required columns exist in the 'columns' field of the given data.
91
+
92
+ :param data: Dictionary containing the structure with "columns".
93
+ :param column: Name of the column to check (by default: "columns").
94
+ :param value: List of columns to check.
95
+ :return: Tuple (checked_key, missing_columns, bool)
96
+ """
97
+ available_columns = data.get(column, None)
98
+ missing_columns = [col for col in value if col not in available_columns]
99
+ return "columns", missing_columns, len(missing_columns) == 0
100
+
101
+ def equal(
102
+ data: dict, column: str, value: Union[int, float]
103
+ ) -> Tuple[str, Union[int, float], bool]:
104
+ """
105
+ Check if the actual value on a specified column in the data is equal to the given threshold value.
106
+ """
107
+ actual_value = data.get(column, None)
108
+ val = actual_value == value
109
+ return column, actual_value, val
110
+
111
+ def gt(
112
+ data: dict, column: str, value: Union[int, float]
113
+ ) -> Tuple[str, Union[int, float], bool]:
114
+ """
115
+ Check if the actual value on a specified column in the data is greater than to the given threshold value.
116
+ """
117
+ try:
118
+ actual_value = data.get(column, None)
119
+ val = float(actual_value) >= float(value)
120
+ return column, actual_value, val
121
+ except Exception as e:
122
+ return column, None, False
123
+
124
+ def lt(
125
+ data: dict, column: str, value: Union[int, float]
126
+ ) -> Tuple[str, Union[int, float], bool]:
127
+ """
128
+ Check if the actual value on a specified column in the data is less than to the given threshold value.
129
+ """
130
+ try:
131
+ actual_value = data.get(column, None)
132
+ val = float(actual_value) <= float(value)
133
+ return column, actual_value, val
134
+ except Exception as e:
135
+ return column, None, False
136
+
137
+ def between(data: dict, column: str, value: list) -> Tuple[str, Union[int, float], bool]:
138
+ """
139
+ Checks if the actual value in the specified column is between two given values.
140
+
141
+ Args:
142
+ data (dict): Dictionary containing the column data.
143
+ column (str): Column name to evaluate.
144
+ value (list): A list containing two values: [min_value, max_value].
145
+
146
+ Returns:
147
+ tuple: (column, actual_value, True/False)
148
+ """
149
+ if not isinstance(value, list) or len(value) != 2:
150
+ raise ValueError(f"Invalid value for 'between': {value}. Must be a list of two numbers.")
151
+
152
+ min_val, max_val = value # Unpack min and max
153
+ actual_value = data.get(column, None) # Extract the value from data
154
+
155
+ if actual_value is None:
156
+ return column, None, False # Column not found
157
+
158
+ return column, actual_value, min_val <= actual_value <= max_val
@@ -0,0 +1,12 @@
1
+ from ...utils import cPrint
2
+ from .abstract import AbstractEvent
3
+
4
+
5
+ class Dummy(AbstractEvent):
6
+ async def __call__(self, *args, **kwargs):
7
+ status = kwargs.pop("status", "event")
8
+ task = kwargs.pop("task", None)
9
+ cPrint(
10
+ f" == TASK {task} EXECUTED {status} WITH: {self._kwargs}, {args}, {kwargs} === ",
11
+ level="INFO",
12
+ )