flowtask 5.8.4__cp310-cp310-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-310-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-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/argparser.py +235 -0
- flowtask/parsers/base.c +15155 -0
- flowtask/parsers/base.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/json.c +11968 -0
- flowtask/parsers/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/parsers/maps.py +49 -0
- flowtask/parsers/toml.c +11968 -0
- flowtask/parsers/toml.cpython-310-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-310-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-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/json.cpp +13349 -0
- flowtask/utils/json.cpython-310-x86_64-linux-gnu.so +0 -0
- flowtask/utils/mail.py +63 -0
- flowtask/utils/parseqs.c +13324 -0
- flowtask/utils/parserqs.cpython-310-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,239 @@
|
|
1
|
+
"""
|
2
|
+
D2L.
|
3
|
+
|
4
|
+
Making operations over D2L.
|
5
|
+
|
6
|
+
"""
|
7
|
+
import re
|
8
|
+
from datetime import datetime, timezone
|
9
|
+
from ..exceptions import (
|
10
|
+
ComponentError
|
11
|
+
)
|
12
|
+
import random
|
13
|
+
from .http import HTTPService, ua
|
14
|
+
from .cache import CacheSupport
|
15
|
+
|
16
|
+
class D2LClient(CacheSupport, HTTPService):
|
17
|
+
'''
|
18
|
+
Manage Connection to D2L
|
19
|
+
'''
|
20
|
+
def __init__(self, *args, **kwargs):
|
21
|
+
self.token_type: str = "Bearer"
|
22
|
+
self.auth_type: str = "apikey"
|
23
|
+
self.domain: str = kwargs.pop('domain', None)
|
24
|
+
self.domain = self.get_env_value(self.domain, self.domain)
|
25
|
+
self.url_login: str = f'https://{self.domain}/d2l/lp/auth/login/login.d2l'
|
26
|
+
self.url_token: str = f'https://{self.domain}/d2l/lp/auth/oauth2/token'
|
27
|
+
self.file_format: str = 'application/zip'
|
28
|
+
self.create_destination: bool = True # by default
|
29
|
+
self.dataset: str = kwargs.pop('dataset', None)
|
30
|
+
self.plugin: str = kwargs.pop('plugin', None)
|
31
|
+
self.d2l_session_val: str = None
|
32
|
+
self.d2l_secure_session_val: str = None
|
33
|
+
self.csrf_token: str = None
|
34
|
+
self.auth: dict = {'apikey': None}
|
35
|
+
super().__init__(*args, **kwargs)
|
36
|
+
self.processing_credentials()
|
37
|
+
self.username: str = self.credentials.get('username', None)
|
38
|
+
self.password: str = self.credentials.get('password', None)
|
39
|
+
self.headers = {
|
40
|
+
"Accept-Encoding": "gzip, deflate",
|
41
|
+
"DNT": "1",
|
42
|
+
"Connection": "keep-alive",
|
43
|
+
"Upgrade-Insecure-Requests": "1",
|
44
|
+
"User-Agent": random.choice(ua)
|
45
|
+
}
|
46
|
+
|
47
|
+
async def get_bearer_token(self):
|
48
|
+
# Try to get API Key from REDIS
|
49
|
+
with await self.open() as redis:
|
50
|
+
api_key = redis.get('D2L_API_KEY')
|
51
|
+
d2l_session_val = redis.get('D2L_SESSION_VAL')
|
52
|
+
d2l_secure_session_val = redis.get('D2L_SECURE_SESSION_VAL')
|
53
|
+
if api_key:
|
54
|
+
self.auth['apikey'] = api_key
|
55
|
+
self.cookies = {
|
56
|
+
"d2lSessionVal": d2l_session_val,
|
57
|
+
"d2lSecureSessionVal": d2l_secure_session_val
|
58
|
+
}
|
59
|
+
self.headers["Authorization"] = f"Bearer {self.auth.get('apikey')}"
|
60
|
+
return api_key
|
61
|
+
# Get cookies values
|
62
|
+
login_headers = {
|
63
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
64
|
+
"Origin": f"https://{self.domain}",
|
65
|
+
"Referer": f"https://{self.domain}/d2l/login",
|
66
|
+
"User-Agent": random.choice(ua)
|
67
|
+
}
|
68
|
+
login_data = {
|
69
|
+
"d2l_referrer": f"https://{self.domain}/d2l/login",
|
70
|
+
"loginPath": "/d2l/login",
|
71
|
+
"userName": self.username,
|
72
|
+
"password": self.password,
|
73
|
+
}
|
74
|
+
try:
|
75
|
+
response = await self._post(
|
76
|
+
url=self.url_login,
|
77
|
+
cookies=None,
|
78
|
+
headers=login_headers,
|
79
|
+
data=login_data,
|
80
|
+
follow_redirects=False,
|
81
|
+
raise_for_status=False,
|
82
|
+
use_proxy= False
|
83
|
+
)
|
84
|
+
d2l_session_val = response.cookies.get("d2lSessionVal", "")
|
85
|
+
d2l_secure_session_val = response.cookies.get("d2lSecureSessionVal", "")
|
86
|
+
self.cookies = {
|
87
|
+
"d2lSessionVal": d2l_session_val,
|
88
|
+
"d2lSecureSessionVal": d2l_secure_session_val
|
89
|
+
}
|
90
|
+
response = await self._post(
|
91
|
+
url=self.url_login,
|
92
|
+
cookies=self.cookies,
|
93
|
+
headers=login_headers,
|
94
|
+
data=login_data,
|
95
|
+
follow_redirects=True,
|
96
|
+
raise_for_status=True,
|
97
|
+
use_proxy= False
|
98
|
+
)
|
99
|
+
csrf_token_match = re.search(r"localStorage\.setItem\('XSRF\.Token','(.*?)'\)", response.text)
|
100
|
+
csrf_token = csrf_token_match.group(1) if csrf_token_match else ""
|
101
|
+
except Exception as err:
|
102
|
+
raise ComponentError(
|
103
|
+
f"D2L: Error getting data from URL {err}"
|
104
|
+
)
|
105
|
+
# Get Bearer Token
|
106
|
+
token_headers = {
|
107
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
108
|
+
"Origin": f"https://{self.domain}",
|
109
|
+
"Referer": f"https://{self.domain}/d2l/home",
|
110
|
+
"x-csrf-token": csrf_token,
|
111
|
+
"User-Agent": random.choice(ua)
|
112
|
+
}
|
113
|
+
token_data = {"scope": "*:*:*"}
|
114
|
+
try:
|
115
|
+
response = await self._post(
|
116
|
+
url=self.url_token,
|
117
|
+
cookies=self.cookies,
|
118
|
+
headers=token_headers,
|
119
|
+
data=token_data,
|
120
|
+
use_proxy= False
|
121
|
+
)
|
122
|
+
json = response.json()
|
123
|
+
with await self.open() as redis:
|
124
|
+
current_timestamp = int(datetime.now(timezone.utc).timestamp())
|
125
|
+
expires_at = json.get('expires_at', (current_timestamp - 600))
|
126
|
+
timeout = expires_at - current_timestamp
|
127
|
+
self.setexp('D2L_API_KEY', json.get("access_token", None), f'{timeout}s')
|
128
|
+
self.setexp('D2L_SESSION_VAL', d2l_session_val, f'{timeout}s')
|
129
|
+
self.setexp('D2L_SECURE_SESSION_VAL', d2l_secure_session_val, f'{timeout}s')
|
130
|
+
self.auth['apikey'] = json.get("access_token", None)
|
131
|
+
self.headers["Authorization"] = f"Bearer {self.auth.get('apikey')}"
|
132
|
+
return self.auth['apikey']
|
133
|
+
except Exception as err:
|
134
|
+
raise ComponentError(
|
135
|
+
f"D2L: Error getting data from URL {err}"
|
136
|
+
)
|
137
|
+
|
138
|
+
async def download_file(self):
|
139
|
+
# Get Download URL
|
140
|
+
url = f'https://{self.domain}/d2l/api/lp/1.45/datasets/bds/{self.schema}/extracts'
|
141
|
+
response = await self.api_get(
|
142
|
+
url=url,
|
143
|
+
headers=self.headers,
|
144
|
+
use_proxy=False
|
145
|
+
)
|
146
|
+
download_link = ''
|
147
|
+
if hasattr(self, "masks") and hasattr(self, 'date'):
|
148
|
+
self.date = self.mask_replacement(self.date)
|
149
|
+
for obj in response.get('Objects', []):
|
150
|
+
if hasattr(self, "date") and self.date:
|
151
|
+
target_date = datetime.strptime(self.date, "%Y-%m-%d").date()
|
152
|
+
if obj.get("BdsType") == "Differential":
|
153
|
+
created_date = datetime.strptime(obj.get("CreatedDate", ""), "%Y-%m-%dT%H:%M:%S.%fZ").date()
|
154
|
+
if created_date == target_date:
|
155
|
+
download_link = obj.get("DownloadLink")
|
156
|
+
break
|
157
|
+
else:
|
158
|
+
if obj.get('BdsType', '') == 'Full':
|
159
|
+
download_link = obj.get('DownloadLink', '')
|
160
|
+
break
|
161
|
+
# Download ZIP File
|
162
|
+
self.download = True
|
163
|
+
await self.async_request(
|
164
|
+
url=download_link
|
165
|
+
)
|
166
|
+
return True
|
167
|
+
|
168
|
+
async def request_iterate(self, endpoint, api=True, **kwargs):
|
169
|
+
has_more_items = True
|
170
|
+
resultset = []
|
171
|
+
bookmark = 0
|
172
|
+
if api == True:
|
173
|
+
while has_more_items == True:
|
174
|
+
url = f'https://{self.domain}/d2l/api{endpoint}/?bookmark={bookmark}'
|
175
|
+
response = await self.api_get(
|
176
|
+
url=url,
|
177
|
+
headers=self.headers,
|
178
|
+
use_proxy= False
|
179
|
+
)
|
180
|
+
if not response['Items']:
|
181
|
+
break
|
182
|
+
else:
|
183
|
+
bookmark = response['PagingInfo']['Bookmark']
|
184
|
+
has_more_items = response['PagingInfo']['HasMoreItems']
|
185
|
+
resultset = [*resultset, *response['Items']]
|
186
|
+
#break
|
187
|
+
return resultset
|
188
|
+
else:
|
189
|
+
item = kwargs.get('item', '')
|
190
|
+
while has_more_items == True:
|
191
|
+
url = f'https://{self.domain}/d2l{endpoint}/?limit=100&offset={bookmark}'
|
192
|
+
try:
|
193
|
+
response = await self.api_get(
|
194
|
+
url=url,
|
195
|
+
headers=self.headers,
|
196
|
+
cookies=self.cookies,
|
197
|
+
use_proxy= False
|
198
|
+
)
|
199
|
+
if not response[item]:
|
200
|
+
break
|
201
|
+
else:
|
202
|
+
bookmark += 100
|
203
|
+
has_more_items = response['Metadata']['HasMore']
|
204
|
+
resultset = [*resultset, *response[item]]
|
205
|
+
#break
|
206
|
+
except Exception:
|
207
|
+
break
|
208
|
+
return resultset
|
209
|
+
|
210
|
+
async def awards(self, org_units=None):
|
211
|
+
result = []
|
212
|
+
|
213
|
+
if org_units is None:
|
214
|
+
org_units = await self.request_iterate('/lp/1.49/orgstructure', True)
|
215
|
+
org_units = [item["Identifier"] for item in org_units["Items"]]
|
216
|
+
|
217
|
+
for org_unit_id in org_units:
|
218
|
+
users = await self.request_iterate(f'/awards/v1/{org_unit_id}/classlist', False, item='Users')
|
219
|
+
for user in users:
|
220
|
+
user_id = user['UserId']
|
221
|
+
org_unit_id = user['OrgUnitId']
|
222
|
+
|
223
|
+
if user['Paging'].get('HasMore', False) == True:
|
224
|
+
awards = await self.request_iterate(f'/awards/v1/{org_unit_id}/myAwards/{user_id}', False, item='Awards')
|
225
|
+
else:
|
226
|
+
awards = user['Awards']
|
227
|
+
|
228
|
+
for award in awards:
|
229
|
+
result.append({
|
230
|
+
'award_id': award['AwardId'],
|
231
|
+
'user_id': user_id,
|
232
|
+
'org_unit_id': org_unit_id,
|
233
|
+
'certificate_id': award['CertificateId'],
|
234
|
+
'achievement_id': award['AchievementId'],
|
235
|
+
'achievement': award['Achievement'].get('Title ', None),
|
236
|
+
'awarded_by': award['AwardedBy'],
|
237
|
+
'issue_date': award['IssueDate'][14:-1]
|
238
|
+
})
|
239
|
+
return result
|
@@ -0,0 +1,223 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
import asyncio
|
3
|
+
import pandas
|
4
|
+
from asyncdb import AsyncDB
|
5
|
+
from navconfig.logging import logging
|
6
|
+
from querysource.conf import asyncpg_url, default_dsn
|
7
|
+
from ..credentials import CredentialsInterface
|
8
|
+
from ...utils.functions import is_empty, as_boolean
|
9
|
+
from ...exceptions import DataNotFound
|
10
|
+
|
11
|
+
|
12
|
+
class DBSupport(CredentialsInterface):
|
13
|
+
"""DBSupport.
|
14
|
+
|
15
|
+
Interface for adding AsyncbDB-based Database Support to Components.
|
16
|
+
"""
|
17
|
+
_service_name: str = 'Flowtask'
|
18
|
+
_credentials = {
|
19
|
+
"user": str,
|
20
|
+
"password": str,
|
21
|
+
"host": str,
|
22
|
+
"port": int,
|
23
|
+
"database": str,
|
24
|
+
}
|
25
|
+
|
26
|
+
def __init__(
|
27
|
+
self,
|
28
|
+
*args,
|
29
|
+
**kwargs
|
30
|
+
):
|
31
|
+
self.as_dataframe: bool = as_boolean(kwargs.get("as_dataframe", False))
|
32
|
+
# using "string" instead objects in pandas
|
33
|
+
self.as_string: bool = as_boolean(kwargs.get("as_string", False))
|
34
|
+
# Infer types:
|
35
|
+
self.infer_types: bool = as_boolean(kwargs.get("infer_types", False))
|
36
|
+
if not hasattr(self, '_logger'):
|
37
|
+
self._logger = logging.getLogger(
|
38
|
+
'Flowtask.DBSupport'
|
39
|
+
)
|
40
|
+
super().__init__(*args, **kwargs)
|
41
|
+
|
42
|
+
def event_loop(
|
43
|
+
self, evt: Optional[asyncio.AbstractEventLoop] = None
|
44
|
+
) -> asyncio.AbstractEventLoop:
|
45
|
+
if evt is not None:
|
46
|
+
asyncio.set_event_loop(evt)
|
47
|
+
return evt
|
48
|
+
else:
|
49
|
+
try:
|
50
|
+
return asyncio.get_event_loop()
|
51
|
+
except RuntimeError as exc:
|
52
|
+
try:
|
53
|
+
evt = asyncio.new_event_loop()
|
54
|
+
asyncio.set_event_loop(evt)
|
55
|
+
return evt
|
56
|
+
except RuntimeError as exc:
|
57
|
+
raise RuntimeError(
|
58
|
+
f"There is no Event Loop: {exc}"
|
59
|
+
) from exc
|
60
|
+
|
61
|
+
def get_connection(
|
62
|
+
self,
|
63
|
+
driver: str = "pg",
|
64
|
+
dsn: Optional[str] = None,
|
65
|
+
params: Optional[dict] = None,
|
66
|
+
event_loop: Optional[asyncio.AbstractEventLoop] = None,
|
67
|
+
**kwargs,
|
68
|
+
):
|
69
|
+
# TODO: datasources and credentials
|
70
|
+
if not kwargs and driver == "pg":
|
71
|
+
kwargs = {
|
72
|
+
"server_settings": {
|
73
|
+
"application_name": f"{self._service_name}.DB",
|
74
|
+
"client_min_messages": "notice",
|
75
|
+
"max_parallel_workers": "512",
|
76
|
+
"jit": "on",
|
77
|
+
}
|
78
|
+
}
|
79
|
+
if not event_loop:
|
80
|
+
event_loop = self.event_loop()
|
81
|
+
args = {
|
82
|
+
"loop": event_loop,
|
83
|
+
**kwargs
|
84
|
+
}
|
85
|
+
if dsn is not None:
|
86
|
+
args["dsn"] = dsn
|
87
|
+
if params:
|
88
|
+
args["params"] = params
|
89
|
+
return AsyncDB(
|
90
|
+
driver, **args
|
91
|
+
)
|
92
|
+
|
93
|
+
def db_connection(
|
94
|
+
self,
|
95
|
+
driver: str = "pg",
|
96
|
+
credentials: Optional[dict] = None,
|
97
|
+
event_loop: Optional[asyncio.AbstractEventLoop] = None,
|
98
|
+
):
|
99
|
+
if not credentials:
|
100
|
+
credentials = {"dsn": default_dsn}
|
101
|
+
else:
|
102
|
+
credentials = {"params": credentials}
|
103
|
+
kwargs = {}
|
104
|
+
if driver == "pg":
|
105
|
+
kwargs = {
|
106
|
+
"server_settings": {
|
107
|
+
"application_name": f"{self._service_name}.DB",
|
108
|
+
"client_min_messages": "notice",
|
109
|
+
"max_parallel_workers": "512",
|
110
|
+
"jit": "on",
|
111
|
+
}
|
112
|
+
}
|
113
|
+
if not event_loop:
|
114
|
+
event_loop = self.event_loop()
|
115
|
+
return AsyncDB(
|
116
|
+
driver,
|
117
|
+
loop=event_loop,
|
118
|
+
**credentials,
|
119
|
+
**kwargs
|
120
|
+
)
|
121
|
+
|
122
|
+
def pg_connection(
|
123
|
+
self,
|
124
|
+
dsn: Optional[str] = None,
|
125
|
+
credentials: Optional[dict] = None,
|
126
|
+
event_loop: Optional[asyncio.AbstractEventLoop] = None,
|
127
|
+
):
|
128
|
+
if not credentials:
|
129
|
+
if dsn is not None:
|
130
|
+
credentials = {"dsn": dsn}
|
131
|
+
else:
|
132
|
+
credentials = {"dsn": asyncpg_url}
|
133
|
+
else:
|
134
|
+
credentials = {"params": credentials}
|
135
|
+
kwargs: dict = {
|
136
|
+
"min_size": 2,
|
137
|
+
"server_settings": {
|
138
|
+
"application_name": f"{self._service_name}.DB",
|
139
|
+
"client_min_messages": "notice",
|
140
|
+
"max_parallel_workers": "512",
|
141
|
+
"jit": "on",
|
142
|
+
},
|
143
|
+
}
|
144
|
+
if not event_loop:
|
145
|
+
event_loop = self.event_loop()
|
146
|
+
return AsyncDB(
|
147
|
+
"pg",
|
148
|
+
loop=event_loop, **credentials, **kwargs
|
149
|
+
)
|
150
|
+
|
151
|
+
def get_default_driver(self, driver: str):
|
152
|
+
"""get_default_driver.
|
153
|
+
|
154
|
+
Getting a default connection based on driver's name.
|
155
|
+
"""
|
156
|
+
driver_path = f"querysource.datasources.drivers.{driver}"
|
157
|
+
drv = f"{driver}_default"
|
158
|
+
try:
|
159
|
+
driver_module = __import__(driver_path, fromlist=[driver])
|
160
|
+
drv_obj = getattr(driver_module, drv)
|
161
|
+
return drv_obj
|
162
|
+
except ImportError as err:
|
163
|
+
raise ImportError(
|
164
|
+
f"Error importing driver: {err!s}"
|
165
|
+
) from err
|
166
|
+
except AttributeError as err:
|
167
|
+
raise AttributeError(
|
168
|
+
f"Error getting driver: {err!s}"
|
169
|
+
) from err
|
170
|
+
except Exception as err:
|
171
|
+
raise Exception(
|
172
|
+
f"Error getting default connection: {err!s}"
|
173
|
+
) from err
|
174
|
+
|
175
|
+
def default_connection(self, driver: str):
|
176
|
+
"""default_connection.
|
177
|
+
|
178
|
+
Default Connection to Database.
|
179
|
+
"""
|
180
|
+
credentials = {}
|
181
|
+
try:
|
182
|
+
driver = self.get_default_driver(driver)
|
183
|
+
credentials = driver.params()
|
184
|
+
if driver.driver == 'pg' and credentials.get('username', None) is not None:
|
185
|
+
credentials['user'] = credentials.pop('username')
|
186
|
+
except ImportError as err:
|
187
|
+
raise ImportError(
|
188
|
+
f"Error importing Default driver: {err!s}"
|
189
|
+
) from err
|
190
|
+
try:
|
191
|
+
return self.get_connection(
|
192
|
+
driver=driver.driver,
|
193
|
+
params=credentials
|
194
|
+
)
|
195
|
+
except Exception as err:
|
196
|
+
raise Exception(
|
197
|
+
f"Error getting Default Connection: {err!s}"
|
198
|
+
) from err
|
199
|
+
|
200
|
+
async def get_dataframe(self, result):
|
201
|
+
try:
|
202
|
+
df = pandas.DataFrame(result)
|
203
|
+
except Exception as err: # pylint: disable=W0703
|
204
|
+
logging.exception(err, stack_info=True)
|
205
|
+
# Attempt to infer better dtypes for object columns.
|
206
|
+
if is_empty(df):
|
207
|
+
raise DataNotFound("DbClient: Data not Found")
|
208
|
+
df.infer_objects()
|
209
|
+
if self.infer_types is True:
|
210
|
+
df = df.convert_dtypes(convert_string=self.as_string)
|
211
|
+
if self._debug is True:
|
212
|
+
print(df.dtypes)
|
213
|
+
if hasattr(self, "drop_empty"):
|
214
|
+
df.dropna(axis=1, how="all", inplace=True)
|
215
|
+
df.dropna(axis=0, how="all", inplace=True)
|
216
|
+
if hasattr(self, "dropna"):
|
217
|
+
df.dropna(subset=self.dropna, how="all", inplace=True)
|
218
|
+
if (
|
219
|
+
hasattr(self, "clean_strings") and getattr(self, "clean_strings", False) is True
|
220
|
+
):
|
221
|
+
u = df.select_dtypes(include=["object", "string"])
|
222
|
+
df[u.columns] = u.fillna("")
|
223
|
+
return df
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
from querysource.conf import (
|
3
|
+
DOCUMENTDB_HOSTNAME,
|
4
|
+
DOCUMENTDB_PORT,
|
5
|
+
DOCUMENTDB_DATABASE,
|
6
|
+
DOCUMENTDB_USERNAME,
|
7
|
+
DOCUMENTDB_PASSWORD,
|
8
|
+
DOCUMENTDB_TLSFILE,
|
9
|
+
)
|
10
|
+
from .db import DBSupport
|
11
|
+
|
12
|
+
|
13
|
+
class DocumentDBSupport(DBSupport):
|
14
|
+
"""DocumentDBSupport.
|
15
|
+
|
16
|
+
Interface for adding AWS DocumentDB Database Support to Components.
|
17
|
+
"""
|
18
|
+
_service_name: str = 'Flowtask'
|
19
|
+
driver: str = 'mongo'
|
20
|
+
_credentials = {
|
21
|
+
"host": str,
|
22
|
+
"port": int,
|
23
|
+
"username": str,
|
24
|
+
"password": str,
|
25
|
+
"database": str,
|
26
|
+
"dbtype": "documentdb",
|
27
|
+
"ssl": True,
|
28
|
+
"tlsCAFile": str,
|
29
|
+
}
|
30
|
+
|
31
|
+
def default_connection(self, driver: str = 'mongo', credentials: Optional[dict] = None):
|
32
|
+
"""default_connection.
|
33
|
+
|
34
|
+
Default Connection to RethinkDB.
|
35
|
+
"""
|
36
|
+
if not credentials:
|
37
|
+
credentials = {
|
38
|
+
"host": DOCUMENTDB_HOSTNAME,
|
39
|
+
"port": DOCUMENTDB_PORT,
|
40
|
+
"username": DOCUMENTDB_USERNAME,
|
41
|
+
"password": DOCUMENTDB_PASSWORD,
|
42
|
+
"database": DOCUMENTDB_DATABASE,
|
43
|
+
"dbtype": "documentdb",
|
44
|
+
"ssl": True,
|
45
|
+
"tlsCAFile": DOCUMENTDB_TLSFILE,
|
46
|
+
}
|
47
|
+
try:
|
48
|
+
return self.get_connection(
|
49
|
+
driver=driver,
|
50
|
+
params=credentials
|
51
|
+
)
|
52
|
+
except Exception as err:
|
53
|
+
raise Exception(
|
54
|
+
f"Error getting Default DocumentDB Connection: {err!s}"
|
55
|
+
) from err
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from .db import DBSupport
|
2
|
+
|
3
|
+
|
4
|
+
class RethinkDBSupport(DBSupport):
|
5
|
+
"""RethinkDBSupport.
|
6
|
+
|
7
|
+
Interface for adding RethinkDB-based Database Support to Components.
|
8
|
+
"""
|
9
|
+
_service_name: str = 'Flowtask'
|
10
|
+
_credentials = {
|
11
|
+
"user": str,
|
12
|
+
"password": str,
|
13
|
+
"host": str,
|
14
|
+
"port": int,
|
15
|
+
"database": str,
|
16
|
+
}
|
17
|
+
|
18
|
+
def default_connection(self, driver: str = 'rethink'):
|
19
|
+
"""default_connection.
|
20
|
+
|
21
|
+
Default Connection to RethinkDB.
|
22
|
+
"""
|
23
|
+
credentials = {}
|
24
|
+
try:
|
25
|
+
driver = self.get_default_driver(driver)
|
26
|
+
credentials = driver.params()
|
27
|
+
except ImportError as err:
|
28
|
+
raise ImportError(
|
29
|
+
f"Error importing RethinkDB driver: {err!s}"
|
30
|
+
) from err
|
31
|
+
try:
|
32
|
+
return self.get_connection(
|
33
|
+
driver=driver.driver,
|
34
|
+
params=credentials
|
35
|
+
)
|
36
|
+
except Exception as err:
|
37
|
+
raise Exception(
|
38
|
+
f"Error getting Default Rethink Connection: {err!s}"
|
39
|
+
) from err
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from typing import Any, Union, ParamSpec
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from navconfig.logging import logging
|
4
|
+
|
5
|
+
|
6
|
+
P = ParamSpec("P")
|
7
|
+
|
8
|
+
|
9
|
+
class BaseDataframe(ABC):
|
10
|
+
|
11
|
+
@abstractmethod
|
12
|
+
async def create_dataframe(
|
13
|
+
self, result: Union[dict, bytes, Any], *args: P.args, **kwargs: P.kwargs
|
14
|
+
) -> Any:
|
15
|
+
"""
|
16
|
+
Converts any result into a DataFrame.
|
17
|
+
|
18
|
+
:param result: The result data to be converted into a DataFrame.
|
19
|
+
:return: A DataFrame containing the result data.
|
20
|
+
"""
|
21
|
+
pass
|
@@ -0,0 +1,71 @@
|
|
1
|
+
from typing import Union, Any, ParamSpec
|
2
|
+
import pandas as pd
|
3
|
+
import orjson
|
4
|
+
import pyarrow as pa
|
5
|
+
import pyarrow.csv as pc
|
6
|
+
import pyarrow.parquet as pq
|
7
|
+
from io import BytesIO
|
8
|
+
from .abstract import BaseDataframe
|
9
|
+
from ...exceptions import ComponentError, DataNotFound
|
10
|
+
|
11
|
+
|
12
|
+
P = ParamSpec("P")
|
13
|
+
|
14
|
+
|
15
|
+
def is_empty(obj):
|
16
|
+
"""check_empty.
|
17
|
+
Check if a basic object, a Apache Arrow Table is empty or not.
|
18
|
+
"""
|
19
|
+
if isinstance(obj, pa.Table):
|
20
|
+
return obj.num_rows == 0
|
21
|
+
else:
|
22
|
+
return bool(not obj)
|
23
|
+
|
24
|
+
|
25
|
+
class ArrowDataframe(BaseDataframe):
|
26
|
+
"""ArrowDataframe.
|
27
|
+
|
28
|
+
Converts any result into a Arrow 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 Arrow DataFrame.
|
36
|
+
|
37
|
+
:param result: The result data to be converted into a Arrow DataFrame.
|
38
|
+
:return: A DataFrame containing the result data.
|
39
|
+
"""
|
40
|
+
if is_empty(result):
|
41
|
+
raise DataNotFound("DataFrame: 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):
|
49
|
+
names = list(result[0].keys())
|
50
|
+
df = pa.Table.from_arrays(result, names=names, **kwargs)
|
51
|
+
elif isinstance(result, bytes) or isinstance(result, BytesIO):
|
52
|
+
try:
|
53
|
+
# Reset the pointer to the start of the stream
|
54
|
+
result.seek(0)
|
55
|
+
df = pc.read_csv(result, **kwargs)
|
56
|
+
except pa.lib.ArrowInvalid as e:
|
57
|
+
# Use pyarrow.parquet.read_table to read Parquet data
|
58
|
+
df = pq.read_table(result)
|
59
|
+
else:
|
60
|
+
df = pa.Table.from_pandas(pd.DataFrame(result, **kwargs))
|
61
|
+
numrows = df.num_rows
|
62
|
+
numcols = df.num_columns
|
63
|
+
try:
|
64
|
+
self._variables["_numRows_"] = numrows
|
65
|
+
self.add_metric("NUM_ROWS", numrows)
|
66
|
+
self.add_metric("NUM_COLS", numcols)
|
67
|
+
except Exception:
|
68
|
+
pass
|
69
|
+
return df
|
70
|
+
except Exception as err:
|
71
|
+
raise ComponentError(f"Error Creating Dataframe: {err!s}")
|