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,136 @@
|
|
1
|
+
import os
|
2
|
+
import asyncio
|
3
|
+
import logging
|
4
|
+
from collections.abc import Callable
|
5
|
+
import aiofiles
|
6
|
+
from ..exceptions import FileError
|
7
|
+
from .UploadTo import UploadToBase
|
8
|
+
from ..interfaces.Boto3Client import Boto3Client
|
9
|
+
|
10
|
+
|
11
|
+
class UploadToS3(Boto3Client, UploadToBase):
|
12
|
+
"""
|
13
|
+
UploadToS3
|
14
|
+
|
15
|
+
Overview
|
16
|
+
|
17
|
+
The `UploadToS3` class is a specialized component that facilitates the uploading of files to an Amazon S3 bucket.
|
18
|
+
This class extends both the `Boto3Client` and `UploadToBase` classes, providing integration with AWS S3 for file
|
19
|
+
storage operations. The component supports the upload of individual files, multiple files, or entire directories.
|
20
|
+
|
21
|
+
.. table:: Properties
|
22
|
+
:widths: auto
|
23
|
+
|
24
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
25
|
+
| Name | Required | Description |
|
26
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
27
|
+
| bucket | Yes | The name of the S3 bucket to which files will be uploaded. |
|
28
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
29
|
+
| directory | Yes | The S3 directory path where files will be uploaded. |
|
30
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
31
|
+
| source_dir | Yes | The local directory containing the files to be uploaded. |
|
32
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
33
|
+
| _filenames | Yes | A list of filenames to be uploaded. |
|
34
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
35
|
+
| whole_dir | No | A flag indicating whether to upload all files in the source directory. |
|
36
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
37
|
+
| ContentType | No | The MIME type of the files to be uploaded. Defaults to "binary/octet-stream".|
|
38
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
39
|
+
| credentials | Yes | A dictionary containing the credentials necessary for AWS authentication. |
|
40
|
+
+-------------------------+----------+-----------+--------------------------------------------------------------------------+
|
41
|
+
|
42
|
+
Return
|
43
|
+
|
44
|
+
The `run` method uploads files to the specified S3 bucket, returning a dictionary containing the list of successfully
|
45
|
+
uploaded files and any errors encountered during the upload process.
|
46
|
+
|
47
|
+
"""
|
48
|
+
|
49
|
+
def __init__(
|
50
|
+
self,
|
51
|
+
loop: asyncio.AbstractEventLoop = None,
|
52
|
+
job: Callable = None,
|
53
|
+
stat: Callable = None,
|
54
|
+
**kwargs,
|
55
|
+
):
|
56
|
+
self.mdate = None
|
57
|
+
self.local_name = None
|
58
|
+
self.filename: str = ""
|
59
|
+
self.whole_dir: bool = False
|
60
|
+
self.preserve = True
|
61
|
+
self.ContentType: str = "binary/octet-stream"
|
62
|
+
super().__init__(loop=loop, job=job, stat=stat, **kwargs)
|
63
|
+
|
64
|
+
async def start(self, **kwargs):
|
65
|
+
"""start Method."""
|
66
|
+
await super(UploadToS3, self).start(**kwargs)
|
67
|
+
if hasattr(self, "destination"):
|
68
|
+
self.directory = self.destination["directory"]
|
69
|
+
if not self.directory.endswith("/"):
|
70
|
+
self.directory = self.source_dir + "/"
|
71
|
+
self.directory = self.mask_replacement(self.destination["directory"])
|
72
|
+
if hasattr(self, "source"):
|
73
|
+
self.whole_dir = (
|
74
|
+
self.source["whole_dir"] if "whole_dir" in self.source else False
|
75
|
+
)
|
76
|
+
if self.whole_dir is True:
|
77
|
+
# if whole dir, is all files in source directory
|
78
|
+
logging.debug(f"Uploading all files on directory {self.source_dir}")
|
79
|
+
p = self.source_dir.glob("**/*")
|
80
|
+
self._filenames = [x for x in p if x.is_file()]
|
81
|
+
else:
|
82
|
+
if "filename" in self.source:
|
83
|
+
p = self.source_dir.glob(self.filename)
|
84
|
+
self._filenames = [x for x in p if x.is_file()]
|
85
|
+
try:
|
86
|
+
if self.previous and self.input:
|
87
|
+
self._filenames = self.input
|
88
|
+
if hasattr(self, "file"):
|
89
|
+
filenames = []
|
90
|
+
for f in self._filenames:
|
91
|
+
p = self.source_dir.glob(f)
|
92
|
+
fp = [x for x in p if x.is_file()]
|
93
|
+
filenames = filenames + fp
|
94
|
+
self._filenames = filenames
|
95
|
+
except (NameError, KeyError):
|
96
|
+
pass
|
97
|
+
return self
|
98
|
+
|
99
|
+
async def close(self):
|
100
|
+
pass
|
101
|
+
|
102
|
+
async def run(self):
|
103
|
+
"""Running Upload file to S3."""
|
104
|
+
self._result = None
|
105
|
+
try:
|
106
|
+
use_credentials = self.credentials["use_credentials"]
|
107
|
+
# del self.credentials['use_credentials']
|
108
|
+
except KeyError:
|
109
|
+
use_credentials = False
|
110
|
+
async with self.get_client(
|
111
|
+
use_credentials, credentials=self.credentials, service=self.service
|
112
|
+
) as s3_client:
|
113
|
+
errors = {}
|
114
|
+
files = {}
|
115
|
+
for file in self._filenames:
|
116
|
+
key = os.path.basename(file)
|
117
|
+
filename = f"{self.directory}{key}"
|
118
|
+
print("FILENAME ", filename)
|
119
|
+
# TODO: making async with chunks (part data)
|
120
|
+
async with aiofiles.open(file, mode="rb") as f:
|
121
|
+
content = await f.read()
|
122
|
+
response = await s3_client.put_object(
|
123
|
+
Bucket=self.bucket,
|
124
|
+
Key=filename,
|
125
|
+
Body=content,
|
126
|
+
ContentType=self.ContentType,
|
127
|
+
)
|
128
|
+
rsp = response["ResponseMetadata"]
|
129
|
+
status_code = int(rsp["HTTPStatusCode"])
|
130
|
+
if status_code == 200:
|
131
|
+
files[file] = filename
|
132
|
+
else:
|
133
|
+
errors[file] = FileError(f"S3: Upload Error: {rsp!s}")
|
134
|
+
self._result = {"files": files, "errors": errors}
|
135
|
+
self.add_metric("S3_UPLOADED", files)
|
136
|
+
return self._result
|
@@ -0,0 +1,160 @@
|
|
1
|
+
import asyncio
|
2
|
+
from collections.abc import Callable
|
3
|
+
import asyncssh
|
4
|
+
from ..exceptions import ComponentError, FileNotFound
|
5
|
+
from .UploadTo import UploadToBase
|
6
|
+
from ..interfaces.SSHClient import SSHClient
|
7
|
+
|
8
|
+
|
9
|
+
class UploadToSFTP(SSHClient, UploadToBase):
|
10
|
+
"""
|
11
|
+
UploadToSFTP
|
12
|
+
|
13
|
+
Overview
|
14
|
+
|
15
|
+
The UploadToSFTP class is a component for uploading files or entire directories to an SSH/SFTP server.
|
16
|
+
It supports various configurations, including recursive directory uploads, customizable transfer settings,
|
17
|
+
and real-time upload progress tracking.
|
18
|
+
|
19
|
+
.. table:: Properties
|
20
|
+
:widths: auto
|
21
|
+
|
22
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
23
|
+
| Name | Required | Summary |
|
24
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
25
|
+
| source | Yes | A dictionary specifying the source directory, filename, and/or |
|
26
|
+
| | | recursive setting for selecting files to upload. |
|
27
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
28
|
+
| destination | Yes | A dictionary defining the target directory on the SFTP server. |
|
29
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
30
|
+
| whole_dir | No | Boolean indicating if the entire source directory should be uploaded. |
|
31
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
32
|
+
| block_size | No | Integer defining the block size for file transfer, defaults to 65356. |
|
33
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
34
|
+
| max_requests | No | Integer setting the max number of parallel requests, defaults to 1. |
|
35
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
36
|
+
|
37
|
+
Returns
|
38
|
+
|
39
|
+
This component uploads files to the specified SFTP directory and returns a list of uploaded files on success.
|
40
|
+
If no files are found or a connection error occurs, it raises a relevant exception. Metrics on the number of
|
41
|
+
files uploade
|
42
|
+
|
43
|
+
|
44
|
+
Example:
|
45
|
+
|
46
|
+
```yaml
|
47
|
+
UploadToSFTP:
|
48
|
+
host: sftp.example.com
|
49
|
+
port: 22
|
50
|
+
credentials:
|
51
|
+
username: sftpuser
|
52
|
+
password: abcd1234
|
53
|
+
destination:
|
54
|
+
directory: /incoming/
|
55
|
+
```
|
56
|
+
|
57
|
+
""" #noqa
|
58
|
+
def __init__(
|
59
|
+
self,
|
60
|
+
loop: asyncio.AbstractEventLoop = None,
|
61
|
+
job: Callable = None,
|
62
|
+
stat: Callable = None,
|
63
|
+
**kwargs,
|
64
|
+
):
|
65
|
+
self.mdate = None
|
66
|
+
self.local_name = None
|
67
|
+
self.filename: str = ""
|
68
|
+
self.whole_dir: bool = False
|
69
|
+
self.preserve = True
|
70
|
+
self.block_size: int = 65356
|
71
|
+
self.max_requests: int = 1
|
72
|
+
super().__init__(loop=loop, job=job, stat=stat, **kwargs)
|
73
|
+
|
74
|
+
async def start(self, **kwargs):
|
75
|
+
"""start Method."""
|
76
|
+
await super(UploadToSFTP, self).start(**kwargs)
|
77
|
+
if hasattr(self, "source"):
|
78
|
+
self.whole_dir = (
|
79
|
+
self.source["whole_dir"] if "whole_dir" in self.source else False
|
80
|
+
)
|
81
|
+
if hasattr(self, "destination"):
|
82
|
+
self.directory = self.destination["directory"]
|
83
|
+
try:
|
84
|
+
if self.previous and self.input:
|
85
|
+
self.filename = self.input
|
86
|
+
elif self.file:
|
87
|
+
self.filename = self.process_pattern("file")
|
88
|
+
except (NameError, KeyError):
|
89
|
+
pass
|
90
|
+
return self
|
91
|
+
|
92
|
+
def upload_progress(self, srcpath, dstpath, bytes_copied, total_bytes):
|
93
|
+
self._pb.reset(total=total_bytes)
|
94
|
+
self._pb.update(bytes_copied)
|
95
|
+
self._pb.refresh()
|
96
|
+
|
97
|
+
async def run(self):
|
98
|
+
"""Running Download file."""
|
99
|
+
self._result = None
|
100
|
+
status = False
|
101
|
+
try:
|
102
|
+
async with await self.open(
|
103
|
+
host=self.host,
|
104
|
+
port=self.port,
|
105
|
+
tunnel=self.tunnel,
|
106
|
+
credentials=self.credentials,
|
107
|
+
):
|
108
|
+
async with self._connection.start_sftp_client() as sftp:
|
109
|
+
# check all versions of functionalities
|
110
|
+
args = {
|
111
|
+
"block_size": self.block_size,
|
112
|
+
"max_requests": self.max_requests,
|
113
|
+
"progress_handler": self.upload_progress,
|
114
|
+
"error_handler": self.err_handler,
|
115
|
+
}
|
116
|
+
if self.whole_dir is True:
|
117
|
+
self._logger.debug(
|
118
|
+
f"Uploading all files on directory {self.source_dir}"
|
119
|
+
)
|
120
|
+
file = "{}/*".format(self.source_dir)
|
121
|
+
p = self.source_dir.glob("**/*")
|
122
|
+
self.filename = [x for x in p if x.is_file()]
|
123
|
+
else:
|
124
|
+
file = self.filename
|
125
|
+
args["remotepath"] = self.directory
|
126
|
+
if hasattr(self, "source"):
|
127
|
+
args["recurse"] = True if "recursive" in self.source else False
|
128
|
+
if not file:
|
129
|
+
raise FileNotFound(f"There is no local File: {file}")
|
130
|
+
self.start_progress(total=len(file))
|
131
|
+
try:
|
132
|
+
self._logger.debug(f"Uploading file: {file} to {self.directory}")
|
133
|
+
status = await sftp.mput(file, **args)
|
134
|
+
self.close_progress()
|
135
|
+
except OSError as err:
|
136
|
+
self._logger.error(f"Upload SFTP local error: {err}")
|
137
|
+
return False
|
138
|
+
except asyncssh.sftp.SFTPError as err:
|
139
|
+
self._logger.error(f"SFTP UploadTo Server error: {err}")
|
140
|
+
return False
|
141
|
+
except asyncssh.Error as err:
|
142
|
+
self._logger.error(f"Upload 2 SFTP: connection failed: {err}")
|
143
|
+
except Exception as err:
|
144
|
+
self._logger.exception(err)
|
145
|
+
raise
|
146
|
+
except asyncio.CancelledError:
|
147
|
+
self._logger.info(
|
148
|
+
f"{self.host} CANCELED~"
|
149
|
+
)
|
150
|
+
# break
|
151
|
+
except (asyncio.TimeoutError, ComponentError) as err:
|
152
|
+
raise ComponentError(f"{err!s}") from err
|
153
|
+
except Exception as err:
|
154
|
+
raise ComponentError(f"{err!s}") from err
|
155
|
+
if status is False:
|
156
|
+
return False
|
157
|
+
else:
|
158
|
+
self.add_metric("SFTP_FILES", self.filename)
|
159
|
+
self._result = self.filename
|
160
|
+
return self._result
|
@@ -0,0 +1,205 @@
|
|
1
|
+
import os
|
2
|
+
from collections.abc import Callable
|
3
|
+
import asyncio
|
4
|
+
import logging
|
5
|
+
from pathlib import Path
|
6
|
+
from ..exceptions import (
|
7
|
+
FileError,
|
8
|
+
ConfigError
|
9
|
+
)
|
10
|
+
from .UploadTo import UploadToBase
|
11
|
+
from ..interfaces.Sharepoint import SharepointClient
|
12
|
+
|
13
|
+
|
14
|
+
class UploadToSharepoint(SharepointClient, UploadToBase):
|
15
|
+
"""
|
16
|
+
UploadToSharepoint
|
17
|
+
|
18
|
+
Overview
|
19
|
+
|
20
|
+
The UploadToSharepoint class is a component for uploading files or entire directories to a SharePoint site.
|
21
|
+
It supports various configuration options for selecting files by name, extension, or pattern, and includes
|
22
|
+
functionality for recursive directory searches.
|
23
|
+
|
24
|
+
.. table:: Properties
|
25
|
+
:widths: auto
|
26
|
+
|
27
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
28
|
+
| Name | Required | Summary |
|
29
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
30
|
+
| credentials | Yes | A dictionary with SharePoint credentials: `username`, `password`, |
|
31
|
+
| | | `tenant`, and `site`. |
|
32
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
33
|
+
| source | Yes | A dictionary specifying the source directory, filename, and/or file |
|
34
|
+
| | | extension for selecting files to upload. |
|
35
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
36
|
+
| destination | Yes | A dictionary defining the SharePoint destination directory. |
|
37
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
38
|
+
| whole_dir | No | Boolean indicating if the entire source directory should be uploaded. |
|
39
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
40
|
+
| recursive | No | Boolean specifying whether to search recursively within directories. |
|
41
|
+
+----------------+----------+-----------+---------------------------------------------------------------+
|
42
|
+
|
43
|
+
Returns
|
44
|
+
|
45
|
+
This component uploads files to a specified SharePoint directory and returns the upload result status.
|
46
|
+
It logs the upload activity and records metrics for the number of files uploaded. If no files are found
|
47
|
+
or the configuration is incomplete, it raises an error. The upload can handle both individual files and
|
48
|
+
entire folders, depending on configuration.
|
49
|
+
|
50
|
+
|
51
|
+
Example:
|
52
|
+
|
53
|
+
```yaml
|
54
|
+
UploadToSharepoint:
|
55
|
+
credentials:
|
56
|
+
username: sharepoint_username
|
57
|
+
password: sharepoint_password
|
58
|
+
tenant: symbits
|
59
|
+
site: trocstorage
|
60
|
+
destination:
|
61
|
+
directory: Shared Documents/Optimum Sales Files
|
62
|
+
masks:
|
63
|
+
'{today}':
|
64
|
+
- today
|
65
|
+
- mask: '%Y%m%d%H%M%S'
|
66
|
+
```
|
67
|
+
|
68
|
+
""" # noqa
|
69
|
+
|
70
|
+
# dict of expected credentials
|
71
|
+
_credentials: dict = {
|
72
|
+
"username": str,
|
73
|
+
"password": str,
|
74
|
+
"tenant": str,
|
75
|
+
"site": str
|
76
|
+
}
|
77
|
+
|
78
|
+
def __init__(
|
79
|
+
self,
|
80
|
+
loop: asyncio.AbstractEventLoop = None,
|
81
|
+
job: Callable = None,
|
82
|
+
stat: Callable = None,
|
83
|
+
**kwargs,
|
84
|
+
):
|
85
|
+
self.mdate = None
|
86
|
+
self.local_name = None
|
87
|
+
self.filename: str = ""
|
88
|
+
self.whole_dir: bool = False
|
89
|
+
self.preserve = True
|
90
|
+
self.ContentType: str = "binary/octet-stream"
|
91
|
+
self.recursive: bool = kwargs.get('recursive', False)
|
92
|
+
super().__init__(
|
93
|
+
loop=loop,
|
94
|
+
job=job,
|
95
|
+
stat=stat,
|
96
|
+
**kwargs
|
97
|
+
)
|
98
|
+
self.define_host = None
|
99
|
+
|
100
|
+
async def start(self, **kwargs):
|
101
|
+
"""start Method."""
|
102
|
+
await super(UploadToSharepoint, self).start(**kwargs)
|
103
|
+
if hasattr(self, "source"):
|
104
|
+
self.source_dir = self.source.get('directory')
|
105
|
+
if isinstance(self.source_dir, str):
|
106
|
+
self.source_dir = Path(self.source_dir).resolve()
|
107
|
+
self.filename = self.source.get("filename", None)
|
108
|
+
self.whole_dir = (
|
109
|
+
self.source["whole_dir"] if "whole_dir" in self.source else False
|
110
|
+
)
|
111
|
+
if self.whole_dir is True:
|
112
|
+
# if whole dir, is all files in source directory
|
113
|
+
logging.debug(
|
114
|
+
f"Uploading all files on directory {self.source_dir}"
|
115
|
+
)
|
116
|
+
p = self.source_dir.glob("**/*")
|
117
|
+
self._filenames = [
|
118
|
+
x for x in p if x.is_file()
|
119
|
+
]
|
120
|
+
else:
|
121
|
+
if "filename" in self.source:
|
122
|
+
filename = self.source_dir.joinpath(self.source_file)
|
123
|
+
if filename.is_dir():
|
124
|
+
p = self.source_dir.glob(filename)
|
125
|
+
self._filenames = [
|
126
|
+
x for x in p if x.is_file()
|
127
|
+
]
|
128
|
+
else:
|
129
|
+
self._filenames = [filename]
|
130
|
+
elif 'extension' in self.source:
|
131
|
+
extension = self.source["extension"]
|
132
|
+
pattern = self.source.get("pattern", None)
|
133
|
+
if pattern:
|
134
|
+
# TODO: fix recursive problem from Glob
|
135
|
+
if self.recursive is True:
|
136
|
+
p = self.source_dir.rglob(f"**/*{pattern}*{extension}")
|
137
|
+
else:
|
138
|
+
p = self.source_dir.glob(f"*{pattern}*{extension}")
|
139
|
+
else:
|
140
|
+
if self.recursive is True:
|
141
|
+
p = self.source_dir.rglob(f"**/*{extension}")
|
142
|
+
else:
|
143
|
+
p = self.source_dir.glob(f"*{pattern}*{extension}")
|
144
|
+
self._filenames = [
|
145
|
+
x for x in p if x.is_file()
|
146
|
+
]
|
147
|
+
else:
|
148
|
+
raise ConfigError(
|
149
|
+
"UploadToSharepoint: No filename or extension in source"
|
150
|
+
)
|
151
|
+
if hasattr(self, "destination"):
|
152
|
+
# Destination in Sharepoint:
|
153
|
+
self.directory = self.destination["directory"]
|
154
|
+
if not self.directory.endswith("/"):
|
155
|
+
self.directory = str(self.directory) + "/"
|
156
|
+
self.directory = self.mask_replacement(self.destination["directory"])
|
157
|
+
else:
|
158
|
+
if self.previous and self.input:
|
159
|
+
self._filenames = self.input
|
160
|
+
if hasattr(self, "file"):
|
161
|
+
filenames = []
|
162
|
+
for f in self._filenames:
|
163
|
+
p = self.source_dir.glob(f)
|
164
|
+
fp = [x for x in p if x.is_file()]
|
165
|
+
filenames = filenames + fp
|
166
|
+
self._filenames = filenames
|
167
|
+
elif 'extension' in self.source:
|
168
|
+
extension = self.source["extension"]
|
169
|
+
pattern = self.source.get("pattern", None)
|
170
|
+
# check if files in self._filenames ends with extension
|
171
|
+
filenames = []
|
172
|
+
for f in self._filenames:
|
173
|
+
if f.suffix == extension:
|
174
|
+
# check if pattern is in the filename
|
175
|
+
if pattern:
|
176
|
+
if pattern in f.name:
|
177
|
+
filenames.append(f)
|
178
|
+
continue
|
179
|
+
else:
|
180
|
+
filenames.append(f)
|
181
|
+
self._filenames = filenames
|
182
|
+
return self
|
183
|
+
|
184
|
+
async def close(self):
|
185
|
+
pass
|
186
|
+
|
187
|
+
async def run(self):
|
188
|
+
"""Upload a File to Sharepoint"""
|
189
|
+
self._result = None
|
190
|
+
async with self.connection():
|
191
|
+
if not self.context:
|
192
|
+
self.context = self.get_context(self.url)
|
193
|
+
if not self._filenames:
|
194
|
+
raise FileError("No files to upload")
|
195
|
+
if self.whole_dir is True:
|
196
|
+
# Using Upload entire Folder:
|
197
|
+
self._result = await self.upload_folder(
|
198
|
+
local_folder=self.source_dir
|
199
|
+
)
|
200
|
+
else:
|
201
|
+
self._result = await self.upload_files(
|
202
|
+
filenames=self._filenames
|
203
|
+
)
|
204
|
+
self.add_metric("SHAREPOINT_UPLOADED", self._result)
|
205
|
+
return self._result
|
@@ -0,0 +1,122 @@
|
|
1
|
+
from typing import Union
|
2
|
+
import importlib
|
3
|
+
import asyncio
|
4
|
+
import logging
|
5
|
+
from collections.abc import Callable, Awaitable
|
6
|
+
from ..exceptions import ComponentError
|
7
|
+
from settings.settings import TASK_STORAGES
|
8
|
+
from .flow import FlowComponent
|
9
|
+
|
10
|
+
|
11
|
+
def getFunction(program, function):
|
12
|
+
"""getFunction.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
|
16
|
+
```yaml
|
17
|
+
UserFunc:
|
18
|
+
function: scheduling_visits
|
19
|
+
args:
|
20
|
+
max_distance: 400
|
21
|
+
max_stores: 5
|
22
|
+
year: 2024
|
23
|
+
month: 11
|
24
|
+
```
|
25
|
+
|
26
|
+
"""
|
27
|
+
## TODO: detect TaskStorage of the task
|
28
|
+
storage = TASK_STORAGES["default"]
|
29
|
+
fn_path = storage.path.joinpath(program, "functions", f"{function}.py")
|
30
|
+
try:
|
31
|
+
spec = importlib.util.spec_from_file_location(function, fn_path)
|
32
|
+
module = importlib.util.module_from_spec(spec)
|
33
|
+
spec.loader.exec_module(module)
|
34
|
+
obj = getattr(module, function)
|
35
|
+
return obj
|
36
|
+
except ImportError as e:
|
37
|
+
logging.error(f"UserFunc: No Function {function} was Found")
|
38
|
+
raise ComponentError(
|
39
|
+
f"UserFunc: No Python Function {function} was Found on {fn_path}"
|
40
|
+
) from e
|
41
|
+
|
42
|
+
|
43
|
+
class UserFunc(FlowComponent):
|
44
|
+
"""
|
45
|
+
UserFunc.
|
46
|
+
|
47
|
+
Overview
|
48
|
+
|
49
|
+
Run a arbitrary user function and return result
|
50
|
+
|
51
|
+
.. table:: Properties
|
52
|
+
:widths: auto
|
53
|
+
|
54
|
+
|
55
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
56
|
+
| Name | Required | Summary |
|
57
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
58
|
+
| function | Yes | Name function |
|
59
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
60
|
+
| params | Yes | Allows you to set parameters |
|
61
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
62
|
+
| foo | Yes | Variable name |
|
63
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
64
|
+
| api_keys | Yes | Api password to query |
|
65
|
+
+--------------+----------+-----------+-------------------------------------------------------+
|
66
|
+
|
67
|
+
Return the list of arbitrary days
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
"""
|
73
|
+
|
74
|
+
def __init__(
|
75
|
+
self,
|
76
|
+
loop: asyncio.AbstractEventLoop = None,
|
77
|
+
job: Callable = None,
|
78
|
+
stat: Callable = None,
|
79
|
+
**kwargs,
|
80
|
+
):
|
81
|
+
"""Init Method."""
|
82
|
+
self._fn: Union[Callable, Awaitable] = None
|
83
|
+
self.data = None
|
84
|
+
self.params = None
|
85
|
+
self.function: Callable = None
|
86
|
+
self._kwargs = kwargs.get('args', {})
|
87
|
+
super(UserFunc, self).__init__(loop=loop, job=job, stat=stat, **kwargs)
|
88
|
+
|
89
|
+
async def start(self, **kwargs):
|
90
|
+
"""Obtain Previous data."""
|
91
|
+
if self.previous:
|
92
|
+
self.data = self.input
|
93
|
+
try:
|
94
|
+
self._fn = getFunction(self._program, self.function)
|
95
|
+
except ComponentError as err:
|
96
|
+
raise ComponentError(
|
97
|
+
f"UserFunc: Error getting Function from {self.function}"
|
98
|
+
) from err
|
99
|
+
|
100
|
+
async def close(self):
|
101
|
+
"""Close Method."""
|
102
|
+
|
103
|
+
async def run(self):
|
104
|
+
"""Run Method."""
|
105
|
+
self._result = None
|
106
|
+
params = {"data": self.data, "variables": self._variables, **self._kwargs}
|
107
|
+
if self.params:
|
108
|
+
params = {**params, **self.params}
|
109
|
+
try:
|
110
|
+
if asyncio.iscoroutinefunction(self._fn):
|
111
|
+
result = await self._fn(
|
112
|
+
self, loop=self._loop, env=self._environment, **params
|
113
|
+
)
|
114
|
+
else:
|
115
|
+
result = self._fn(
|
116
|
+
self, loop=self._loop, env=self._environment, **params
|
117
|
+
)
|
118
|
+
self._result = result
|
119
|
+
self.add_metric("UDF", f"{self._fn!s}")
|
120
|
+
return self._result
|
121
|
+
except ComponentError as err:
|
122
|
+
raise ComponentError(f"UserFunc: Error calling {self._fn}: {err}") from err
|