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.
- flowtask/__init__.py +93 -0
- flowtask/__main__.py +38 -0
- flowtask/bots/__init__.py +6 -0
- flowtask/bots/check.py +93 -0
- flowtask/bots/codebot.py +51 -0
- flowtask/components/ASPX.py +148 -0
- flowtask/components/AddDataset.py +352 -0
- flowtask/components/Amazon.py +523 -0
- flowtask/components/AutoTask.py +314 -0
- flowtask/components/Azure.py +80 -0
- flowtask/components/AzureUsers.py +106 -0
- flowtask/components/BaseAction.py +91 -0
- flowtask/components/BaseLoop.py +198 -0
- flowtask/components/BestBuy.py +800 -0
- flowtask/components/CSVToGCS.py +120 -0
- flowtask/components/CompanyScraper/__init__.py +1 -0
- flowtask/components/CompanyScraper/parsers/__init__.py +6 -0
- flowtask/components/CompanyScraper/parsers/base.py +102 -0
- flowtask/components/CompanyScraper/parsers/explorium.py +192 -0
- flowtask/components/CompanyScraper/parsers/leadiq.py +206 -0
- flowtask/components/CompanyScraper/parsers/rocket.py +133 -0
- flowtask/components/CompanyScraper/parsers/siccode.py +109 -0
- flowtask/components/CompanyScraper/parsers/visualvisitor.py +130 -0
- flowtask/components/CompanyScraper/parsers/zoominfo.py +118 -0
- flowtask/components/CompanyScraper/scrapper.py +1054 -0
- flowtask/components/CopyTo.py +177 -0
- flowtask/components/CopyToBigQuery.py +243 -0
- flowtask/components/CopyToMongoDB.py +291 -0
- flowtask/components/CopyToPg.py +609 -0
- flowtask/components/CopyToRethink.py +207 -0
- flowtask/components/CreateGCSBucket.py +102 -0
- flowtask/components/CreateReport/CreateReport.py +228 -0
- flowtask/components/CreateReport/__init__.py +9 -0
- flowtask/components/CreateReport/charts/__init__.py +15 -0
- flowtask/components/CreateReport/charts/bar.py +51 -0
- flowtask/components/CreateReport/charts/base.py +66 -0
- flowtask/components/CreateReport/charts/pie.py +64 -0
- flowtask/components/CreateReport/utils.py +9 -0
- flowtask/components/CustomerSatisfaction.py +196 -0
- flowtask/components/DataInput.py +200 -0
- flowtask/components/DateList.py +255 -0
- flowtask/components/DbClient.py +163 -0
- flowtask/components/DialPad.py +146 -0
- flowtask/components/DocumentDBQuery.py +200 -0
- flowtask/components/DownloadFrom.py +371 -0
- flowtask/components/DownloadFromD2L.py +113 -0
- flowtask/components/DownloadFromFTP.py +181 -0
- flowtask/components/DownloadFromIMAP.py +315 -0
- flowtask/components/DownloadFromS3.py +198 -0
- flowtask/components/DownloadFromSFTP.py +265 -0
- flowtask/components/DownloadFromSharepoint.py +110 -0
- flowtask/components/DownloadFromSmartSheet.py +114 -0
- flowtask/components/DownloadS3File.py +229 -0
- flowtask/components/Dummy.py +59 -0
- flowtask/components/DuplicatePhoto.py +411 -0
- flowtask/components/EmployeeEvaluation.py +237 -0
- flowtask/components/ExecuteSQL.py +323 -0
- flowtask/components/ExtractHTML.py +178 -0
- flowtask/components/FileBase.py +178 -0
- flowtask/components/FileCopy.py +181 -0
- flowtask/components/FileDelete.py +82 -0
- flowtask/components/FileExists.py +146 -0
- flowtask/components/FileIteratorDelete.py +112 -0
- flowtask/components/FileList.py +194 -0
- flowtask/components/FileOpen.py +75 -0
- flowtask/components/FileRead.py +120 -0
- flowtask/components/FileRename.py +106 -0
- flowtask/components/FilterIf.py +284 -0
- flowtask/components/FilterRows/FilterRows.py +200 -0
- flowtask/components/FilterRows/__init__.py +10 -0
- flowtask/components/FilterRows/functions.py +4 -0
- flowtask/components/GCSToBigQuery.py +103 -0
- flowtask/components/GoogleA4.py +150 -0
- flowtask/components/GoogleGeoCoding.py +344 -0
- flowtask/components/GooglePlaces.py +315 -0
- flowtask/components/GoogleSearch.py +539 -0
- flowtask/components/HTTPClient.py +268 -0
- flowtask/components/ICIMS.py +146 -0
- flowtask/components/IF.py +179 -0
- flowtask/components/IcimsFolderCopy.py +173 -0
- flowtask/components/ImageFeatures/__init__.py +5 -0
- flowtask/components/ImageFeatures/process.py +233 -0
- flowtask/components/IteratorBase.py +251 -0
- flowtask/components/LangchainLoader/__init__.py +5 -0
- flowtask/components/LangchainLoader/loader.py +194 -0
- flowtask/components/LangchainLoader/loaders/__init__.py +22 -0
- flowtask/components/LangchainLoader/loaders/abstract.py +362 -0
- flowtask/components/LangchainLoader/loaders/basepdf.py +50 -0
- flowtask/components/LangchainLoader/loaders/docx.py +91 -0
- flowtask/components/LangchainLoader/loaders/html.py +119 -0
- flowtask/components/LangchainLoader/loaders/pdfblocks.py +146 -0
- flowtask/components/LangchainLoader/loaders/pdfmark.py +79 -0
- flowtask/components/LangchainLoader/loaders/pdftables.py +135 -0
- flowtask/components/LangchainLoader/loaders/qa.py +67 -0
- flowtask/components/LangchainLoader/loaders/txt.py +55 -0
- flowtask/components/LeadIQ.py +650 -0
- flowtask/components/Loop.py +253 -0
- flowtask/components/Lowes.py +334 -0
- flowtask/components/MS365Usage.py +156 -0
- flowtask/components/MSTeamsMessages.py +320 -0
- flowtask/components/MarketClustering.py +1051 -0
- flowtask/components/MergeFiles.py +362 -0
- flowtask/components/MilvusOutput.py +87 -0
- flowtask/components/NearByStores.py +175 -0
- flowtask/components/NetworkNinja/__init__.py +6 -0
- flowtask/components/NetworkNinja/models/__init__.py +52 -0
- flowtask/components/NetworkNinja/models/abstract.py +177 -0
- flowtask/components/NetworkNinja/models/account.py +39 -0
- flowtask/components/NetworkNinja/models/client.py +19 -0
- flowtask/components/NetworkNinja/models/district.py +14 -0
- flowtask/components/NetworkNinja/models/events.py +101 -0
- flowtask/components/NetworkNinja/models/forms.py +499 -0
- flowtask/components/NetworkNinja/models/market.py +16 -0
- flowtask/components/NetworkNinja/models/organization.py +34 -0
- flowtask/components/NetworkNinja/models/photos.py +125 -0
- flowtask/components/NetworkNinja/models/project.py +44 -0
- flowtask/components/NetworkNinja/models/region.py +28 -0
- flowtask/components/NetworkNinja/models/store.py +203 -0
- flowtask/components/NetworkNinja/models/user.py +151 -0
- flowtask/components/NetworkNinja/router.py +854 -0
- flowtask/components/Odoo.py +175 -0
- flowtask/components/OdooInjector.py +192 -0
- flowtask/components/OpenFromXML.py +126 -0
- flowtask/components/OpenWeather.py +41 -0
- flowtask/components/OpenWithBase.py +616 -0
- flowtask/components/OpenWithPandas.py +715 -0
- flowtask/components/PGPDecrypt.py +199 -0
- flowtask/components/PandasIterator.py +187 -0
- flowtask/components/PandasToFile.py +189 -0
- flowtask/components/Paradox.py +339 -0
- flowtask/components/ParamIterator.py +117 -0
- flowtask/components/ParseHTML.py +84 -0
- flowtask/components/PlacerStores.py +249 -0
- flowtask/components/Pokemon.py +507 -0
- flowtask/components/PositiveBot.py +62 -0
- flowtask/components/PowerPointSlide.py +400 -0
- flowtask/components/PrintMessage.py +127 -0
- flowtask/components/ProductCompetitors/__init__.py +5 -0
- flowtask/components/ProductCompetitors/parsers/__init__.py +7 -0
- flowtask/components/ProductCompetitors/parsers/base.py +72 -0
- flowtask/components/ProductCompetitors/parsers/bestbuy.py +86 -0
- flowtask/components/ProductCompetitors/parsers/lowes.py +103 -0
- flowtask/components/ProductCompetitors/scrapper.py +155 -0
- flowtask/components/ProductCompliant.py +169 -0
- flowtask/components/ProductInfo/__init__.py +1 -0
- flowtask/components/ProductInfo/parsers/__init__.py +5 -0
- flowtask/components/ProductInfo/parsers/base.py +83 -0
- flowtask/components/ProductInfo/parsers/brother.py +97 -0
- flowtask/components/ProductInfo/parsers/canon.py +167 -0
- flowtask/components/ProductInfo/parsers/epson.py +118 -0
- flowtask/components/ProductInfo/parsers/hp.py +131 -0
- flowtask/components/ProductInfo/parsers/samsung.py +97 -0
- flowtask/components/ProductInfo/scraper.py +319 -0
- flowtask/components/ProductPricing.py +118 -0
- flowtask/components/QS.py +261 -0
- flowtask/components/QSBase.py +201 -0
- flowtask/components/QueryIterator.py +273 -0
- flowtask/components/QueryToInsert.py +327 -0
- flowtask/components/QueryToPandas.py +432 -0
- flowtask/components/RESTClient.py +195 -0
- flowtask/components/RethinkDBQuery.py +189 -0
- flowtask/components/Rsync.py +74 -0
- flowtask/components/RunSSH.py +59 -0
- flowtask/components/RunShell.py +71 -0
- flowtask/components/SalesForce.py +20 -0
- flowtask/components/SaveImageBank/__init__.py +257 -0
- flowtask/components/SchedulingVisits.py +592 -0
- flowtask/components/ScrapPage.py +216 -0
- flowtask/components/ScrapSearch.py +79 -0
- flowtask/components/SendNotify.py +257 -0
- flowtask/components/SentimentAnalysis.py +694 -0
- flowtask/components/ServiceScrapper/__init__.py +5 -0
- flowtask/components/ServiceScrapper/parsers/__init__.py +1 -0
- flowtask/components/ServiceScrapper/parsers/base.py +94 -0
- flowtask/components/ServiceScrapper/parsers/costco.py +93 -0
- flowtask/components/ServiceScrapper/scrapper.py +199 -0
- flowtask/components/SetVariables.py +156 -0
- flowtask/components/SubTask.py +182 -0
- flowtask/components/SuiteCRM.py +48 -0
- flowtask/components/Switch.py +175 -0
- flowtask/components/TableBase.py +148 -0
- flowtask/components/TableDelete.py +312 -0
- flowtask/components/TableInput.py +143 -0
- flowtask/components/TableOutput/TableOutput.py +384 -0
- flowtask/components/TableOutput/__init__.py +3 -0
- flowtask/components/TableSchema.py +534 -0
- flowtask/components/Target.py +223 -0
- flowtask/components/ThumbnailGenerator.py +156 -0
- flowtask/components/ToPandas.py +67 -0
- flowtask/components/TransformRows/TransformRows.py +507 -0
- flowtask/components/TransformRows/__init__.py +9 -0
- flowtask/components/TransformRows/functions.py +559 -0
- flowtask/components/TransposeRows.py +176 -0
- flowtask/components/UPCDatabase.py +86 -0
- flowtask/components/UnGzip.py +171 -0
- flowtask/components/Uncompress.py +172 -0
- flowtask/components/UniqueRows.py +126 -0
- flowtask/components/Unzip.py +107 -0
- flowtask/components/UpdateOperationalVars.py +147 -0
- flowtask/components/UploadTo.py +299 -0
- flowtask/components/UploadToS3.py +136 -0
- flowtask/components/UploadToSFTP.py +160 -0
- flowtask/components/UploadToSharepoint.py +205 -0
- flowtask/components/UserFunc.py +122 -0
- flowtask/components/VivaTracker.py +140 -0
- flowtask/components/WSDLClient.py +123 -0
- flowtask/components/Wait.py +18 -0
- flowtask/components/Walmart.py +199 -0
- flowtask/components/Workplace.py +134 -0
- flowtask/components/XMLToPandas.py +267 -0
- flowtask/components/Zammad/__init__.py +41 -0
- flowtask/components/Zammad/models.py +0 -0
- flowtask/components/ZoomInfoScraper.py +409 -0
- flowtask/components/__init__.py +104 -0
- flowtask/components/abstract.py +18 -0
- flowtask/components/flow.py +530 -0
- flowtask/components/google.py +335 -0
- flowtask/components/group.py +221 -0
- flowtask/components/py.typed +0 -0
- flowtask/components/reviewscrap.py +132 -0
- flowtask/components/tAutoincrement.py +117 -0
- flowtask/components/tConcat.py +109 -0
- flowtask/components/tExplode.py +119 -0
- flowtask/components/tFilter.py +184 -0
- flowtask/components/tGroup.py +236 -0
- flowtask/components/tJoin.py +270 -0
- flowtask/components/tMap/__init__.py +9 -0
- flowtask/components/tMap/functions.py +54 -0
- flowtask/components/tMap/tMap.py +450 -0
- flowtask/components/tMelt.py +112 -0
- flowtask/components/tMerge.py +114 -0
- flowtask/components/tOrder.py +93 -0
- flowtask/components/tPandas.py +94 -0
- flowtask/components/tPivot.py +71 -0
- flowtask/components/tPluckCols.py +76 -0
- flowtask/components/tUnnest.py +82 -0
- flowtask/components/user.py +401 -0
- flowtask/conf.py +457 -0
- flowtask/download.py +102 -0
- flowtask/events/__init__.py +11 -0
- flowtask/events/events/__init__.py +20 -0
- flowtask/events/events/abstract.py +95 -0
- flowtask/events/events/alerts/__init__.py +362 -0
- flowtask/events/events/alerts/colfunctions.py +131 -0
- flowtask/events/events/alerts/functions.py +158 -0
- flowtask/events/events/dummy.py +12 -0
- flowtask/events/events/exec.py +124 -0
- flowtask/events/events/file/__init__.py +7 -0
- flowtask/events/events/file/base.py +51 -0
- flowtask/events/events/file/copy.py +23 -0
- flowtask/events/events/file/delete.py +16 -0
- flowtask/events/events/interfaces/__init__.py +9 -0
- flowtask/events/events/interfaces/client.py +67 -0
- flowtask/events/events/interfaces/credentials.py +28 -0
- flowtask/events/events/interfaces/notifications.py +58 -0
- flowtask/events/events/jira.py +122 -0
- flowtask/events/events/log.py +26 -0
- flowtask/events/events/logerr.py +52 -0
- flowtask/events/events/notify.py +59 -0
- flowtask/events/events/notify_event.py +160 -0
- flowtask/events/events/publish.py +54 -0
- flowtask/events/events/sendfile.py +104 -0
- flowtask/events/events/task.py +97 -0
- flowtask/events/events/teams.py +98 -0
- flowtask/events/events/webhook.py +58 -0
- flowtask/events/manager.py +287 -0
- flowtask/exceptions.c +39393 -0
- flowtask/exceptions.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/extensions/__init__.py +3 -0
- flowtask/extensions/abstract.py +82 -0
- flowtask/extensions/logging/__init__.py +65 -0
- flowtask/hooks/__init__.py +9 -0
- flowtask/hooks/actions/__init__.py +22 -0
- flowtask/hooks/actions/abstract.py +66 -0
- flowtask/hooks/actions/dummy.py +23 -0
- flowtask/hooks/actions/jira.py +74 -0
- flowtask/hooks/actions/rest.py +320 -0
- flowtask/hooks/actions/sampledata.py +37 -0
- flowtask/hooks/actions/sensor.py +23 -0
- flowtask/hooks/actions/task.py +9 -0
- flowtask/hooks/actions/ticket.py +37 -0
- flowtask/hooks/actions/zammad.py +55 -0
- flowtask/hooks/hook.py +62 -0
- flowtask/hooks/models.py +17 -0
- flowtask/hooks/service.py +187 -0
- flowtask/hooks/step.py +91 -0
- flowtask/hooks/types/__init__.py +23 -0
- flowtask/hooks/types/base.py +129 -0
- flowtask/hooks/types/brokers/__init__.py +11 -0
- flowtask/hooks/types/brokers/base.py +54 -0
- flowtask/hooks/types/brokers/mqtt.py +35 -0
- flowtask/hooks/types/brokers/rabbitmq.py +82 -0
- flowtask/hooks/types/brokers/redis.py +83 -0
- flowtask/hooks/types/brokers/sqs.py +44 -0
- flowtask/hooks/types/fs.py +232 -0
- flowtask/hooks/types/http.py +49 -0
- flowtask/hooks/types/imap.py +200 -0
- flowtask/hooks/types/jira.py +279 -0
- flowtask/hooks/types/mail.py +205 -0
- flowtask/hooks/types/postgres.py +98 -0
- flowtask/hooks/types/responses/__init__.py +8 -0
- flowtask/hooks/types/responses/base.py +5 -0
- flowtask/hooks/types/sharepoint.py +288 -0
- flowtask/hooks/types/ssh.py +141 -0
- flowtask/hooks/types/tagged.py +59 -0
- flowtask/hooks/types/upload.py +85 -0
- flowtask/hooks/types/watch.py +71 -0
- flowtask/hooks/types/web.py +36 -0
- flowtask/interfaces/AzureClient.py +137 -0
- flowtask/interfaces/AzureGraph.py +839 -0
- flowtask/interfaces/Boto3Client.py +326 -0
- flowtask/interfaces/DropboxClient.py +173 -0
- flowtask/interfaces/ExcelHandler.py +94 -0
- flowtask/interfaces/FTPClient.py +131 -0
- flowtask/interfaces/GoogleCalendar.py +201 -0
- flowtask/interfaces/GoogleClient.py +133 -0
- flowtask/interfaces/GoogleDrive.py +127 -0
- flowtask/interfaces/GoogleGCS.py +89 -0
- flowtask/interfaces/GoogleGeocoding.py +93 -0
- flowtask/interfaces/GoogleLang.py +114 -0
- flowtask/interfaces/GooglePub.py +61 -0
- flowtask/interfaces/GoogleSheet.py +68 -0
- flowtask/interfaces/IMAPClient.py +137 -0
- flowtask/interfaces/O365Calendar.py +113 -0
- flowtask/interfaces/O365Client.py +220 -0
- flowtask/interfaces/OneDrive.py +284 -0
- flowtask/interfaces/Outlook.py +155 -0
- flowtask/interfaces/ParrotBot.py +130 -0
- flowtask/interfaces/SSHClient.py +378 -0
- flowtask/interfaces/Sharepoint.py +496 -0
- flowtask/interfaces/__init__.py +36 -0
- flowtask/interfaces/azureauth.py +119 -0
- flowtask/interfaces/cache.py +201 -0
- flowtask/interfaces/client.py +82 -0
- flowtask/interfaces/compress.py +525 -0
- flowtask/interfaces/credentials.py +124 -0
- flowtask/interfaces/d2l.py +239 -0
- flowtask/interfaces/databases/__init__.py +5 -0
- flowtask/interfaces/databases/db.py +223 -0
- flowtask/interfaces/databases/documentdb.py +55 -0
- flowtask/interfaces/databases/rethink.py +39 -0
- flowtask/interfaces/dataframes/__init__.py +11 -0
- flowtask/interfaces/dataframes/abstract.py +21 -0
- flowtask/interfaces/dataframes/arrow.py +71 -0
- flowtask/interfaces/dataframes/dt.py +69 -0
- flowtask/interfaces/dataframes/pandas.py +167 -0
- flowtask/interfaces/dataframes/polars.py +60 -0
- flowtask/interfaces/db.py +263 -0
- flowtask/interfaces/env.py +46 -0
- flowtask/interfaces/func.py +137 -0
- flowtask/interfaces/http.py +1780 -0
- flowtask/interfaces/locale.py +40 -0
- flowtask/interfaces/log.py +75 -0
- flowtask/interfaces/mask.py +143 -0
- flowtask/interfaces/notification.py +154 -0
- flowtask/interfaces/playwright.py +339 -0
- flowtask/interfaces/powerpoint.py +368 -0
- flowtask/interfaces/py.typed +0 -0
- flowtask/interfaces/qs.py +376 -0
- flowtask/interfaces/result.py +87 -0
- flowtask/interfaces/selenium_service.py +779 -0
- flowtask/interfaces/smartsheet.py +154 -0
- flowtask/interfaces/stat.py +39 -0
- flowtask/interfaces/task.py +96 -0
- flowtask/interfaces/template.py +118 -0
- flowtask/interfaces/vectorstores/__init__.py +1 -0
- flowtask/interfaces/vectorstores/abstract.py +133 -0
- flowtask/interfaces/vectorstores/milvus.py +669 -0
- flowtask/interfaces/zammad.py +107 -0
- flowtask/models.py +193 -0
- flowtask/parsers/__init__.py +15 -0
- flowtask/parsers/_yaml.c +11978 -0
- flowtask/parsers/_yaml.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/argparser.py +235 -0
- flowtask/parsers/base.c +15155 -0
- flowtask/parsers/base.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/json.c +11968 -0
- flowtask/parsers/json.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/maps.py +49 -0
- flowtask/parsers/toml.c +11968 -0
- flowtask/parsers/toml.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/plugins/__init__.py +16 -0
- flowtask/plugins/components/__init__.py +0 -0
- flowtask/plugins/handler/__init__.py +45 -0
- flowtask/plugins/importer.py +31 -0
- flowtask/plugins/sources/__init__.py +0 -0
- flowtask/runner.py +283 -0
- flowtask/scheduler/__init__.py +9 -0
- flowtask/scheduler/functions.py +493 -0
- flowtask/scheduler/handlers/__init__.py +8 -0
- flowtask/scheduler/handlers/manager.py +504 -0
- flowtask/scheduler/handlers/models.py +58 -0
- flowtask/scheduler/handlers/service.py +72 -0
- flowtask/scheduler/notifications.py +65 -0
- flowtask/scheduler/scheduler.py +993 -0
- flowtask/services/__init__.py +0 -0
- flowtask/services/bots/__init__.py +0 -0
- flowtask/services/bots/telegram.py +264 -0
- flowtask/services/files/__init__.py +11 -0
- flowtask/services/files/manager.py +522 -0
- flowtask/services/files/model.py +37 -0
- flowtask/services/files/service.py +767 -0
- flowtask/services/jira/__init__.py +3 -0
- flowtask/services/jira/jira_actions.py +191 -0
- flowtask/services/tasks/__init__.py +13 -0
- flowtask/services/tasks/launcher.py +213 -0
- flowtask/services/tasks/manager.py +323 -0
- flowtask/services/tasks/service.py +275 -0
- flowtask/services/tasks/task_manager.py +376 -0
- flowtask/services/tasks/tasks.py +155 -0
- flowtask/storages/__init__.py +16 -0
- flowtask/storages/exceptions.py +12 -0
- flowtask/storages/files/__init__.py +8 -0
- flowtask/storages/files/abstract.py +29 -0
- flowtask/storages/files/filesystem.py +66 -0
- flowtask/storages/tasks/__init__.py +19 -0
- flowtask/storages/tasks/abstract.py +26 -0
- flowtask/storages/tasks/database.py +33 -0
- flowtask/storages/tasks/filesystem.py +108 -0
- flowtask/storages/tasks/github.py +119 -0
- flowtask/storages/tasks/memory.py +45 -0
- flowtask/storages/tasks/row.py +25 -0
- flowtask/tasks/__init__.py +0 -0
- flowtask/tasks/abstract.py +526 -0
- flowtask/tasks/command.py +118 -0
- flowtask/tasks/pile.py +486 -0
- flowtask/tasks/py.typed +0 -0
- flowtask/tasks/task.py +778 -0
- flowtask/template/__init__.py +161 -0
- flowtask/tests.py +257 -0
- flowtask/types/__init__.py +8 -0
- flowtask/types/typedefs.c +11347 -0
- flowtask/types/typedefs.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/__init__.py +24 -0
- flowtask/utils/constants.py +117 -0
- flowtask/utils/encoders.py +21 -0
- flowtask/utils/executor.py +112 -0
- flowtask/utils/functions.cpp +14280 -0
- flowtask/utils/functions.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/json.cpp +13349 -0
- flowtask/utils/json.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/mail.py +63 -0
- flowtask/utils/parseqs.c +13324 -0
- flowtask/utils/parserqs.cpython-312-x86_64-linux-gnu.so +0 -0
- flowtask/utils/stats.py +308 -0
- flowtask/utils/transformations.py +74 -0
- flowtask/utils/uv.py +12 -0
- flowtask/utils/validators.py +97 -0
- flowtask/version.py +11 -0
- flowtask-5.8.4.dist-info/LICENSE +201 -0
- flowtask-5.8.4.dist-info/METADATA +209 -0
- flowtask-5.8.4.dist-info/RECORD +470 -0
- flowtask-5.8.4.dist-info/WHEEL +6 -0
- flowtask-5.8.4.dist-info/entry_points.txt +3 -0
- flowtask-5.8.4.dist-info/top_level.txt +2 -0
- plugins/components/CreateQR.py +39 -0
- plugins/components/TestComponent.py +28 -0
- plugins/components/Use1.py +13 -0
- plugins/components/Workplace.py +117 -0
- plugins/components/__init__.py +3 -0
- plugins/sources/__init__.py +0 -0
- plugins/sources/get_populartimes.py +78 -0
- plugins/sources/google.py +150 -0
- plugins/sources/hubspot.py +679 -0
- plugins/sources/icims.py +679 -0
- plugins/sources/mobileinsight.py +501 -0
- plugins/sources/newrelic.py +262 -0
- plugins/sources/uap.py +268 -0
- plugins/sources/venu.py +244 -0
- plugins/sources/vocinity.py +314 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
from typing import Union, Any, ParamSpec
|
2
|
+
from io import BytesIO
|
3
|
+
import orjson
|
4
|
+
import pyarrow as pa
|
5
|
+
import datatable as dt
|
6
|
+
import pandas as pd
|
7
|
+
from .abstract import BaseDataframe
|
8
|
+
from ...exceptions import ComponentError, DataNotFound
|
9
|
+
|
10
|
+
|
11
|
+
P = ParamSpec("P")
|
12
|
+
|
13
|
+
|
14
|
+
def is_empty(obj):
|
15
|
+
"""check_empty.
|
16
|
+
Check if a basic object, a Polars DataFrame, an Apache Arrow Table,
|
17
|
+
or a Python DataTable Frame is empty or not.
|
18
|
+
"""
|
19
|
+
if isinstance(obj, (pa.Table, dt.Frame)):
|
20
|
+
return obj.nrows == 0
|
21
|
+
else:
|
22
|
+
return bool(not obj)
|
23
|
+
|
24
|
+
|
25
|
+
class DtDataframe(BaseDataframe):
|
26
|
+
"""DtDataframe.
|
27
|
+
|
28
|
+
Converts any result into a Datatable DataFrame.
|
29
|
+
"""
|
30
|
+
|
31
|
+
async def create_dataframe(
|
32
|
+
self, result: Union[dict, bytes, Any], *args: P.args, **kwargs: P.kwargs
|
33
|
+
) -> Any:
|
34
|
+
"""
|
35
|
+
Converts any result into a Datatable DataFrame.
|
36
|
+
|
37
|
+
:param result: The result data to be converted into a Datatable DataFrame.
|
38
|
+
:return: A DataFrame containing the result data.
|
39
|
+
"""
|
40
|
+
if is_empty(result):
|
41
|
+
raise DataNotFound("Frame: No Data was Found.")
|
42
|
+
try:
|
43
|
+
if isinstance(result, str):
|
44
|
+
try:
|
45
|
+
result = orjson.loads(result)
|
46
|
+
except Exception:
|
47
|
+
pass
|
48
|
+
if isinstance(result, (list, dict)):
|
49
|
+
df = dt.Frame(result, **kwargs)
|
50
|
+
elif isinstance(result, bytes) or isinstance(result, BytesIO):
|
51
|
+
# Reset the pointer to the start of the stream
|
52
|
+
result.seek(0)
|
53
|
+
# Assuming bytes is a CSV format, adjust as needed
|
54
|
+
df = dt.Frame(pd.read_csv(result))
|
55
|
+
else:
|
56
|
+
raise ValueError("Unsupported data type for DataTable Frame creation")
|
57
|
+
|
58
|
+
columns = list(df.names)
|
59
|
+
numrows = df.nrows
|
60
|
+
numcols = df.ncols
|
61
|
+
try:
|
62
|
+
self._variables["_numRows_"] = numrows
|
63
|
+
self.add_metric("NUM_ROWS", numrows)
|
64
|
+
self.add_metric("NUM_COLS", numcols)
|
65
|
+
except Exception:
|
66
|
+
pass
|
67
|
+
return df
|
68
|
+
except Exception as err:
|
69
|
+
raise ComponentError(f"Error Creating Frame: {err!s}")
|
@@ -0,0 +1,167 @@
|
|
1
|
+
from typing import Union, Any, ParamSpec, Callable
|
2
|
+
import asyncio
|
3
|
+
import orjson
|
4
|
+
import pandas as pd
|
5
|
+
from .abstract import BaseDataframe
|
6
|
+
from ...exceptions import ComponentError, DataNotFound
|
7
|
+
|
8
|
+
P = ParamSpec("P")
|
9
|
+
|
10
|
+
|
11
|
+
def is_empty(obj):
|
12
|
+
"""check_empty.
|
13
|
+
Check if a basic object is empty or not.
|
14
|
+
"""
|
15
|
+
if isinstance(obj, pd.DataFrame):
|
16
|
+
return True if obj.empty else False
|
17
|
+
else:
|
18
|
+
return bool(not obj)
|
19
|
+
|
20
|
+
|
21
|
+
class PandasDataframe(BaseDataframe):
|
22
|
+
"""PandasDataframe.
|
23
|
+
|
24
|
+
Converts any result into a Pandas DataFrame.
|
25
|
+
"""
|
26
|
+
chunk_size: int = 100
|
27
|
+
task_parts: int = 10
|
28
|
+
|
29
|
+
async def create_dataframe(
|
30
|
+
self,
|
31
|
+
result: Union[dict, bytes, Any],
|
32
|
+
*args: P.args,
|
33
|
+
**kwargs: P.kwargs
|
34
|
+
) -> Any:
|
35
|
+
"""
|
36
|
+
Converts any result into a Pandas DataFrame.
|
37
|
+
|
38
|
+
:param result: The result data to be converted into a Pandas DataFrame.
|
39
|
+
:return: A DataFrame containing the result data.
|
40
|
+
"""
|
41
|
+
if is_empty(result):
|
42
|
+
raise DataNotFound("DataFrame: No Data was Found.")
|
43
|
+
try:
|
44
|
+
if isinstance(result, str):
|
45
|
+
try:
|
46
|
+
result = orjson.loads(result)
|
47
|
+
except Exception:
|
48
|
+
pass
|
49
|
+
if isinstance(result, dict):
|
50
|
+
result = [result]
|
51
|
+
df = pd.DataFrame(result, **kwargs)
|
52
|
+
# Attempt to infer better dtypes for object columns.
|
53
|
+
df.infer_objects()
|
54
|
+
columns = list(df.columns)
|
55
|
+
if hasattr(self, "infer_types"):
|
56
|
+
df = df.convert_dtypes(convert_string=self.to_string)
|
57
|
+
if hasattr(self, "infer_types"):
|
58
|
+
df = df.convert_dtypes()
|
59
|
+
if hasattr(self, "drop_empty"):
|
60
|
+
df.dropna(axis=1, how="all", inplace=True)
|
61
|
+
df.dropna(axis=0, how="all", inplace=True)
|
62
|
+
if hasattr(self, "dropna"):
|
63
|
+
df.dropna(subset=self.dropna, how="all", inplace=True)
|
64
|
+
numrows = len(df.index)
|
65
|
+
try:
|
66
|
+
self._variables["_numRows_"] = numrows
|
67
|
+
self.add_metric("NUM_ROWS", numrows)
|
68
|
+
self.add_metric("NUM_COLS", len(columns))
|
69
|
+
except Exception:
|
70
|
+
pass
|
71
|
+
return df
|
72
|
+
except Exception as err:
|
73
|
+
raise ComponentError(
|
74
|
+
f"Error Creating Dataframe: {err!s}"
|
75
|
+
)
|
76
|
+
|
77
|
+
async def from_csv(
|
78
|
+
self, result: str, *args: P.args, **kwargs: P.kwargs
|
79
|
+
) -> Any:
|
80
|
+
"""
|
81
|
+
Converts a Comma-Separated CSV into a Pandas DataFrame.
|
82
|
+
|
83
|
+
:param result: The result data to be converted into a Pandas DataFrame.
|
84
|
+
:return: A DataFrame containing the result data.
|
85
|
+
"""
|
86
|
+
if is_empty(result):
|
87
|
+
raise DataNotFound("DataFrame: No Data was Found.")
|
88
|
+
try:
|
89
|
+
df = pd.read_csv(result, encoding="utf-8", **kwargs)
|
90
|
+
# Attempt to infer better dtypes for object columns.
|
91
|
+
df.infer_objects()
|
92
|
+
columns = list(df.columns)
|
93
|
+
if hasattr(self, "infer_types"):
|
94
|
+
df = df.convert_dtypes(convert_string=self.to_string)
|
95
|
+
if hasattr(self, "infer_types"):
|
96
|
+
df = df.convert_dtypes()
|
97
|
+
if hasattr(self, "drop_empty"):
|
98
|
+
df.dropna(axis=1, how="all", inplace=True)
|
99
|
+
df.dropna(axis=0, how="all", inplace=True)
|
100
|
+
if hasattr(self, "dropna"):
|
101
|
+
df.dropna(subset=self.dropna, how="all", inplace=True)
|
102
|
+
numrows = len(df.index)
|
103
|
+
try:
|
104
|
+
self._variables["_numRows_"] = numrows
|
105
|
+
self.add_metric("NUM_ROWS", numrows)
|
106
|
+
self.add_metric("NUM_COLS", len(columns))
|
107
|
+
except Exception:
|
108
|
+
pass
|
109
|
+
return df
|
110
|
+
except Exception as err:
|
111
|
+
raise ComponentError(f"Error Creating Dataframe: {err!s}")
|
112
|
+
|
113
|
+
def column_exists(self, column: str):
|
114
|
+
"""Returns True if the column exists in the DataFrame."""
|
115
|
+
if column not in self.data.columns:
|
116
|
+
self._logger.warning(
|
117
|
+
f"Column {column} does not exist in the dataframe"
|
118
|
+
)
|
119
|
+
self.data[column] = None
|
120
|
+
return False
|
121
|
+
return True
|
122
|
+
|
123
|
+
def _create_tasks(self, dataframe: pd.DataFrame, func: Union[str, Callable], **kwargs) -> list:
|
124
|
+
"""
|
125
|
+
Create tasks for processing the DataFrame.
|
126
|
+
|
127
|
+
:param dataframe: The DataFrame to process.
|
128
|
+
:param
|
129
|
+
func: The function to apply to each row.
|
130
|
+
:return: A list of tasks.
|
131
|
+
"""
|
132
|
+
if isinstance(func, str):
|
133
|
+
func = getattr(self, func)
|
134
|
+
if not callable(func):
|
135
|
+
raise ValueError(f"Function {func} is not callable.")
|
136
|
+
if not isinstance(dataframe, pd.DataFrame):
|
137
|
+
raise ValueError(f"Dataframe {dataframe} is not a DataFrame.")
|
138
|
+
if dataframe.empty:
|
139
|
+
raise ValueError(f"Dataframe {dataframe} is empty.")
|
140
|
+
tasks = []
|
141
|
+
for idx, row in dataframe.iterrows():
|
142
|
+
task = func(row, idx, **kwargs)
|
143
|
+
if asyncio.iscoroutinefunction(task):
|
144
|
+
tasks.append(task)
|
145
|
+
else:
|
146
|
+
tasks.append(asyncio.create_task(task))
|
147
|
+
return tasks
|
148
|
+
|
149
|
+
def split_parts(self, task_list, num_parts: int = 5) -> list:
|
150
|
+
part_size = len(task_list) // num_parts
|
151
|
+
remainder = len(task_list) % num_parts
|
152
|
+
parts = []
|
153
|
+
start = 0
|
154
|
+
for i in range(num_parts):
|
155
|
+
# Distribute the remainder across the first `remainder` parts
|
156
|
+
end = start + part_size + (1 if i < remainder else 0)
|
157
|
+
parts.append(task_list[start:end])
|
158
|
+
start = end
|
159
|
+
return parts
|
160
|
+
|
161
|
+
async def _processing_tasks(self, tasks: list) -> pd.DataFrame:
|
162
|
+
"""Process tasks concurrently."""
|
163
|
+
results = []
|
164
|
+
for chunk in self.split_parts(tasks, self.task_parts):
|
165
|
+
result = await asyncio.gather(*chunk, return_exceptions=False)
|
166
|
+
results.extend(result)
|
167
|
+
return results
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from typing import Union, Any, ParamSpec
|
2
|
+
import orjson
|
3
|
+
import pandas as pd
|
4
|
+
import polars as pl
|
5
|
+
from .abstract import BaseDataframe
|
6
|
+
from ...exceptions import ComponentError, DataNotFound
|
7
|
+
|
8
|
+
|
9
|
+
P = ParamSpec("P")
|
10
|
+
|
11
|
+
|
12
|
+
def is_empty(obj):
|
13
|
+
"""check_empty.
|
14
|
+
Check if a basic object or a DataFrame (Pandas or Polars) is empty or not.
|
15
|
+
"""
|
16
|
+
if isinstance(obj, pd.DataFrame) or isinstance(obj, pl.DataFrame):
|
17
|
+
return obj.shape[0] == 0
|
18
|
+
else:
|
19
|
+
return bool(not obj)
|
20
|
+
|
21
|
+
|
22
|
+
class PolarsDataframe(BaseDataframe):
|
23
|
+
"""PolarsDataframe.
|
24
|
+
|
25
|
+
Converts any result into a Polars DataFrame.
|
26
|
+
"""
|
27
|
+
|
28
|
+
async def create_dataframe(
|
29
|
+
self, result: Union[dict, bytes, Any], *args: P.args, **kwargs: P.kwargs
|
30
|
+
) -> Any:
|
31
|
+
"""
|
32
|
+
Converts any result into a Polars DataFrame.
|
33
|
+
|
34
|
+
:param result: The result data to be converted into a Polars DataFrame.
|
35
|
+
:return: A DataFrame containing the result data.
|
36
|
+
"""
|
37
|
+
if is_empty(result):
|
38
|
+
raise DataNotFound("DataFrame: No Data was Found.")
|
39
|
+
try:
|
40
|
+
if isinstance(result, str):
|
41
|
+
try:
|
42
|
+
result = orjson.loads(result)
|
43
|
+
except Exception:
|
44
|
+
pass
|
45
|
+
df = pl.DataFrame(result, **kwargs)
|
46
|
+
columns = list(df.columns)
|
47
|
+
if hasattr(self, "drop_empty"):
|
48
|
+
df = df.drop_nulls(how="all", subset=df.columns)
|
49
|
+
if hasattr(self, "dropna"):
|
50
|
+
df = df.drop_nulls(how="all", subset=self.dropna)
|
51
|
+
numrows = df.height
|
52
|
+
try:
|
53
|
+
self._variables["_numRows_"] = numrows
|
54
|
+
self.add_metric("NUM_ROWS", numrows)
|
55
|
+
self.add_metric("NUM_COLS", df.width)
|
56
|
+
except Exception:
|
57
|
+
pass
|
58
|
+
return df
|
59
|
+
except Exception as err:
|
60
|
+
raise ComponentError(f"Error Creating Dataframe: {err!s}")
|
@@ -0,0 +1,263 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Optional
|
3
|
+
from collections.abc import Callable
|
4
|
+
from navconfig.logging import logging
|
5
|
+
from querysource.conf import (
|
6
|
+
# postgres main database:
|
7
|
+
# postgres read-only
|
8
|
+
PG_DRIVER,
|
9
|
+
PG_HOST,
|
10
|
+
PG_USER,
|
11
|
+
PG_PWD,
|
12
|
+
PG_DATABASE,
|
13
|
+
PG_PORT,
|
14
|
+
# rethinkdb
|
15
|
+
RT_DRIVER,
|
16
|
+
RT_HOST,
|
17
|
+
RT_PORT,
|
18
|
+
RT_USER,
|
19
|
+
RT_PASSWORD,
|
20
|
+
RT_DATABASE,
|
21
|
+
# SQL Server
|
22
|
+
MSSQL_DRIVER,
|
23
|
+
MSSQL_HOST,
|
24
|
+
MSSQL_PORT,
|
25
|
+
MSSQL_USER,
|
26
|
+
MSSQL_PWD,
|
27
|
+
MSSQL_DATABASE,
|
28
|
+
# MySQL Server
|
29
|
+
MYSQL_DRIVER,
|
30
|
+
MYSQL_HOST,
|
31
|
+
MYSQL_PORT,
|
32
|
+
MYSQL_USER,
|
33
|
+
MYSQL_PWD,
|
34
|
+
MYSQL_DATABASE,
|
35
|
+
# influxdb
|
36
|
+
INFLUX_DRIVER,
|
37
|
+
INFLUX_HOST,
|
38
|
+
INFLUX_PORT,
|
39
|
+
INFLUX_ORG,
|
40
|
+
INFLUX_TOKEN,
|
41
|
+
# INFLUX_USER,
|
42
|
+
# INFLUX_PWD,
|
43
|
+
INFLUX_DATABASE,
|
44
|
+
# cassandra
|
45
|
+
CASSANDRA_DRIVER,
|
46
|
+
CASSANDRA_HOST,
|
47
|
+
CASSANDRA_PORT,
|
48
|
+
CASSANDRA_USER,
|
49
|
+
CASSANDRA_PWD,
|
50
|
+
CASSANDRA_DATABASE,
|
51
|
+
)
|
52
|
+
from asyncdb import AsyncDB
|
53
|
+
from asyncdb.drivers.base import BaseDriver
|
54
|
+
from asyncdb.exceptions import ProviderError
|
55
|
+
from ..conf import default_dsn
|
56
|
+
from ..exceptions import ComponentError
|
57
|
+
from .credentials import CredentialsInterface
|
58
|
+
|
59
|
+
|
60
|
+
class DBInterface(CredentialsInterface):
|
61
|
+
"""DBInterface.
|
62
|
+
|
63
|
+
Abstract Interface for Database-based connectors.
|
64
|
+
"""
|
65
|
+
_credentials = {
|
66
|
+
"host": str,
|
67
|
+
"port": int,
|
68
|
+
"user": str,
|
69
|
+
"password": str,
|
70
|
+
"database": str,
|
71
|
+
}
|
72
|
+
|
73
|
+
def __init__(
|
74
|
+
self,
|
75
|
+
*args,
|
76
|
+
driver: Optional[str] = None,
|
77
|
+
**kwargs
|
78
|
+
) -> None:
|
79
|
+
self.driver: str = driver
|
80
|
+
self.datasource: str = None
|
81
|
+
self._connection: Callable = None
|
82
|
+
super().__init__(*args, **kwargs)
|
83
|
+
|
84
|
+
async def connection(
|
85
|
+
self,
|
86
|
+
driver: str = "pg",
|
87
|
+
credentials: Optional[dict] = None,
|
88
|
+
event_loop: Optional[asyncio.AbstractEventLoop] = None,
|
89
|
+
**kwargs,
|
90
|
+
) -> BaseDriver:
|
91
|
+
if not event_loop:
|
92
|
+
event_loop = asyncio.get_event_loop()
|
93
|
+
if driver == "pg": # default driver:
|
94
|
+
args = {
|
95
|
+
"server_settings": {
|
96
|
+
"client_min_messages": "notice",
|
97
|
+
"max_parallel_workers": "24",
|
98
|
+
"statement_timeout": "36000000",
|
99
|
+
}
|
100
|
+
}
|
101
|
+
else:
|
102
|
+
args = kwargs
|
103
|
+
try:
|
104
|
+
self._connection = AsyncDB(
|
105
|
+
driver, params=credentials, loop=event_loop, **args
|
106
|
+
)
|
107
|
+
except ProviderError as e:
|
108
|
+
raise ComponentError(f"DbClient: Error creating connection: {e}") from e
|
109
|
+
except Exception as e:
|
110
|
+
raise ComponentError(f"DbClient: unknown DB error: {e}") from e
|
111
|
+
if self._connection:
|
112
|
+
return self._connection
|
113
|
+
else:
|
114
|
+
raise ComponentError(f"DbClient: Unable to connect to {driver}")
|
115
|
+
|
116
|
+
def pg_connection(self, event_loop: asyncio.AbstractEventLoop = None) -> BaseDriver:
|
117
|
+
pgargs: dict = {
|
118
|
+
"server_settings": {
|
119
|
+
"application_name": "Flowtask",
|
120
|
+
"client_min_messages": "notice",
|
121
|
+
"max_parallel_workers": "48",
|
122
|
+
"jit": "off",
|
123
|
+
"statement_timeout": "3600000",
|
124
|
+
"effective_cache_size": "2147483647",
|
125
|
+
},
|
126
|
+
}
|
127
|
+
if not event_loop:
|
128
|
+
try:
|
129
|
+
event_loop = asyncio.get_running_loop()
|
130
|
+
except RuntimeError:
|
131
|
+
event_loop = asyncio.get_event_loop()
|
132
|
+
return AsyncDB("pg", dsn=default_dsn, loop=event_loop, **pgargs)
|
133
|
+
|
134
|
+
async def get_driver(self, driver: str, conn: BaseDriver) -> BaseDriver:
|
135
|
+
# TODO: migration to Model
|
136
|
+
result = None
|
137
|
+
query = (
|
138
|
+
"SELECT driver, params, credentials FROM public.datasources where name = '{}'"
|
139
|
+
)
|
140
|
+
try:
|
141
|
+
result, error = await conn.queryrow(query.format(driver))
|
142
|
+
if error:
|
143
|
+
raise ComponentError(
|
144
|
+
f"DbClient: Error on Getting Datasource: {error!s}"
|
145
|
+
)
|
146
|
+
if result:
|
147
|
+
try:
|
148
|
+
self.driver = result["driver"]
|
149
|
+
except KeyError as ex:
|
150
|
+
raise RuntimeError(
|
151
|
+
f"DbClient Error: there is no *Driver* column on datasource {driver}"
|
152
|
+
) from ex
|
153
|
+
try:
|
154
|
+
params = result["params"]
|
155
|
+
logging.debug(
|
156
|
+
f"DB: connection params: {params}"
|
157
|
+
)
|
158
|
+
self.credentials = {**dict(params), **dict(result["credentials"])}
|
159
|
+
except (TypeError, ValueError, KeyError) as ex:
|
160
|
+
raise RuntimeError(
|
161
|
+
f"DbClient Error: wrong or missing credentials on Datasource {driver}"
|
162
|
+
) from ex
|
163
|
+
except Exception as e:
|
164
|
+
logging.exception(f"DB Error: {e}", stack_info=True)
|
165
|
+
raise
|
166
|
+
if not result:
|
167
|
+
# getting the default for any kind of database connection:
|
168
|
+
# based on provider (rethink, mssql, etc) get default connection
|
169
|
+
if driver == "sqlserver":
|
170
|
+
self.driver = MSSQL_DRIVER
|
171
|
+
self.credentials = {
|
172
|
+
"host": MSSQL_HOST,
|
173
|
+
"port": MSSQL_PORT,
|
174
|
+
"database": MSSQL_DATABASE,
|
175
|
+
"user": MSSQL_USER,
|
176
|
+
"password": MSSQL_PWD,
|
177
|
+
}
|
178
|
+
elif driver == "cassandra":
|
179
|
+
self.driver = CASSANDRA_DRIVER
|
180
|
+
self.credentials = {
|
181
|
+
"host": CASSANDRA_HOST,
|
182
|
+
"port": CASSANDRA_PORT,
|
183
|
+
"database": CASSANDRA_DATABASE,
|
184
|
+
"user": CASSANDRA_USER,
|
185
|
+
"password": CASSANDRA_PWD,
|
186
|
+
}
|
187
|
+
elif driver in ("influx", "influxdb"):
|
188
|
+
self.driver = INFLUX_DRIVER
|
189
|
+
self.credentials = {
|
190
|
+
"host": INFLUX_HOST,
|
191
|
+
"port": INFLUX_PORT,
|
192
|
+
"database": INFLUX_DATABASE,
|
193
|
+
"org": INFLUX_ORG,
|
194
|
+
"token": INFLUX_TOKEN,
|
195
|
+
}
|
196
|
+
elif driver in ("rethink", "rethinkdb"):
|
197
|
+
self.driver = RT_DRIVER
|
198
|
+
self.credentials = {
|
199
|
+
"host": RT_HOST,
|
200
|
+
"port": RT_PORT,
|
201
|
+
"database": RT_DATABASE,
|
202
|
+
"user": RT_USER,
|
203
|
+
"password": RT_PASSWORD,
|
204
|
+
}
|
205
|
+
elif driver in ("postgres", "postgresql"):
|
206
|
+
self.driver = PG_DRIVER
|
207
|
+
self.credentials = {
|
208
|
+
"host": PG_HOST,
|
209
|
+
"port": PG_PORT,
|
210
|
+
"database": PG_DATABASE,
|
211
|
+
"user": PG_USER,
|
212
|
+
"password": PG_PWD,
|
213
|
+
}
|
214
|
+
elif driver == "mysql":
|
215
|
+
self.driver = MYSQL_DRIVER
|
216
|
+
self.credentials = {
|
217
|
+
"host": MYSQL_HOST,
|
218
|
+
"port": MYSQL_PORT,
|
219
|
+
"database": MYSQL_DATABASE,
|
220
|
+
"user": MYSQL_USER,
|
221
|
+
"password": MYSQL_PWD,
|
222
|
+
}
|
223
|
+
else:
|
224
|
+
raise ComponentError(f"Unknown Database Driver {driver}")
|
225
|
+
|
226
|
+
async def get_credentials(self) -> BaseDriver:
|
227
|
+
if self.credentials:
|
228
|
+
return True # credentials are passed to Component
|
229
|
+
if self.datasource is not None:
|
230
|
+
driver = self.datasource
|
231
|
+
else:
|
232
|
+
driver = "pg"
|
233
|
+
if driver in ("db", "pg"):
|
234
|
+
# default credentials
|
235
|
+
self.driver = PG_DRIVER
|
236
|
+
self.credentials = {
|
237
|
+
"user": PG_USER,
|
238
|
+
"password": PG_PWD,
|
239
|
+
"host": PG_HOST,
|
240
|
+
"port": int(PG_PORT),
|
241
|
+
"database": PG_DATABASE,
|
242
|
+
}
|
243
|
+
return True
|
244
|
+
else:
|
245
|
+
# getting from "datasources" table:
|
246
|
+
db = self.pg_connection()
|
247
|
+
try:
|
248
|
+
async with await db.connection() as conn:
|
249
|
+
await self.get_driver(driver, conn)
|
250
|
+
if not self.credentials:
|
251
|
+
raise RuntimeError(
|
252
|
+
f"DB Error: wrong or missing credentials: {driver}"
|
253
|
+
)
|
254
|
+
except Exception as e:
|
255
|
+
logging.exception(f"DB Error: {e}")
|
256
|
+
raise
|
257
|
+
|
258
|
+
async def start(self, **kwargs):
|
259
|
+
# first: getting credential from datasource or creds dictionary.
|
260
|
+
# second: processing credentials (extracting value replacements from environment)
|
261
|
+
await self.get_credentials()
|
262
|
+
self.processing_credentials()
|
263
|
+
await super(DBInterface, self).start(**kwargs)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
import os
|
3
|
+
from navconfig import config
|
4
|
+
|
5
|
+
|
6
|
+
class EnvSupport(ABC):
|
7
|
+
"""EnvSupport.
|
8
|
+
|
9
|
+
Support for Environment Variables
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, *args, **kwargs):
|
13
|
+
self._environment = config
|
14
|
+
# Call super only if there’s a next class in the MRO
|
15
|
+
try:
|
16
|
+
super().__init__(*args, **kwargs)
|
17
|
+
except TypeError:
|
18
|
+
super().__init__()
|
19
|
+
|
20
|
+
def get_env_value(self, key, default: str = None, expected_type: object = None):
|
21
|
+
"""
|
22
|
+
Retrieves a value from the environment variables or the configuration.
|
23
|
+
|
24
|
+
:param key: The key for the environment variable.
|
25
|
+
:param default: The default value to return if the key is not found.
|
26
|
+
:param expected_type: the data type to be expected.
|
27
|
+
:return: The value of the environment variable or the default value.
|
28
|
+
"""
|
29
|
+
if key is None:
|
30
|
+
return default
|
31
|
+
if expected_type is not None:
|
32
|
+
if expected_type in (int, float):
|
33
|
+
return self._environment.getint(key, default)
|
34
|
+
elif expected_type == bool:
|
35
|
+
return self._environment.getboolean(key, default)
|
36
|
+
else:
|
37
|
+
return self._environment.get(key, default)
|
38
|
+
if val := os.getenv(str(key), default):
|
39
|
+
return val
|
40
|
+
if val := self._environment.get(key, default):
|
41
|
+
return val
|
42
|
+
else:
|
43
|
+
if hasattr(self, "masks") and hasattr(self, "_mask"):
|
44
|
+
if key in self._mask.keys():
|
45
|
+
return self._mask[key]
|
46
|
+
return key
|