flowtask 5.8.4__cp39-cp39-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-39-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-39-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-39-x86_64-linux-gnu.so +0 -0
  377. flowtask/parsers/json.c +11968 -0
  378. flowtask/parsers/json.cpython-39-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-39-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-39-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-39-x86_64-linux-gnu.so +0 -0
  440. flowtask/utils/json.cpp +13349 -0
  441. flowtask/utils/json.cpython-39-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-39-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,273 @@
1
+ import asyncio
2
+ from decimal import Decimal
3
+ from typing import Any
4
+ from collections.abc import Callable
5
+ from pathlib import Path, PurePath
6
+ import aiofiles
7
+ import numpy as np
8
+ import pandas as pd
9
+ from navconfig.logging import logging
10
+ from asyncdb.exceptions import NoDataFound, ProviderError
11
+ from querysource.queries.qs import QS
12
+ from ..conf import TASK_PATH
13
+ from ..exceptions import ComponentError, NotSupported, DataNotFound, FileError
14
+ from .IteratorBase import IteratorBase
15
+ from ..interfaces import TemplateSupport, DBSupport
16
+
17
+
18
+ class QueryIterator(DBSupport, TemplateSupport, IteratorBase):
19
+ """
20
+ QueryIterator
21
+
22
+
23
+ Overview
24
+
25
+ This component creates a Pandas Iterator from a QuerySource query,
26
+ allowing for the iteration over data returned from a query.
27
+
28
+ .. table:: Properties
29
+ :widths: auto
30
+
31
+
32
+ +------------------------+----------+-----------+--------------------------------------------------------+
33
+ | Name | Required | Summary |
34
+ +------------------------+----------+-----------+--------------------------------------------------------+
35
+ | file_sql | No | The SQL file to read the query from. |
36
+ +------------------------+----------+-----------+--------------------------------------------------------+
37
+ | query_slug | No | The query slug to use for fetching data. |
38
+ +------------------------+----------+-----------+--------------------------------------------------------+
39
+ | query | No | The raw SQL query string to execute. |
40
+ +------------------------+----------+-----------+--------------------------------------------------------+
41
+ | conditions | No | Conditions to apply to the query. |
42
+ +------------------------+----------+-----------+--------------------------------------------------------+
43
+ | columns | No | Specific columns to extract from the result. |
44
+ +------------------------+----------+-----------+--------------------------------------------------------+
45
+ | use_template | No | If True, use a query template for the query. Default is False. |
46
+ +------------------------+----------+-----------+--------------------------------------------------------+
47
+ | drop_empty | No | If True, drop empty rows and columns from the DataFrame. |
48
+ +------------------------+----------+-----------+--------------------------------------------------------+
49
+ | dropna | No | Subset of columns to check for NaN values before dropping rows. |
50
+ +------------------------+----------+-----------+--------------------------------------------------------+
51
+
52
+ Returns
53
+
54
+ This component returns the last value generated by the iteration process. Typically,
55
+ it returns a pandas DataFrame containing the query results.
56
+ """
57
+
58
+ def __init__(
59
+ self,
60
+ loop: asyncio.AbstractEventLoop = None,
61
+ job: Callable = None,
62
+ stat: Callable = None,
63
+ **kwargs,
64
+ ):
65
+ self.pk = []
66
+ self.data = None
67
+ self._iterator: Any = None
68
+ self._variables = {}
69
+ self.vars = {}
70
+ self._columns = []
71
+ self._query: str = None
72
+ self.use_template: bool = bool(kwargs.get("use_template", False))
73
+ super().__init__(loop=loop, job=job, stat=stat, **kwargs)
74
+
75
+ async def open_sqlfile(self, file: PurePath, **kwargs) -> str:
76
+ if file.exists() and file.is_file():
77
+ content = None
78
+ # open SQL File:
79
+ async with aiofiles.open(file, "r+") as afp:
80
+ content = await afp.read()
81
+ # check if we need to replace masks
82
+ if hasattr(self, "masks"):
83
+ content = self.mask_replacement(content)
84
+ if self.use_template is True:
85
+ content = self._templateparser.from_string(content, kwargs)
86
+ return content
87
+ else:
88
+ raise FileError(f"{self.__name__}: Missing SQL File: {file}")
89
+
90
+ async def start(self, **kwargs):
91
+ """Getting kind of Query."""
92
+ if hasattr(self, "file_sql"):
93
+ try:
94
+ file_path = Path(TASK_PATH).joinpath(
95
+ self._program, "sql", self.file_sql
96
+ )
97
+ if file_path.exists() and file_path.is_file():
98
+ self._query = await self.open_sqlfile(file_path)
99
+ except Exception as e:
100
+ raise FileError(
101
+ f"File SQL doesn't exists: {self.file_sql!s}, {e}"
102
+ ) from e
103
+ elif hasattr(self, "query_slug"):
104
+ self.query_slug = self.mask_replacement(self.query_slug)
105
+ self._query = self.query_slug
106
+ elif hasattr(self, "query"):
107
+ self._query = self.query
108
+ if hasattr(self, "masks"):
109
+ self._query = self.mask_replacement(self._query)
110
+ try:
111
+ self._query = self._query.format(**self._variables)
112
+ except Exception as err:
113
+ print("Error replacing Vars in Query: ", err)
114
+ if hasattr(self, "conditions"):
115
+ self.set_conditions("conditions")
116
+ await super().start(**kwargs)
117
+ self.processing_credentials()
118
+ return True
119
+
120
+ async def close(self, job=None):
121
+ close = getattr(job, "close", None)
122
+ if job:
123
+ if asyncio.iscoroutinefunction(close):
124
+ await job.close()
125
+ else:
126
+ job.close()
127
+
128
+ def createJob(self, target, params, row):
129
+ """Create the Job Component."""
130
+ self._result = self.data
131
+ dt = {}
132
+ for column in self._columns:
133
+ value = row[column]
134
+ if isinstance(value, (int, np.int64, np.integer)):
135
+ value = int(value)
136
+ elif isinstance(value, (float, Decimal)):
137
+ value = float(value)
138
+ self.setVar(column, value)
139
+ # print('ITER ', value, type(value))
140
+ params[column] = value
141
+ dt[column] = value
142
+ for name, value in self.vars.items():
143
+ # TODO: check this logic
144
+ print("VARS: ", name, value, column)
145
+ val = row[column]
146
+ # print('VAL ', val)
147
+ # need to build this attribute
148
+ if isinstance(value, list):
149
+ pass
150
+ # TODO: logic to use functions with dataframes
151
+ # # need to calculate the value
152
+ else:
153
+ if "{" in str(value):
154
+ value = value.format(**dt)
155
+ else:
156
+ value = val
157
+ params[name] = value
158
+ self.setVar(name, value)
159
+ return self.get_job(target, **params)
160
+
161
+ async def run(self):
162
+ """Async Run Method."""
163
+ # first: getting data:
164
+ df = None
165
+ result = None
166
+ if not self._query:
167
+ raise ComponentError("QueryToPandas: Empty Query/Slug or File")
168
+ if hasattr(self, "query") or hasattr(self, "file_sql"):
169
+ try:
170
+ connection = self.get_connection(event_loop=self._loop)
171
+ except Exception as err:
172
+ self._logger.exception(err, stack_info=True)
173
+ raise
174
+ async with await connection.connection() as conn:
175
+ try:
176
+ res, error = await conn.query(self._query)
177
+ if error:
178
+ self._logger.error(f"QueryIterator: {error}")
179
+ raise NoDataFound(error)
180
+ result = [dict(row) for row in res]
181
+ df = await self.get_dataframe(result)
182
+ except NoDataFound:
183
+ result = []
184
+ except Exception as err:
185
+ self._logger.error(err)
186
+ raise
187
+ elif hasattr(self, "query_slug"):
188
+ conditions = {}
189
+ if hasattr(self, "conditions"):
190
+ conditions = self.conditions
191
+ result = await self.get_query(self._query, conditions)
192
+ df = await self.get_dataframe(result)
193
+ else:
194
+ raise NotSupported(f"{self.__name__}: Method not allowed")
195
+ # getting the iterator:
196
+ if not hasattr(self, "columns"):
197
+ # iterate over the total columns of dataframe
198
+ self._columns = df.columns
199
+ else:
200
+ self._columns = self.columns
201
+ self._iterator = df.iterrows()
202
+ # iterate over next task
203
+ step, target, params = self.get_step()
204
+ step_name = step.name
205
+ for index, row in self._iterator:
206
+ self._logger.debug(f"ITER: index:{index} row: {row}")
207
+ # iterate over every row
208
+ # get I got all values, create a job:
209
+ job = self.createJob(target, params, row)
210
+ # print('JOB: ', job)
211
+ if job:
212
+ try:
213
+ self._result = await self.async_job(job, step_name)
214
+ except (NoDataFound, DataNotFound) as err:
215
+ # its a data component a no data was found
216
+ self._logger.debug(f"Data not Found for Task {step_name}, got: {err}")
217
+ continue
218
+ except (ProviderError, ComponentError) as err:
219
+ raise ComponentError(f"Error on {step_name}, error: {err}") from err
220
+ except NotSupported as err:
221
+ raise NotSupported(f"Not Supported: {err}") from err
222
+ except Exception as err:
223
+ raise ComponentError(
224
+ f"Component Error {step_name}, error: {err}"
225
+ ) from err
226
+ finally:
227
+ await self.close(job)
228
+ # returning last value generated by iteration
229
+ return self._result
230
+
231
+ async def get_dataframe(self, result) -> pd.DataFrame:
232
+ try:
233
+ df = pd.DataFrame(result)
234
+ except Exception as err:
235
+ self._logger.exception(err, stack_info=True)
236
+ # Attempt to infer better dtypes for object columns.
237
+ df.infer_objects()
238
+ df = df.convert_dtypes(convert_string=True)
239
+ if hasattr(self, "drop_empty"):
240
+ df.dropna(axis=1, how="all", inplace=True)
241
+ df.dropna(axis=0, how="all", inplace=True)
242
+ if hasattr(self, "dropna"):
243
+ df.dropna(subset=self.dropna, how="all", inplace=True)
244
+ return df
245
+
246
+ async def get_query(self, slug, conditions: dict = None):
247
+ result: Any = []
248
+ if not conditions:
249
+ conditions = self.conditions
250
+ try:
251
+ qry = QS(slug=slug, conditions=conditions, loop=self._loop, lazy=True)
252
+ await qry.get_query()
253
+ except (DataNotFound, NoDataFound) as ex:
254
+ raise DataNotFound(f"{ex!s}") from ex
255
+ except Exception as err:
256
+ raise ComponentError(f"{err}") from err
257
+ try:
258
+ res, error = await qry.query()
259
+ if not res:
260
+ raise NoDataFound(f"{slug}: Data Not Found")
261
+ if error:
262
+ raise ComponentError(f"Error on Query: {error}")
263
+ result = result + [dict(row) for row in res]
264
+ return result
265
+ except (DataNotFound, NoDataFound) as err:
266
+ raise DataNotFound(f"{err!s}") from err
267
+ except Exception as err:
268
+ raise ComponentError(f"Error on Query: {err}") from err
269
+ finally:
270
+ try:
271
+ await qry.close()
272
+ except Exception as err:
273
+ self._logger.exception(err, stack_info=True)
@@ -0,0 +1,327 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Any
3
+ from collections.abc import Callable
4
+ import asyncio
5
+ from datetime import datetime
6
+ from pathlib import PosixPath
7
+ from tqdm import tqdm
8
+ import orjson
9
+ from datamodel.parsers.json import json_encoder
10
+ from asyncdb.drivers.postgres import postgres
11
+ from asyncdb.exceptions import ProviderError
12
+ from ..exceptions import ComponentError
13
+ from ..utils import SafeDict
14
+ from ..conf import default_dsn
15
+ from .flow import FlowComponent
16
+
17
+
18
+ class QueryToInsert(FlowComponent):
19
+ """
20
+ QueryToInsert.
21
+
22
+
23
+ Overview
24
+
25
+ This component allows me to insert data into a database schema
26
+
27
+ .. table:: Properties
28
+ :widths: auto
29
+
30
+
31
+ +--------------+----------+-----------+-------------------------------------------------------+
32
+ | Name | Required | Summary |
33
+ +--------------+----------+-----------+-------------------------------------------------------+
34
+ | schema | Yes | Name of the schema where is to the table |
35
+ +--------------+----------+-----------+-------------------------------------------------------+
36
+ | tablename | Yes | Name of the table in the database |
37
+ +--------------+----------+-----------+-------------------------------------------------------+
38
+ | action | Yes | Sets the action to execute in this case an insert |
39
+ +--------------+----------+-----------+-------------------------------------------------------+
40
+ | pk | Yes | Primary key to the table in the database |
41
+ +--------------+----------+-----------+-------------------------------------------------------+
42
+ | directory | Yes | Source directory where the file is located |
43
+ +--------------+----------+-----------+-------------------------------------------------------+
44
+ | filter | Yes | This attribute allows me to apply a filter to the data |
45
+ +--------------+----------+-----------+-------------------------------------------------------+
46
+
47
+
48
+
49
+ Return the list of arbitrary days
50
+
51
+
52
+
53
+ Example:
54
+
55
+ ```yaml
56
+ QueryToInsert:
57
+ schema: public
58
+ tablename: queries
59
+ action: insert
60
+ pk:
61
+ - query_slug
62
+ directory: /home/ubuntu/symbits/
63
+ filter:
64
+ query_slug: walmart_stores
65
+ ```
66
+
67
+ """
68
+ """
69
+ QueryToInsert
70
+
71
+ Overview
72
+
73
+ This component generates SQL INSERT or UPDATE statements from a query and saves them to a file.
74
+
75
+ .. table:: Properties
76
+ :widths: auto
77
+
78
+
79
+ +------------------------+----------+-----------+-------------------------------------------------------+
80
+ | Name | Required | Summary |
81
+ +------------------------+----------+-----------+-------------------------------------------------------+
82
+ | schema | Yes | The schema of the table to insert or update data in. |
83
+ +------------------------+----------+-----------+-------------------------------------------------------+
84
+ | tablename | Yes | The name of the table to insert or update data in. |
85
+ +------------------------+----------+-----------+-------------------------------------------------------+
86
+ | action | Yes | The action to perform, either "insert" or "update". |
87
+ +------------------------+----------+-----------+-------------------------------------------------------+
88
+ | pk | Yes | The primary key(s) of the table. |
89
+ +------------------------+----------+-----------+-------------------------------------------------------+
90
+ | filter | No | Filters to apply to the query. |
91
+ +------------------------+----------+-----------+-------------------------------------------------------+
92
+ | directory | Yes | The directory to save the SQL file. |
93
+ +------------------------+----------+-----------+-------------------------------------------------------+
94
+ | fields | No | Specific fields to select in the query. |
95
+ +------------------------+----------+-----------+-------------------------------------------------------+
96
+
97
+ Returns
98
+
99
+ This component returns True if the SQL file is successfully created, otherwise raises a ComponentError.
100
+ """
101
+ where = ""
102
+ query = "SELECT {fields} FROM {schema}.{table} {where} order by ctid;"
103
+ insert = "INSERT INTO {}.{} ({}) VALUES({}) {};\n"
104
+ conflict = "ON CONFLICT ({}) DO UPDATE SET {}"
105
+ conflict_update = "{} = EXCLUDED.{}"
106
+ update = "UPDATE {}.{} SET {} {};\n"
107
+
108
+ def __init__(
109
+ self,
110
+ loop: asyncio.AbstractEventLoop = None,
111
+ job: Callable = None,
112
+ stat: Callable = None,
113
+ **kwargs,
114
+ ):
115
+ """Init Method."""
116
+ self.action: str = None
117
+ self.schema: str = ""
118
+ self.tablename: str = ""
119
+ self.pk: Any = None
120
+ self.filter: Any = None
121
+ self._connection: Callable = None
122
+ self._fields = kwargs.pop('fields', [])
123
+ super(QueryToInsert, self).__init__(
124
+ loop=loop,
125
+ job=job,
126
+ stat=stat,
127
+ **kwargs
128
+ )
129
+
130
+ def _escapeString(self, value):
131
+ v = value if value != "None" or value is not None else ""
132
+ v = str(v).replace("'", "''") if type(v) == str else v
133
+ v = "'{}'".format(v) if type(v) == str else v
134
+ v = "array{}".format(v) if type(v) == list else v
135
+ return v
136
+
137
+ async def start(self, **kwargs):
138
+ """Start."""
139
+ if not hasattr(self, "schema"):
140
+ raise ComponentError("Schema not defined:")
141
+ if not hasattr(self, "tablename"):
142
+ raise ComponentError("Tablename not defined:")
143
+ if not hasattr(self, "action"):
144
+ raise ComponentError("Action not defined:")
145
+ if not hasattr(self, "pk"):
146
+ raise ComponentError("Primary keys not defined:")
147
+ else:
148
+ if isinstance(self.pk, str):
149
+ try:
150
+ self.pk = orjson.loads(self.pk)
151
+ except Exception:
152
+ self.pk = self.pk
153
+ if not hasattr(self, "directory"):
154
+ raise ComponentError("Directory not defined:")
155
+ if hasattr(self, "filter"):
156
+ filter = []
157
+ if isinstance(self.filter, str):
158
+ self.filter = orjson.loads(self.filter)
159
+ for key, value in self.filter.items():
160
+ filter.append(
161
+ "{} = {}".format(
162
+ key, ("'{}'".format(value) if type(value) == str else value)
163
+ )
164
+ )
165
+ if len(filter) > 0:
166
+ self.where = "WHERE {}".format(" AND ".join(filter))
167
+ today = datetime.today().strftime("%Y-%m-%d")
168
+ # Create directory if not exists
169
+ try:
170
+ PosixPath(self.directory).mkdir(parents=True, exist_ok=True)
171
+ except Exception as err:
172
+ self.logger.error(f"Error creating directory {self.directory}: {err}")
173
+ raise ComponentError(
174
+ f"Error creating directory {self.directory}: {err}"
175
+ ) from err
176
+ self.filename = PosixPath(
177
+ self.directory,
178
+ "{}_{}_{}.{}.sql".format(today, self.action, self.schema, self.tablename),
179
+ )
180
+ if not self._fields:
181
+ fields = '*'
182
+ else:
183
+ fields = ', '.join(self._fields)
184
+ self.query = self.query.format_map(
185
+ SafeDict(fields=fields)
186
+ )
187
+ self.query = self.query.format(
188
+ schema=self.schema,
189
+ table=self.tablename,
190
+ where=self.where
191
+ )
192
+ self._logger.notice(
193
+ f"Query: {self.query}"
194
+ )
195
+ return True
196
+
197
+ async def get_connection(self):
198
+ try:
199
+ self._connection = postgres(dsn=default_dsn, loop=self._loop)
200
+ await self._connection.connection()
201
+ except Exception as err:
202
+ raise ProviderError(f"Error configuring pg Connection: {err!s}") from err
203
+ return self._connection
204
+
205
+ async def run(self):
206
+ """Async Method."""
207
+ # get connection
208
+ self._connection = await self.get_connection()
209
+ res, err = await self._connection.query(self.query)
210
+ if err:
211
+ raise ComponentError(
212
+ 'Query Error "{}": {}'.format(self.query, err)
213
+ )
214
+ colinfo = self.column_info("{}.{}".format(self.schema, self.tablename))
215
+ if res:
216
+ query = []
217
+ if self.action == "insert":
218
+ total = len(res)
219
+ with tqdm(total=total) as pbar:
220
+ for row in res:
221
+ columns_update = row.keys()
222
+ columns = row.keys()
223
+ values = []
224
+ for col in row.keys():
225
+ values.append(self.get_values(col, colinfo[col], row[col]))
226
+ update = ", ".join(
227
+ [self.conflict_update.format(c, c) for c in columns_update]
228
+ )
229
+ conflict = self.conflict.format(",\n".join(self.pk), update)
230
+ query.append(
231
+ self.insert.format(
232
+ self.schema,
233
+ self.tablename,
234
+ ", ".join(columns),
235
+ ", ".join(values),
236
+ conflict,
237
+ )
238
+ )
239
+ pbar.update(1)
240
+ elif self.action == "update":
241
+ for row in res:
242
+ columns = row.keys()
243
+ values = []
244
+ for col in row.keys():
245
+ values.append(self.get_values(col, colinfo[col], row[col]))
246
+ vals = dict(zip(list(columns), values))
247
+ pkwhere = "AND".join(["{}={}".format(v, vals[v]) for v in self.pk])
248
+ where = (
249
+ "{} AND {}".format(self.where, pkwhere)
250
+ if self.where != ""
251
+ else "WHERE {}".format(pkwhere)
252
+ )
253
+ update_list = ["{}={}".format(k, v) for k, v in vals.items()]
254
+ query.append(
255
+ self.update.format(
256
+ self.schema, self.tablename, ", ".join(update_list), where
257
+ )
258
+ )
259
+
260
+ f = open(self.filename, "w")
261
+ f.write("".join(query))
262
+ f.close()
263
+ self._result = "".join(query)
264
+ self.add_metric('NUM_ROWS', len(query))
265
+ self.add_metric('QUERY', self.query)
266
+ # return self._result
267
+ return True
268
+ else:
269
+ raise ComponentError(
270
+ "Error creating Query File: Empty Result."
271
+ )
272
+
273
+ def close(self):
274
+ """Method."""
275
+ pass
276
+
277
+ def column_info(self, table):
278
+ result = None
279
+ sql = f"""
280
+ SELECT attname AS column_name, atttypid::regtype AS data_type, attnotnull::boolean as notnull
281
+ FROM pg_attribute WHERE attrelid = '{table}'::regclass AND attnum > 0 AND NOT attisdropped
282
+ ORDER BY attnum"""
283
+ db = postgres(dsn=default_dsn)
284
+ conn = db.connect()
285
+ result, error = conn.fetchall(sql)
286
+ if error:
287
+ raise ComponentError(f"Error executing query: {error}")
288
+ if result:
289
+ return {item["column_name"]: item["data_type"] for item in result}
290
+ else:
291
+ print(f"The table {self.schema}.{self.tablename} does not exist")
292
+ return None
293
+
294
+ def get_values(self, column, type, value):
295
+ if value is None or value == "None":
296
+ return "NULL"
297
+ elif type in [
298
+ "text",
299
+ "character varying",
300
+ "timestamp with time zone",
301
+ "timestamp without time zone",
302
+ "date",
303
+ "uuid",
304
+ "inet",
305
+ ]:
306
+ return "'{}'".format(str(value).replace("'", "''"))
307
+ elif type in ["hstore"]:
308
+ return "'{}'".format(
309
+ ", ".join(
310
+ [
311
+ '"{}"=>"{}"'.format(k, v).replace("'", "''")
312
+ for k, v in value.items()
313
+ ]
314
+ )
315
+ )
316
+ elif type in ["jsonb"]:
317
+ return "'{}'".format(json_encoder(value).replace("'", "''"))
318
+ elif type in ["character varying[]"]:
319
+ return "'{{{}}}'".format(
320
+ ", ".join(['"{}"'.format(v) for v in value]).replace("'", "''")
321
+ )
322
+ elif type in ["integer[]"]:
323
+ return "'{{{}}}'".format(
324
+ ", ".join([str(v) for v in value]).replace("'", "''")
325
+ )
326
+ else:
327
+ return str(value)