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,37 @@
|
|
1
|
+
from .abstract import AbstractAction
|
2
|
+
|
3
|
+
class ProcessData(AbstractAction):
|
4
|
+
"""ProcessData.
|
5
|
+
Process data received in a webhook event.
|
6
|
+
"""
|
7
|
+
def __init__(self, *args, **kwargs):
|
8
|
+
super().__init__(*args, **kwargs)
|
9
|
+
self.params = kwargs
|
10
|
+
|
11
|
+
async def open(self):
|
12
|
+
pass
|
13
|
+
|
14
|
+
async def close(self):
|
15
|
+
pass
|
16
|
+
|
17
|
+
async def run(self, hook, *args, **kwargs):
|
18
|
+
"""
|
19
|
+
Sample Action for Processing uploaded files.
|
20
|
+
"""
|
21
|
+
uploaded_files = kwargs.get('uploaded_files', [])
|
22
|
+
form_data = kwargs.get('form_data', {})
|
23
|
+
notification = kwargs.get('notification', None)
|
24
|
+
if notification:
|
25
|
+
self._logger.notice(f"Notification: {notification}")
|
26
|
+
self._logger.info(
|
27
|
+
f"Processing notification from channel '{notification.channel}': {notification.payload}"
|
28
|
+
)
|
29
|
+
# Process each uploaded file
|
30
|
+
results = []
|
31
|
+
for file_path in uploaded_files:
|
32
|
+
# Open and process the file
|
33
|
+
with open(file_path, 'r') as f:
|
34
|
+
content = f.read()
|
35
|
+
# Do something with the content
|
36
|
+
results.append({'file': file_path, 'content_length': len(content)})
|
37
|
+
return {'results': results, 'form_data': form_data}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from .abstract import AbstractAction
|
2
|
+
from ...utils import cPrint
|
3
|
+
|
4
|
+
class ProcessSensorData(AbstractAction):
|
5
|
+
"""ProcessSensorData.
|
6
|
+
|
7
|
+
WIP example of to process Sensor data from MQTTT service.
|
8
|
+
"""
|
9
|
+
|
10
|
+
async def open(self):
|
11
|
+
cPrint('Opening Action on Process.')
|
12
|
+
|
13
|
+
async def run(self, hook, *args, **kwargs):
|
14
|
+
print(
|
15
|
+
f"Running action from hook {hook} with arguments:",
|
16
|
+
args,
|
17
|
+
self._args,
|
18
|
+
kwargs,
|
19
|
+
self._kwargs
|
20
|
+
)
|
21
|
+
|
22
|
+
async def close(self):
|
23
|
+
cPrint("Closing Action on Process.")
|
@@ -0,0 +1,37 @@
|
|
1
|
+
from abc import abstractmethod
|
2
|
+
from collections.abc import Callable
|
3
|
+
from .abstract import AbstractAction
|
4
|
+
|
5
|
+
|
6
|
+
class AbstractTicket(AbstractAction):
|
7
|
+
"""AbstractTicket.
|
8
|
+
|
9
|
+
Managing Ticket system using Actions.
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, *args, **kwargs):
|
13
|
+
super(AbstractTicket, self).__init__(*args, **kwargs)
|
14
|
+
self.service: Callable = None
|
15
|
+
try:
|
16
|
+
self._action_ = self._kwargs["action"]
|
17
|
+
del self._kwargs["action"]
|
18
|
+
except KeyError:
|
19
|
+
self._action_ = "create"
|
20
|
+
|
21
|
+
@abstractmethod
|
22
|
+
async def create(self, *args, **kwargs):
|
23
|
+
"""create.
|
24
|
+
|
25
|
+
Create a new Ticket.
|
26
|
+
"""
|
27
|
+
|
28
|
+
async def run(self, hook, *args, **kwargs):
|
29
|
+
if not self.service:
|
30
|
+
await self.open()
|
31
|
+
try:
|
32
|
+
if self._action_ == "create":
|
33
|
+
params = {**self._kwargs, **kwargs}
|
34
|
+
return await self.create(*self._args, **params)
|
35
|
+
except Exception as exc:
|
36
|
+
self._logger.error(f"Error creating new Ticket: {exc}")
|
37
|
+
raise
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from ...conf import (
|
2
|
+
ZAMMAD_INSTANCE,
|
3
|
+
ZAMMAD_TOKEN,
|
4
|
+
ZAMMAD_DEFAULT_CUSTOMER,
|
5
|
+
ZAMMAD_DEFAULT_GROUP,
|
6
|
+
)
|
7
|
+
from ...exceptions import ActionError
|
8
|
+
from .ticket import AbstractTicket
|
9
|
+
from .rest import AbstractREST
|
10
|
+
|
11
|
+
|
12
|
+
class Zammad(AbstractTicket, AbstractREST):
|
13
|
+
"""Zammad.
|
14
|
+
|
15
|
+
Managing Tickets using Zammad.
|
16
|
+
"""
|
17
|
+
|
18
|
+
auth_type = "apikey"
|
19
|
+
token_type = "Bearer"
|
20
|
+
article_base = {"type": "note", "internal": False}
|
21
|
+
data_format: str = "raw"
|
22
|
+
|
23
|
+
def __init__(self, *args, **kwargs):
|
24
|
+
super(Zammad, self).__init__(*args, **kwargs)
|
25
|
+
self.auth = {"apikey": ZAMMAD_TOKEN}
|
26
|
+
|
27
|
+
async def close(self):
|
28
|
+
pass
|
29
|
+
|
30
|
+
async def open(self):
|
31
|
+
pass
|
32
|
+
|
33
|
+
async def create(self, hook, *args, **kwargs):
|
34
|
+
"""create.
|
35
|
+
|
36
|
+
Create a new Ticket.
|
37
|
+
"""
|
38
|
+
self.url = f"{ZAMMAD_INSTANCE}api/v1/tickets"
|
39
|
+
self.method = "post"
|
40
|
+
group = kwargs.pop("group", ZAMMAD_DEFAULT_GROUP)
|
41
|
+
title = kwargs.pop("title", None)
|
42
|
+
customer = kwargs.pop("customer", ZAMMAD_DEFAULT_CUSTOMER)
|
43
|
+
article = kwargs.pop("article")
|
44
|
+
article = {**self.article_base, **article}
|
45
|
+
data = {
|
46
|
+
"title": title,
|
47
|
+
"group": group,
|
48
|
+
"customer": customer,
|
49
|
+
"article": article,
|
50
|
+
}
|
51
|
+
try:
|
52
|
+
result, _ = await self.request(self.url, self.method, data=data)
|
53
|
+
return result
|
54
|
+
except Exception as e:
|
55
|
+
raise ActionError(f"Error creating Zammad Ticket: {e}") from e
|
flowtask/hooks/hook.py
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
from uuid import uuid4
|
2
|
+
from navconfig.logging import logging
|
3
|
+
from ..exceptions import ConfigError
|
4
|
+
from .step import StepAction, import_component
|
5
|
+
|
6
|
+
|
7
|
+
class Hook:
|
8
|
+
"""Hook.
|
9
|
+
|
10
|
+
Compile a Hook (Triggers and Actions) and got every step on the hook.
|
11
|
+
"""
|
12
|
+
|
13
|
+
def __init__(self, hook: dict):
|
14
|
+
self.triggers: list = []
|
15
|
+
self.logger = logging.getLogger(name='Flowtask.Hook')
|
16
|
+
self._id = hook.pop("id", uuid4())
|
17
|
+
self.name = hook.pop("name")
|
18
|
+
try:
|
19
|
+
triggers = hook["When"]
|
20
|
+
except KeyError as exc:
|
21
|
+
raise ConfigError(
|
22
|
+
"Hook Error: Unable to find Trigger: *When* parameter"
|
23
|
+
) from exc
|
24
|
+
try:
|
25
|
+
actions = hook["Then"]
|
26
|
+
except KeyError as exc:
|
27
|
+
raise ConfigError(
|
28
|
+
"Hook Error: Unable to get list of Actions: *Then* parameter"
|
29
|
+
) from exc
|
30
|
+
## build Hook Component:
|
31
|
+
self.build(triggers, actions)
|
32
|
+
|
33
|
+
def build(self, triggers: list, actions: list):
|
34
|
+
self._actions: list = []
|
35
|
+
# "Then": Load Actions
|
36
|
+
for step in actions:
|
37
|
+
for step_name, params in step.items():
|
38
|
+
action = StepAction(step_name, params)
|
39
|
+
self._actions.append(action)
|
40
|
+
for step in triggers:
|
41
|
+
# When: Load Triggers
|
42
|
+
# Triggers are listener for events.
|
43
|
+
for step_name, params in step.items():
|
44
|
+
trigger_cls = import_component(step_name, "flowtask.hooks.types", "types")
|
45
|
+
if trigger_cls:
|
46
|
+
# start trigger:
|
47
|
+
args = {"name": self.name, "actions": self._actions}
|
48
|
+
args = {**args, **params}
|
49
|
+
try:
|
50
|
+
hook = trigger_cls(**args)
|
51
|
+
self.triggers.append(hook)
|
52
|
+
self.logger.debug(
|
53
|
+
f":: Loading Hook {self.name}"
|
54
|
+
)
|
55
|
+
except Exception as exc:
|
56
|
+
self.logger.error(
|
57
|
+
f"Unable to load Trigger {step_name}: {exc}"
|
58
|
+
)
|
59
|
+
else:
|
60
|
+
self.logger.warning(
|
61
|
+
f"Unable to load Trigger: {step_name}"
|
62
|
+
)
|
flowtask/hooks/models.py
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from dataclasses import InitVar
|
3
|
+
from datamodel import Field
|
4
|
+
from asyncdb.models import Model
|
5
|
+
from uuid import UUID, uuid4
|
6
|
+
|
7
|
+
class HookObject(Model):
|
8
|
+
trigger_id: UUID = Field(required=True, primary_key=True, default=uuid4, db_default="auto")
|
9
|
+
name: str = Field(required=True)
|
10
|
+
definition: dict = Field(required=True)
|
11
|
+
created_by: int = Field(required=False)
|
12
|
+
created_at: datetime = Field(required=False, default=datetime.now())
|
13
|
+
|
14
|
+
class Meta:
|
15
|
+
name: str = "triggers"
|
16
|
+
schema: str = "navigator"
|
17
|
+
strict: bool = False
|
@@ -0,0 +1,187 @@
|
|
1
|
+
"""
|
2
|
+
Hook Management.
|
3
|
+
|
4
|
+
This module is responsible for handling the Hooks in Flowtask.
|
5
|
+
"""
|
6
|
+
import asyncio
|
7
|
+
from navconfig.logging import logging
|
8
|
+
from asyncdb import AsyncDB
|
9
|
+
from navigator.types import WebApp
|
10
|
+
from navigator.applications.base import BaseApplication
|
11
|
+
from navigator.views import ModelView
|
12
|
+
from ..exceptions import ConfigError, FlowTaskError
|
13
|
+
from ..conf import TASK_STORAGES, default_dsn
|
14
|
+
from .types.base import BaseTrigger
|
15
|
+
from .hook import Hook
|
16
|
+
from .models import HookObject
|
17
|
+
|
18
|
+
|
19
|
+
class HookHandler(ModelView):
|
20
|
+
model = HookObject
|
21
|
+
name = "Navigator Triggers"
|
22
|
+
pk: str = "trigger_id"
|
23
|
+
|
24
|
+
async def _set_created_by(self, value, column, data):
|
25
|
+
return await self.get_userid(session=self._session)
|
26
|
+
|
27
|
+
@ModelView.service_auth
|
28
|
+
async def _post_data(self, *args, **kwargs):
|
29
|
+
payload = await super()._post_data(*args, **kwargs)
|
30
|
+
if not payload:
|
31
|
+
raise ConfigError("Trigger: No payload provided.")
|
32
|
+
payload['definition'] = payload.copy()
|
33
|
+
# then, remove the components
|
34
|
+
del payload['When']
|
35
|
+
del payload['Then']
|
36
|
+
# and renamed "id" to "trigger_id":
|
37
|
+
payload['trigger_id'] = payload.pop('id')
|
38
|
+
return payload
|
39
|
+
|
40
|
+
@ModelView.service_auth
|
41
|
+
async def _post_response(
|
42
|
+
self,
|
43
|
+
response,
|
44
|
+
fields: list = None,
|
45
|
+
headers: dict = None,
|
46
|
+
status: int = 200
|
47
|
+
):
|
48
|
+
if status == 201:
|
49
|
+
# Hook was correctly created.
|
50
|
+
# TODO: remove the previous when edited.
|
51
|
+
try:
|
52
|
+
hookservice = self.request.app['HookService']
|
53
|
+
hook = Hook(hook=response.definition)
|
54
|
+
for trigger in hook.triggers:
|
55
|
+
tg = trigger()
|
56
|
+
print('TG > ', tg)
|
57
|
+
hookservice.add_hook(tg)
|
58
|
+
await tg.start()
|
59
|
+
message = f"Hook {response.trigger_id} added successfully."
|
60
|
+
self.logger.info(
|
61
|
+
message
|
62
|
+
)
|
63
|
+
response.status = message
|
64
|
+
except Exception as exc:
|
65
|
+
self.logger.error(
|
66
|
+
f"Error adding hook: {exc}"
|
67
|
+
)
|
68
|
+
return self.json_response(
|
69
|
+
response=response,
|
70
|
+
status=status
|
71
|
+
)
|
72
|
+
|
73
|
+
class HookService:
|
74
|
+
def __init__(self, event_loop: asyncio.AbstractEventLoop, app: BaseApplication, **kwargs):
|
75
|
+
self._loop = event_loop
|
76
|
+
self._hooks: list = []
|
77
|
+
self._started: bool = False
|
78
|
+
self.logger = logging.getLogger(name="Flowtask.HookService")
|
79
|
+
self.app: WebApp = None
|
80
|
+
# TaskStorage
|
81
|
+
self._storage = kwargs.pop("storage", "default")
|
82
|
+
# App
|
83
|
+
if isinstance(app, BaseApplication): # migrate to BaseApplication (on types)
|
84
|
+
self.app = app.get_app()
|
85
|
+
elif isinstance(app, WebApp):
|
86
|
+
self.app = app # register the app into the Extension
|
87
|
+
else:
|
88
|
+
raise TypeError(
|
89
|
+
f"Invalid type for Application Setup: {app}:{type(app)}"
|
90
|
+
)
|
91
|
+
try:
|
92
|
+
self.taskstore = TASK_STORAGES[self._storage]
|
93
|
+
except KeyError as exc:
|
94
|
+
raise RuntimeError(
|
95
|
+
f"Invalid Task Storage > {self._storage}"
|
96
|
+
) from exc
|
97
|
+
if not self.taskstore.path:
|
98
|
+
raise ConfigError(
|
99
|
+
f"Current Task Storage {self.taskstore!r} is not Supported for saving Triggers/Hooks."
|
100
|
+
)
|
101
|
+
|
102
|
+
def add_hook(self, hook: BaseTrigger):
|
103
|
+
"""
|
104
|
+
Add the Hook, start it and calling the Setup.
|
105
|
+
"""
|
106
|
+
self._hooks.append(hook)
|
107
|
+
hook.setup(app=self.app)
|
108
|
+
|
109
|
+
add_trigger = add_hook
|
110
|
+
|
111
|
+
async def setup(self) -> None:
|
112
|
+
"""setup.
|
113
|
+
|
114
|
+
Service Configuration.
|
115
|
+
Args:
|
116
|
+
app (aiohttp.web.Application): Web Application.
|
117
|
+
"""
|
118
|
+
self.app['HookService'] = self
|
119
|
+
# Start all hooks, and register the endpoint.
|
120
|
+
await self.start_hooks(self.app)
|
121
|
+
# register endpoint to add Triggers to HookService.
|
122
|
+
HookHandler.configure(
|
123
|
+
self.app,
|
124
|
+
path='/api/v1/triggers/'
|
125
|
+
)
|
126
|
+
self.logger.notice('Hook Service Started.')
|
127
|
+
|
128
|
+
async def start_hooks(self, app: WebApp) -> None:
|
129
|
+
"""start_hooks.
|
130
|
+
|
131
|
+
Starts the Hook Service.
|
132
|
+
"""
|
133
|
+
# First: loading the File-based Hooks
|
134
|
+
await self.load_fs_hooks()
|
135
|
+
# Second: loading the Database Hooks
|
136
|
+
await self.load_db_hooks()
|
137
|
+
# mark service as started.
|
138
|
+
self._started = True
|
139
|
+
|
140
|
+
async def load_fs_hooks(self) -> None:
|
141
|
+
"""load_fs_hooks.
|
142
|
+
|
143
|
+
Load all Hooks from the Task Storage (Filesystem).
|
144
|
+
"""
|
145
|
+
self.logger.notice(":: Loading Hooks from Filesystem.")
|
146
|
+
for program_dir in self.taskstore.path.iterdir():
|
147
|
+
if program_dir.is_dir():
|
148
|
+
hooks_dir = program_dir.joinpath("hooks.d")
|
149
|
+
for file_path in hooks_dir.rglob("*.*"):
|
150
|
+
# only work with supported extensions:
|
151
|
+
if file_path.suffix in ('.json', '.yaml', '.yml'):
|
152
|
+
try:
|
153
|
+
store = await self.taskstore.open_hook(file_path)
|
154
|
+
except Exception as exc:
|
155
|
+
self.logger.warning(
|
156
|
+
f"Unable to load Hook {file_path!r}: Invalid Hook File, {exc}"
|
157
|
+
)
|
158
|
+
continue
|
159
|
+
try:
|
160
|
+
hook = Hook(hook=store)
|
161
|
+
if hook:
|
162
|
+
for trigger in hook.triggers:
|
163
|
+
self.add_hook(trigger)
|
164
|
+
except FlowTaskError:
|
165
|
+
pass
|
166
|
+
|
167
|
+
async def load_db_hooks(self) -> None:
|
168
|
+
"""load_db_hooks.
|
169
|
+
|
170
|
+
Load all Hooks saved into the Database.
|
171
|
+
"""
|
172
|
+
db = AsyncDB('pg', dsn=default_dsn)
|
173
|
+
async with await db.connection() as conn:
|
174
|
+
HookObject.Meta.connection = conn
|
175
|
+
hooks = await HookObject.all()
|
176
|
+
for hook in hooks:
|
177
|
+
definition = hook.definition
|
178
|
+
try:
|
179
|
+
hook = Hook(hook=definition)
|
180
|
+
for trigger in hook.triggers:
|
181
|
+
self.add_hook(trigger)
|
182
|
+
except FlowTaskError:
|
183
|
+
pass
|
184
|
+
except Exception as exc:
|
185
|
+
self.logger.error(
|
186
|
+
f"Error Loading Database Hooks: {exc}"
|
187
|
+
)
|
flowtask/hooks/step.py
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
from typing import Union, Any
|
2
|
+
from collections.abc import Callable, Awaitable
|
3
|
+
import importlib
|
4
|
+
from navconfig.logging import logging
|
5
|
+
from ..exceptions import ConfigError, FlowTaskError, ComponentError, NotSupported
|
6
|
+
from ..components import getComponent, importComponent
|
7
|
+
from ..components.abstract import AbstractFlow
|
8
|
+
from .actions.abstract import AbstractAction
|
9
|
+
|
10
|
+
|
11
|
+
_ACTIONS: dict[str, Any] = {}
|
12
|
+
|
13
|
+
|
14
|
+
def import_component(component: str, classpath: str, package: str = "components"):
|
15
|
+
module = importlib.import_module(classpath, package=package)
|
16
|
+
# module = importlib.import_module(f".{name.lower()}", package=module_path)
|
17
|
+
obj = getattr(module, component, None)
|
18
|
+
return obj
|
19
|
+
|
20
|
+
|
21
|
+
class StepAction:
|
22
|
+
def __init__(self, action: str, params: dict, **kwargs) -> None:
|
23
|
+
self.name = action
|
24
|
+
self._step: Union[Callable, Awaitable] = None
|
25
|
+
try:
|
26
|
+
# Check if the action is already loaded
|
27
|
+
if hasattr(self, "_action"):
|
28
|
+
return
|
29
|
+
# Check if the action is a function or a class
|
30
|
+
action_cls = None
|
31
|
+
if callable(action):
|
32
|
+
self._action = action
|
33
|
+
elif _ACTIONS.get(action):
|
34
|
+
action_cls = _ACTIONS[action]
|
35
|
+
else:
|
36
|
+
# Load the action from the components module
|
37
|
+
try:
|
38
|
+
action_cls = importComponent(action)
|
39
|
+
except (NotSupported, ImportError):
|
40
|
+
pass
|
41
|
+
if not action_cls:
|
42
|
+
# Load the action from the actions module
|
43
|
+
action_cls: AbstractAction = import_component(
|
44
|
+
action,
|
45
|
+
"flowtask.hooks.actions",
|
46
|
+
"actions"
|
47
|
+
)
|
48
|
+
if not action_cls:
|
49
|
+
raise ConfigError(
|
50
|
+
f"Unable to load Action: {action}"
|
51
|
+
)
|
52
|
+
args = {**kwargs, **params}
|
53
|
+
self._action = action_cls(**args)
|
54
|
+
# saving into _ACTIONS variable
|
55
|
+
_ACTIONS[action] = action_cls
|
56
|
+
except (ImportError, RuntimeError) as exc:
|
57
|
+
raise FlowTaskError(
|
58
|
+
f"Unable to load Action {action}: {exc}"
|
59
|
+
) from exc
|
60
|
+
self.params = args
|
61
|
+
|
62
|
+
def __repr__(self) -> str:
|
63
|
+
return f"<StepAction.{self.name}: {self.params!r}>"
|
64
|
+
|
65
|
+
@property
|
66
|
+
def component(self):
|
67
|
+
return self._action
|
68
|
+
|
69
|
+
async def run(self, hook, *args, **kwargs):
|
70
|
+
"""Run action involved"""
|
71
|
+
try:
|
72
|
+
try:
|
73
|
+
async with self._action as step:
|
74
|
+
# Check if Step is a AbstractFlow to set the "self.data" property
|
75
|
+
if isinstance(step, AbstractFlow):
|
76
|
+
# Passing all arguments to the Flowtask component
|
77
|
+
step.data = kwargs
|
78
|
+
step.result = kwargs.get('result')
|
79
|
+
result = await step.run()
|
80
|
+
else:
|
81
|
+
result = await step.run(hook, *args, **kwargs)
|
82
|
+
return result
|
83
|
+
except Exception as exc:
|
84
|
+
logging.error(
|
85
|
+
f"Error running action {self._action!s}: {exc}"
|
86
|
+
)
|
87
|
+
except Exception as exc:
|
88
|
+
logging.error(
|
89
|
+
f"Unable to load Action {self._action}: {exc}"
|
90
|
+
)
|
91
|
+
raise
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"""
|
2
|
+
Hook Types.
|
3
|
+
|
4
|
+
Hook Types are triggers that can be executed when an event is triggered.
|
5
|
+
|
6
|
+
1. FSWatchdog: Watches a specified directory for changes.
|
7
|
+
"""
|
8
|
+
from .fs import FSWatchdog
|
9
|
+
from .web import WebHook
|
10
|
+
from .imap import IMAPWatchdog
|
11
|
+
from .tagged import TaggedIMAPWatchdog
|
12
|
+
from .ssh import SFTPWatchdog
|
13
|
+
from .upload import UploadHook
|
14
|
+
from .postgres import PostgresTrigger
|
15
|
+
from .http import HTTPHook
|
16
|
+
from .sharepoint import SharePointTrigger
|
17
|
+
from .mail import EmailTrigger
|
18
|
+
from .jira import JiraTrigger
|
19
|
+
# Message Brokers:
|
20
|
+
from .brokers.mqtt import MQTTTrigger
|
21
|
+
from .brokers.sqs import SQSTrigger
|
22
|
+
from .brokers.redis import RedisTrigger
|
23
|
+
from .brokers.rabbitmq import RabbitMQTrigger
|
@@ -0,0 +1,129 @@
|
|
1
|
+
import os
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from typing import Optional
|
4
|
+
from collections.abc import Callable
|
5
|
+
import asyncio
|
6
|
+
import uuid
|
7
|
+
from concurrent.futures import ThreadPoolExecutor
|
8
|
+
from navconfig import config
|
9
|
+
from navconfig.logging import logging
|
10
|
+
from navigator.types import WebApp
|
11
|
+
from .responses import TriggerResponse
|
12
|
+
from ..actions import AbstractAction
|
13
|
+
from ...interfaces import (
|
14
|
+
MaskSupport,
|
15
|
+
LocaleSupport,
|
16
|
+
LogSupport
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
class BaseTrigger(MaskSupport, LogSupport, LocaleSupport, ABC):
|
21
|
+
"""BaseTrigger.
|
22
|
+
|
23
|
+
Base class for all Triggers in FlowTask.
|
24
|
+
"""
|
25
|
+
# Signal for startup/shutdown method for this Hook (using aiohttp signals)
|
26
|
+
on_startup: Optional[Callable] = None
|
27
|
+
on_shutdown: Optional[Callable] = None
|
28
|
+
|
29
|
+
def __init__(self, *args, actions: list = None, **kwargs):
|
30
|
+
self.trigger_id = kwargs.get("id", uuid.uuid4())
|
31
|
+
super().__init__(*args, **kwargs)
|
32
|
+
self._name_ = self.__class__.__name__
|
33
|
+
self.description = kwargs.pop('description', self._name_)
|
34
|
+
self._args = args
|
35
|
+
self._kwargs = kwargs
|
36
|
+
self.app: WebApp = None
|
37
|
+
self._logger = logging.getLogger(
|
38
|
+
f"Trigger.{self._name_}"
|
39
|
+
)
|
40
|
+
self._response: TriggerResponse = None
|
41
|
+
self._environment = config
|
42
|
+
self._actions: list[AbstractAction] = actions
|
43
|
+
for key, val in kwargs.items():
|
44
|
+
setattr(self, key, val)
|
45
|
+
|
46
|
+
def setup(self, app: WebApp) -> None:
|
47
|
+
"""setup.
|
48
|
+
|
49
|
+
Configuration of Trigger when started.
|
50
|
+
Args:
|
51
|
+
app (aiohttp.web.Application): Web Application.
|
52
|
+
"""
|
53
|
+
self.app = app # register the app into the Extension
|
54
|
+
# startup operations over extension backend
|
55
|
+
try:
|
56
|
+
# avoid Cannot modify frozen list
|
57
|
+
if callable(self.on_startup):
|
58
|
+
app.on_startup.append(self.on_startup)
|
59
|
+
|
60
|
+
if callable(self.on_shutdown):
|
61
|
+
app.on_shutdown.append(self.on_shutdown)
|
62
|
+
except Exception as e:
|
63
|
+
self._logger.warning(
|
64
|
+
f"Error setting up Trigger {self.__class__.__name__}: {e}"
|
65
|
+
)
|
66
|
+
return False
|
67
|
+
|
68
|
+
def get_env_value(self, key, default: str = None):
|
69
|
+
if val := os.getenv(key):
|
70
|
+
return val
|
71
|
+
elif val := self._environment.get(key, default):
|
72
|
+
return val
|
73
|
+
else:
|
74
|
+
return key
|
75
|
+
|
76
|
+
def add_action(self, action: AbstractAction):
|
77
|
+
self._actions.append(action)
|
78
|
+
|
79
|
+
def get_actions(self) -> list:
|
80
|
+
return self._actions
|
81
|
+
|
82
|
+
async def run_actions(self, *args, **kwargs):
|
83
|
+
result = None
|
84
|
+
if self._actions:
|
85
|
+
for action in self._actions:
|
86
|
+
self._logger.notice(
|
87
|
+
f"Calling Action: {action}"
|
88
|
+
)
|
89
|
+
try:
|
90
|
+
result = await action.run(
|
91
|
+
hook=self,
|
92
|
+
result=result,
|
93
|
+
*args,
|
94
|
+
**kwargs
|
95
|
+
)
|
96
|
+
except Exception as e:
|
97
|
+
# Handle any exceptions that might occur during action.run()
|
98
|
+
self._logger.error(
|
99
|
+
f"Error while running {action}: {e}"
|
100
|
+
)
|
101
|
+
return result
|
102
|
+
else:
|
103
|
+
self._logger.warning(
|
104
|
+
f"Trigger {self.__class__.__name__}: No actions were found to be executed."
|
105
|
+
)
|
106
|
+
|
107
|
+
def call_actions(self, *args, **kwargs):
|
108
|
+
# Run the actions in a thread pool
|
109
|
+
_new = False
|
110
|
+
try:
|
111
|
+
loop = asyncio.get_event_loop()
|
112
|
+
_new = False
|
113
|
+
except RuntimeError:
|
114
|
+
loop = asyncio.new_event_loop()
|
115
|
+
_new = True
|
116
|
+
try:
|
117
|
+
with ThreadPoolExecutor() as executor:
|
118
|
+
future = executor.submit(
|
119
|
+
loop.run_until_complete, self.run_actions(*args, **kwargs)
|
120
|
+
)
|
121
|
+
future.result()
|
122
|
+
except Exception as exc:
|
123
|
+
self._logger.error(f"Error Calling Action: {exc}")
|
124
|
+
finally:
|
125
|
+
if _new is True:
|
126
|
+
try:
|
127
|
+
loop.close()
|
128
|
+
except RuntimeError:
|
129
|
+
pass
|