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
flowtask/tasks/task.py
ADDED
@@ -0,0 +1,778 @@
|
|
1
|
+
import asyncio
|
2
|
+
import traceback
|
3
|
+
from typing import Any, Optional
|
4
|
+
from collections.abc import Callable
|
5
|
+
from asyncdb.exceptions import NoDataFound, ProviderError
|
6
|
+
# Flowtask Core:
|
7
|
+
from ..interfaces.log import SkipErrors
|
8
|
+
from ..utils.stats import StepMonitor
|
9
|
+
from ..models import TaskState, setTaskState
|
10
|
+
from ..exceptions import (
|
11
|
+
TaskFailed,
|
12
|
+
TaskDefinition,
|
13
|
+
TaskError,
|
14
|
+
TaskParseError,
|
15
|
+
TaskNotFound,
|
16
|
+
NotSupported,
|
17
|
+
ComponentError,
|
18
|
+
DataNotFound,
|
19
|
+
FileNotFound,
|
20
|
+
FileError,
|
21
|
+
DataError,
|
22
|
+
EmptyFile,
|
23
|
+
)
|
24
|
+
from ..tasks.pile import TaskPile
|
25
|
+
from ..utils import cPrint, check_empty, AttrDict
|
26
|
+
from .abstract import AbstractTask
|
27
|
+
from ..events import NotifyEvent, LogError
|
28
|
+
from ..events.events.exec import LogExecution, SaveExecution
|
29
|
+
from ..bots import CodeReview, ENABLE_BOT_REVIEWER
|
30
|
+
|
31
|
+
|
32
|
+
class Task(AbstractTask):
|
33
|
+
"""
|
34
|
+
Task.
|
35
|
+
|
36
|
+
Object contain a Flow Task.
|
37
|
+
"""
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
task_id: str = None,
|
42
|
+
task: str = None,
|
43
|
+
program: str = None,
|
44
|
+
loop: asyncio.AbstractEventLoop = None,
|
45
|
+
parser: Callable = None,
|
46
|
+
worker: Callable = None,
|
47
|
+
**kwargs,
|
48
|
+
) -> None:
|
49
|
+
self._pile_: TaskPile = None
|
50
|
+
self._steps = None
|
51
|
+
self._vars = None
|
52
|
+
super(Task, self).__init__(
|
53
|
+
task_id=task_id,
|
54
|
+
task=task,
|
55
|
+
program=program,
|
56
|
+
loop=loop,
|
57
|
+
parser=parser,
|
58
|
+
**kwargs,
|
59
|
+
)
|
60
|
+
self._taskname = task
|
61
|
+
self._conditions = {}
|
62
|
+
self._attrs = {}
|
63
|
+
self.ignore_steps = []
|
64
|
+
self.run_only = []
|
65
|
+
self._stepattrs = {}
|
66
|
+
self._kwargs = {}
|
67
|
+
self._masks = {}
|
68
|
+
self._resultset: Any = None
|
69
|
+
self._codereview = None
|
70
|
+
self._task_payload = None
|
71
|
+
if not self._taskname:
|
72
|
+
raise TaskError(
|
73
|
+
'Missing Task Name, \
|
74
|
+
HINT: add --task (in command line) or parameter "task" \
|
75
|
+
with a task name'
|
76
|
+
)
|
77
|
+
# change root-level attributes on fly
|
78
|
+
if parser:
|
79
|
+
self._attrs = parser.attributes
|
80
|
+
attrs = kwargs.pop('attributes', {})
|
81
|
+
self._attrs = {**self._attrs, **attrs}
|
82
|
+
# disable Events:
|
83
|
+
self._no_events: bool = kwargs.pop("no_events", False)
|
84
|
+
self.logger.notice(
|
85
|
+
f"Disabled Events: {self._no_events}"
|
86
|
+
)
|
87
|
+
# for component-based attributes (ex: --DownloadFromIMAP_1:host)
|
88
|
+
if parser:
|
89
|
+
self._stepattrs = parser.stepattrs
|
90
|
+
# Steps:
|
91
|
+
steps = kwargs.pop('steps', {})
|
92
|
+
if steps:
|
93
|
+
self._stepattrs = {**self._stepattrs, **steps}
|
94
|
+
# Is a Subtask?
|
95
|
+
self.is_subtask: bool = kwargs.pop('is_subtask', False)
|
96
|
+
# override attributes:
|
97
|
+
self._override_attributes = kwargs.pop("override_attributes", False)
|
98
|
+
self.ignore_steps = kwargs.pop('ignore_steps', [])
|
99
|
+
self.run_only = kwargs.pop('run_only', [])
|
100
|
+
if parser:
|
101
|
+
self._override_attributes = self._options.override_attributes
|
102
|
+
# ignoring components in task execution.
|
103
|
+
self.ignore_steps = self._options.ignore
|
104
|
+
# list of "run only" components:
|
105
|
+
self.run_only = self._options.run_only
|
106
|
+
# variables: can be passed between components as reusable values.
|
107
|
+
if parser:
|
108
|
+
self._variables = self._options.variables
|
109
|
+
# parsing variables:
|
110
|
+
variables = kwargs.pop('variables', {})
|
111
|
+
if isinstance(variables, dict):
|
112
|
+
self._variables = {**self._variables, **variables}
|
113
|
+
self.logger.debug(
|
114
|
+
f"CURRENTLY NEW Variables: {self._variables}"
|
115
|
+
)
|
116
|
+
# masks: replacing masks with values or even new functions
|
117
|
+
if parser:
|
118
|
+
self._masks = self._options.masks
|
119
|
+
self._conditions = self._options.conditions
|
120
|
+
self._args = self._options.args
|
121
|
+
try:
|
122
|
+
conditions = kwargs["conditions"]
|
123
|
+
except KeyError:
|
124
|
+
conditions = {}
|
125
|
+
self._conditions = {**self._conditions, **conditions}
|
126
|
+
self.logger.debug(
|
127
|
+
f"CURRENTLY NEW CONDS: {self._conditions}"
|
128
|
+
)
|
129
|
+
self.worker = worker
|
130
|
+
if kwargs:
|
131
|
+
# remain args go to kwargs:
|
132
|
+
self._kwargs = {**kwargs}
|
133
|
+
# add also the Log execution for InfluxDB
|
134
|
+
self.event_defaults(
|
135
|
+
LogExecution(disable_notification=self._no_notify)
|
136
|
+
)
|
137
|
+
## set the Task State:
|
138
|
+
running = getattr(self._events, "running")
|
139
|
+
running.add(setTaskState)
|
140
|
+
completed = getattr(self._events, "completed")
|
141
|
+
completed.add(setTaskState)
|
142
|
+
# Special Events:
|
143
|
+
self._events.exception += NotifyEvent(event="exception")
|
144
|
+
self._events.data_not_found += NotifyEvent(event="warning")
|
145
|
+
self._events.data_error += NotifyEvent(event="error")
|
146
|
+
self._events.file_not_found += NotifyEvent(event="error")
|
147
|
+
self._events.file_empty += NotifyEvent(event="error")
|
148
|
+
# Internal On Finished Events:
|
149
|
+
self._events.done += NotifyEvent(event="done")
|
150
|
+
self._events.on_error += NotifyEvent(event="error")
|
151
|
+
self._events.completed += SaveExecution(disable_notification=self._no_notify)
|
152
|
+
# and Log for Errors:
|
153
|
+
logerr = LogError()
|
154
|
+
self._events.file_not_found += logerr
|
155
|
+
self._events.data_not_found += logerr
|
156
|
+
self._events.exception += logerr
|
157
|
+
# Code Review on Errors or Exceptions:
|
158
|
+
if ENABLE_BOT_REVIEWER is True:
|
159
|
+
self._codereview = CodeReview(task=self)
|
160
|
+
self._events.exception += self._codereview
|
161
|
+
self._events.on_error += self._codereview
|
162
|
+
|
163
|
+
async def close(self):
|
164
|
+
"""close.
|
165
|
+
|
166
|
+
Closing the remaining connections.
|
167
|
+
"""
|
168
|
+
if self.is_subtask is False:
|
169
|
+
await super(Task, self).close()
|
170
|
+
self._pile_ = None
|
171
|
+
self._steps = None
|
172
|
+
self._args = None
|
173
|
+
|
174
|
+
@property
|
175
|
+
def variables(self):
|
176
|
+
return self._vars
|
177
|
+
|
178
|
+
@property
|
179
|
+
def taskname(self):
|
180
|
+
return self._taskname
|
181
|
+
|
182
|
+
def __repr__(self) -> str:
|
183
|
+
return f"{self._program}.{self._taskname}"
|
184
|
+
|
185
|
+
def pile(self):
|
186
|
+
return self._pile_
|
187
|
+
|
188
|
+
async def prepare(self):
|
189
|
+
if self._task_:
|
190
|
+
# calling steps
|
191
|
+
try:
|
192
|
+
self._pile_ = TaskPile(self._task_, program=self._program)
|
193
|
+
except (KeyError, TaskDefinition) as exc:
|
194
|
+
raise TaskDefinition(
|
195
|
+
f"Bad Task Definition: {exc!s}"
|
196
|
+
) from exc
|
197
|
+
except Exception as exc:
|
198
|
+
raise TaskDefinition(
|
199
|
+
f"Task Exception {self._program}.{self._taskname}: {exc!s}"
|
200
|
+
) from exc
|
201
|
+
## Processing Event list:
|
202
|
+
try:
|
203
|
+
self._events.LoadEvents(
|
204
|
+
self._task_.get('events')
|
205
|
+
)
|
206
|
+
except KeyError:
|
207
|
+
pass
|
208
|
+
return True
|
209
|
+
else:
|
210
|
+
raise TaskDefinition(
|
211
|
+
f"Flowtkas: Invalid Task: {self._program}.{self._taskname}"
|
212
|
+
)
|
213
|
+
|
214
|
+
def get_component(self, step, prev):
|
215
|
+
step_name = step.name
|
216
|
+
if self.enable_stat is True:
|
217
|
+
stat = StepMonitor(name=step_name, parent=self.stat)
|
218
|
+
self.stat.add_step(stat)
|
219
|
+
else:
|
220
|
+
stat = None
|
221
|
+
params = step.params()
|
222
|
+
params["program"] = self._program
|
223
|
+
params["ENV"] = self._env
|
224
|
+
# params:
|
225
|
+
params["params"] = self._params
|
226
|
+
# parameters
|
227
|
+
params["parameters"] = self._parameters
|
228
|
+
# useful to change variables in set var components
|
229
|
+
params["_vars"] = self._kwargs
|
230
|
+
# variables dictionary
|
231
|
+
try:
|
232
|
+
variables = params["variables"]
|
233
|
+
except KeyError:
|
234
|
+
variables = {}
|
235
|
+
if prev:
|
236
|
+
variables = {**variables, **prev.variables}
|
237
|
+
params["variables"] = {**self._variables, **variables}
|
238
|
+
params["_masks"] = self._masks # override mask value
|
239
|
+
try:
|
240
|
+
arguments = params["arguments"]
|
241
|
+
except KeyError:
|
242
|
+
arguments = []
|
243
|
+
if not self._arguments:
|
244
|
+
self._arguments = []
|
245
|
+
params["arguments"] = arguments + self._arguments
|
246
|
+
# argument list for components (or tasks) that need argument lists
|
247
|
+
params["_args"] = self._args
|
248
|
+
# for components with conditions, we can add more conditions
|
249
|
+
try:
|
250
|
+
conditions = params["conditions"]
|
251
|
+
except KeyError:
|
252
|
+
conditions = {}
|
253
|
+
params["conditions"] = {**conditions, **self._conditions}
|
254
|
+
# attributes only usable component-only
|
255
|
+
if step_name in self._stepattrs or step_name.startswith('SubTask'):
|
256
|
+
# this can rewrite attributes for steps
|
257
|
+
if self._override_attributes:
|
258
|
+
newattrs = self._stepattrs.get(step_name, {})
|
259
|
+
self._attrs = {**self._attrs, **newattrs}
|
260
|
+
else:
|
261
|
+
self._attrs = {**self._attrs, **self._stepattrs}
|
262
|
+
# will be a dictionary with ComponentName: parameter
|
263
|
+
params["attributes"] = self._attrs
|
264
|
+
# the current Pile of components
|
265
|
+
params["TaskPile"] = self._pile_
|
266
|
+
params["debug"] = self._debug
|
267
|
+
params["argparser"] = self._argparser
|
268
|
+
params["taskstorage"] = self.taskstore
|
269
|
+
component = None
|
270
|
+
component = step.component
|
271
|
+
# get dependency
|
272
|
+
depends = step.getDepends(prev)
|
273
|
+
if "TaskPile" in params["parameters"]:
|
274
|
+
del params["parameters"]["TaskPile"]
|
275
|
+
try:
|
276
|
+
comp = component(
|
277
|
+
job=depends, loop=self._loop, stat=stat, step_name=step_name, **params # stats object
|
278
|
+
)
|
279
|
+
self.logger.debug(f"Task.{self.task_id}: Component {comp}")
|
280
|
+
comp.TaskName = step_name
|
281
|
+
comp.set_filestore(self._filestore)
|
282
|
+
comp.set_taskstore(self.taskstore)
|
283
|
+
return comp
|
284
|
+
except Exception as err:
|
285
|
+
raise ComponentError(
|
286
|
+
f"DI: Component Error on {self._taskname}, \
|
287
|
+
Component: {step_name} error: {err}"
|
288
|
+
) from err
|
289
|
+
|
290
|
+
def resultset(self):
|
291
|
+
return self._resultset
|
292
|
+
|
293
|
+
async def exchange_variables(self, component, result: Any = None):
|
294
|
+
# TODO: saving results on Redis, variables on Memory, etc.
|
295
|
+
self._variables = component.variables
|
296
|
+
self._resultset = result
|
297
|
+
|
298
|
+
def _on_error(self, status: str, exc: BaseException, step_name: str = None):
|
299
|
+
if isinstance(exc, str):
|
300
|
+
error = exc
|
301
|
+
else:
|
302
|
+
error = str(exc)
|
303
|
+
try:
|
304
|
+
self.logger.error(str(exc))
|
305
|
+
self._state = TaskState.ERROR
|
306
|
+
trace = traceback.format_exc()
|
307
|
+
self._events.on_error(
|
308
|
+
message=error,
|
309
|
+
component=self._taskname,
|
310
|
+
task=self,
|
311
|
+
status=status,
|
312
|
+
error=exc,
|
313
|
+
stacktrace=trace
|
314
|
+
)
|
315
|
+
except AttributeError as err:
|
316
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
317
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
318
|
+
finally:
|
319
|
+
# call the OnComplete Event
|
320
|
+
if self._no_events is False:
|
321
|
+
self._events.completed(
|
322
|
+
message=f":: Task Error: {self._program}.{self._taskname}",
|
323
|
+
task=self,
|
324
|
+
status="error",
|
325
|
+
error=exc,
|
326
|
+
)
|
327
|
+
if step_name:
|
328
|
+
raise ComponentError(f"{error!s}")
|
329
|
+
else:
|
330
|
+
raise exc
|
331
|
+
|
332
|
+
def _on_exception(self, status: str, exc: BaseException, step_name: str = None):
|
333
|
+
try:
|
334
|
+
self._state = TaskState.EXCEPTION
|
335
|
+
trace = traceback.format_exc()
|
336
|
+
self._events.exception(
|
337
|
+
message=f"{exc!s}",
|
338
|
+
component=step_name,
|
339
|
+
task=self,
|
340
|
+
status=status,
|
341
|
+
stacktrace=trace,
|
342
|
+
)
|
343
|
+
except AttributeError as err:
|
344
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
345
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
346
|
+
finally:
|
347
|
+
# call the OnComplete Event
|
348
|
+
if self._no_events is False:
|
349
|
+
self._events.completed(
|
350
|
+
message=f":: Task Ended: {self._program}.{self._taskname}",
|
351
|
+
task=self,
|
352
|
+
status=status,
|
353
|
+
error=exc,
|
354
|
+
)
|
355
|
+
if step_name:
|
356
|
+
raise ComponentError(
|
357
|
+
f"Error Getting Component {step_name}, error: {exc}"
|
358
|
+
)
|
359
|
+
elif isinstance(exc, TaskParseError):
|
360
|
+
raise TaskParseError(
|
361
|
+
f"{self._program}.{self._taskname}: {exc!s}"
|
362
|
+
)
|
363
|
+
else:
|
364
|
+
raise TaskError(
|
365
|
+
f"Task Error {self._program}.{self._taskname}: {exc!s}"
|
366
|
+
)
|
367
|
+
|
368
|
+
def get_task_code(self):
|
369
|
+
return self._task_payload
|
370
|
+
|
371
|
+
async def start(self, payload: Optional[str] = None):
|
372
|
+
# starting a Task
|
373
|
+
await super(Task, self).start()
|
374
|
+
self.logger.info(
|
375
|
+
f"Task Started {self._taskname}"
|
376
|
+
)
|
377
|
+
# Open Task:
|
378
|
+
try:
|
379
|
+
payload = await self.taskstore.open_task(
|
380
|
+
task=self._taskname,
|
381
|
+
program=self._program,
|
382
|
+
payload=payload
|
383
|
+
)
|
384
|
+
self._task_payload = payload
|
385
|
+
if not payload:
|
386
|
+
raise TaskNotFound(
|
387
|
+
f"Task Missing or empty: {self._taskname}"
|
388
|
+
)
|
389
|
+
except TaskParseError as exc:
|
390
|
+
self._on_exception(
|
391
|
+
status="Parsing Error",
|
392
|
+
exc=exc
|
393
|
+
)
|
394
|
+
except TaskNotFound as exc:
|
395
|
+
self._on_exception(
|
396
|
+
status="Task Not Found",
|
397
|
+
exc=exc
|
398
|
+
)
|
399
|
+
except Exception as exc:
|
400
|
+
self._on_exception(
|
401
|
+
status="Task Error",
|
402
|
+
exc=exc
|
403
|
+
)
|
404
|
+
# task is loaded, we need to check syntax.
|
405
|
+
# TODO: check syntax of YAML and TOML versions
|
406
|
+
try:
|
407
|
+
self.check_syntax(payload)
|
408
|
+
except TaskParseError as exc:
|
409
|
+
self._on_exception(
|
410
|
+
status="Parsing Error",
|
411
|
+
exc=exc
|
412
|
+
)
|
413
|
+
# can prepare the task before run.
|
414
|
+
try:
|
415
|
+
self._task_ = AttrDict(payload)
|
416
|
+
if "timezone" in self._task_:
|
417
|
+
# re-set timezone based on a Task parameter
|
418
|
+
self.set_timezone(self._task_.timezone)
|
419
|
+
await self.prepare()
|
420
|
+
return True
|
421
|
+
except TaskDefinition as exc:
|
422
|
+
self._on_exception(
|
423
|
+
status="Error on Task Definition",
|
424
|
+
exc=exc
|
425
|
+
)
|
426
|
+
except NotSupported as exc:
|
427
|
+
self._on_exception(
|
428
|
+
status="Not Supported", exc=exc
|
429
|
+
)
|
430
|
+
except Exception as exc:
|
431
|
+
self._on_exception(
|
432
|
+
status="Unknown Exception",
|
433
|
+
exc=exc
|
434
|
+
)
|
435
|
+
|
436
|
+
def _task_running(self):
|
437
|
+
try:
|
438
|
+
self._state = TaskState.RUNNING
|
439
|
+
if self._no_events is False:
|
440
|
+
self._events.running(
|
441
|
+
message=f":: Task.{self.task_id} Running: {self._program}.{self._taskname}",
|
442
|
+
task=self,
|
443
|
+
status="running",
|
444
|
+
disable_notification=self._no_notify,
|
445
|
+
)
|
446
|
+
except AttributeError as exc:
|
447
|
+
raise TaskError(f"Error on Event System: {exc}") from exc
|
448
|
+
except Exception as err: # pytest: disable=W0718
|
449
|
+
self.logger.error(
|
450
|
+
f"Failed to set Running status on task {self._taskname}={self.task_id}, {err}"
|
451
|
+
)
|
452
|
+
|
453
|
+
def _on_done(self, result):
|
454
|
+
try:
|
455
|
+
self._state = TaskState.DONE
|
456
|
+
if self._no_events is False:
|
457
|
+
self._events.done(
|
458
|
+
message=f":: Task Ended: {self._program}.{self._taskname}",
|
459
|
+
result=result,
|
460
|
+
task=self,
|
461
|
+
status="done",
|
462
|
+
disable_notification=self._no_notify,
|
463
|
+
)
|
464
|
+
except AttributeError as err:
|
465
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
466
|
+
raise TaskError(f"Error at Task Done: {err}") from err
|
467
|
+
finally:
|
468
|
+
if self._no_events is False:
|
469
|
+
# call the OnComplete Event
|
470
|
+
self._events.completed(
|
471
|
+
message=f":: Task Ended: {self._program}.{self._taskname}",
|
472
|
+
status="done",
|
473
|
+
task=self,
|
474
|
+
result=result,
|
475
|
+
)
|
476
|
+
|
477
|
+
def _data_error(self, status: str, exc: BaseException, step_name: str = None):
|
478
|
+
try:
|
479
|
+
self._state = TaskState.DONE_WITH_WARNINGS
|
480
|
+
self._events.data_error(
|
481
|
+
message=f"Data Error: {exc}",
|
482
|
+
component=step_name,
|
483
|
+
task=self,
|
484
|
+
status=status,
|
485
|
+
)
|
486
|
+
except AttributeError as err:
|
487
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
488
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
489
|
+
finally:
|
490
|
+
# call the OnComplete Event
|
491
|
+
if self._no_events is False:
|
492
|
+
self._events.completed(
|
493
|
+
message=f":: Data Error: {self._program}.{self._taskname}",
|
494
|
+
status=status,
|
495
|
+
task=self,
|
496
|
+
error=exc,
|
497
|
+
)
|
498
|
+
# and raise the exception:
|
499
|
+
if isinstance(exc, BaseException):
|
500
|
+
raise exc
|
501
|
+
else:
|
502
|
+
raise TaskError(str(exc))
|
503
|
+
|
504
|
+
def _not_found(self, status: str, exc: BaseException, step_name: str = None):
|
505
|
+
try:
|
506
|
+
self._state = TaskState.DONE_WITH_NODATA
|
507
|
+
if self._no_events is False:
|
508
|
+
self._events.data_not_found(
|
509
|
+
message=f"Not Found: {exc}",
|
510
|
+
component=step_name,
|
511
|
+
task=self,
|
512
|
+
status=status,
|
513
|
+
)
|
514
|
+
except AttributeError as err:
|
515
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
516
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
517
|
+
finally:
|
518
|
+
# call the OnComplete Event
|
519
|
+
if self._no_events is False:
|
520
|
+
self._events.completed(
|
521
|
+
message=f":: Not Found: {self._program}.{self._taskname}",
|
522
|
+
status=status,
|
523
|
+
task=self,
|
524
|
+
error=exc,
|
525
|
+
)
|
526
|
+
# and raise the exception:
|
527
|
+
if isinstance(exc, BaseException):
|
528
|
+
raise exc
|
529
|
+
else:
|
530
|
+
raise TaskError(str(exc))
|
531
|
+
|
532
|
+
def _file_empty(self, status: str, exc: BaseException, step_name: str = None):
|
533
|
+
try:
|
534
|
+
self._state = TaskState.ERROR
|
535
|
+
if self._no_events is False:
|
536
|
+
self._events.file_empty(
|
537
|
+
message=f"Empty File: {exc}",
|
538
|
+
error=exc,
|
539
|
+
component=step_name,
|
540
|
+
task=self,
|
541
|
+
status=status,
|
542
|
+
)
|
543
|
+
except AttributeError as err:
|
544
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
545
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
546
|
+
finally:
|
547
|
+
# call the OnComplete Event
|
548
|
+
if self._no_events is False:
|
549
|
+
self._events.completed(
|
550
|
+
message=f":: Empty File: {self._program}.{self._taskname}",
|
551
|
+
status=status,
|
552
|
+
task=self,
|
553
|
+
error=exc,
|
554
|
+
)
|
555
|
+
# and raise the exception:
|
556
|
+
if isinstance(exc, BaseException):
|
557
|
+
raise exc
|
558
|
+
else:
|
559
|
+
raise TaskError(str(exc))
|
560
|
+
|
561
|
+
def _file_not_found(self, status: str, exc: BaseException, step_name: str = None):
|
562
|
+
try:
|
563
|
+
self._state = TaskState.ERROR
|
564
|
+
if self._no_events is False:
|
565
|
+
self._events.file_not_found(
|
566
|
+
message=f"File Not Found: {exc}",
|
567
|
+
error=exc,
|
568
|
+
component=step_name,
|
569
|
+
task=self,
|
570
|
+
status=status,
|
571
|
+
)
|
572
|
+
except AttributeError as err:
|
573
|
+
self.logger.error(f"Error {self._taskname}={self.task_id}, {err}")
|
574
|
+
raise TaskError(f"Error on Event System: {err}") from err
|
575
|
+
finally:
|
576
|
+
# call the OnComplete Event
|
577
|
+
if self._no_events is False:
|
578
|
+
self._events.completed(
|
579
|
+
message=f":: Not Found: {self._program}.{self._taskname}",
|
580
|
+
status=status,
|
581
|
+
task=self,
|
582
|
+
error=exc,
|
583
|
+
)
|
584
|
+
# and raise the exception:
|
585
|
+
raise exc
|
586
|
+
|
587
|
+
async def run(self):
|
588
|
+
# run Task and returning the result.
|
589
|
+
result = None
|
590
|
+
comp = None
|
591
|
+
prev = None
|
592
|
+
_exit = False
|
593
|
+
failed: list = []
|
594
|
+
try:
|
595
|
+
task_name = self._task_.name
|
596
|
+
except TypeError:
|
597
|
+
task_name = self._taskname
|
598
|
+
self._task_running()
|
599
|
+
for step in self._pile_:
|
600
|
+
self.logger.notice(f"Step: {step.name}, Task: {self.task_id}")
|
601
|
+
step_name = step.name
|
602
|
+
if step_name in self.ignore_steps:
|
603
|
+
# we can ignore this component for execution
|
604
|
+
continue
|
605
|
+
if len(self.run_only) > 0:
|
606
|
+
# we only need to run the existing list of components
|
607
|
+
if step_name not in self.run_only:
|
608
|
+
continue
|
609
|
+
prev = comp
|
610
|
+
try:
|
611
|
+
comp = self.get_component(step, prev)
|
612
|
+
step.setStep(comp) # put the Component initialized in the Pile.
|
613
|
+
except Exception as err:
|
614
|
+
self._on_exception(status="exception", exc=err, step_name=step_name)
|
615
|
+
if self._debug:
|
616
|
+
cPrint(f":: Running {step_name} from {task_name}", level="DEBUG")
|
617
|
+
# try START
|
618
|
+
try:
|
619
|
+
start = getattr(comp, "start")
|
620
|
+
parameters = comp.user_params()
|
621
|
+
if callable(start):
|
622
|
+
if asyncio.iscoroutinefunction(start):
|
623
|
+
await comp.start(**parameters)
|
624
|
+
else:
|
625
|
+
comp.start()
|
626
|
+
else:
|
627
|
+
self._on_error(
|
628
|
+
status="not_started",
|
629
|
+
exc=f"DI: Error calling Start on Component {step_name}",
|
630
|
+
step_name=step_name,
|
631
|
+
)
|
632
|
+
except EmptyFile as exc:
|
633
|
+
self._file_empty(status="empty_file", exc=exc, step_name=step_name)
|
634
|
+
except FileNotFound as exc:
|
635
|
+
self._file_not_found(
|
636
|
+
status="file_not_found", exc=exc, step_name=step_name
|
637
|
+
)
|
638
|
+
except (NoDataFound, DataNotFound) as exc:
|
639
|
+
self._not_found(status="not_found", exc=exc, step_name=step_name)
|
640
|
+
except (ProviderError, ComponentError, NotSupported, FileError) as exc:
|
641
|
+
self._on_error(status="error", exc=exc, step_name=step_name)
|
642
|
+
except Exception as err:
|
643
|
+
self._on_exception(step_name, err)
|
644
|
+
try:
|
645
|
+
run = getattr(comp, "run", None)
|
646
|
+
if asyncio.iscoroutinefunction(run):
|
647
|
+
result = await comp.run()
|
648
|
+
elif callable(run):
|
649
|
+
result = comp.run()
|
650
|
+
else:
|
651
|
+
raise TaskFailed(
|
652
|
+
f"DI: Component {step_name} is not callable"
|
653
|
+
)
|
654
|
+
# close operations
|
655
|
+
close = getattr(comp, "close", None)
|
656
|
+
if asyncio.iscoroutinefunction(close):
|
657
|
+
await comp.close()
|
658
|
+
else:
|
659
|
+
comp.close()
|
660
|
+
if check_empty(result):
|
661
|
+
if comp.skipError == SkipErrors.SKIP:
|
662
|
+
print(f"::: SKIPPING Error on {step_name} :::: ")
|
663
|
+
failed.append(comp)
|
664
|
+
_exit = False
|
665
|
+
continue
|
666
|
+
failed.append(comp)
|
667
|
+
_exit = True
|
668
|
+
break
|
669
|
+
except EmptyFile as exc:
|
670
|
+
# its a data component a no data was found
|
671
|
+
if comp.skipError == SkipErrors.SKIP:
|
672
|
+
failed.append(comp)
|
673
|
+
self.logger.warning(
|
674
|
+
f"SKIP Failed Component: {comp!r} with error: {exc}"
|
675
|
+
)
|
676
|
+
# can skip error for this component
|
677
|
+
continue
|
678
|
+
self._file_empty(
|
679
|
+
status="empty_file",
|
680
|
+
exc=exc,
|
681
|
+
step_name=step_name
|
682
|
+
)
|
683
|
+
except (NoDataFound, DataNotFound) as err:
|
684
|
+
# its a data component a no data was found
|
685
|
+
if comp.skipError == SkipErrors.SKIP:
|
686
|
+
failed.append(comp)
|
687
|
+
self.logger.warning(
|
688
|
+
f"SKIP Failed Component: {comp!r} with error: {err}"
|
689
|
+
)
|
690
|
+
# can skip error for this component
|
691
|
+
continue
|
692
|
+
self._not_found(
|
693
|
+
status="not_found",
|
694
|
+
exc=err,
|
695
|
+
step_name=step_name
|
696
|
+
)
|
697
|
+
except FileNotFound as err:
|
698
|
+
if comp.skipError == SkipErrors.SKIP:
|
699
|
+
failed.append(comp)
|
700
|
+
self.logger.warning(
|
701
|
+
f"SKIP Failed Component: {comp!r} with error: {err}"
|
702
|
+
)
|
703
|
+
# can skip error for this component
|
704
|
+
continue
|
705
|
+
self._file_not_found(status="not_found", exc=err, step_name=step_name)
|
706
|
+
except (FileError, DataError) as err:
|
707
|
+
if comp.skipError == SkipErrors.SKIP:
|
708
|
+
failed.append(comp)
|
709
|
+
self.logger.warning(
|
710
|
+
f"SKIP Failed Component: {comp!r} with error: {err}"
|
711
|
+
)
|
712
|
+
comp = prev
|
713
|
+
# can skip error for this component
|
714
|
+
continue
|
715
|
+
self._data_error(status="data_error", exc=err, step_name=step_name)
|
716
|
+
except (ProviderError, ComponentError, NotSupported) as err:
|
717
|
+
if comp.skipError == SkipErrors.SKIP:
|
718
|
+
# can skip error for this component
|
719
|
+
failed.append(comp)
|
720
|
+
self.logger.warning(
|
721
|
+
f"SKIP Failed Component: {comp!r} with error: {err}"
|
722
|
+
)
|
723
|
+
empty = check_empty(comp.output())
|
724
|
+
if empty:
|
725
|
+
# avoid when failed, lost the chain of results:
|
726
|
+
others = comp.previous
|
727
|
+
if isinstance(others, list):
|
728
|
+
previous = others[0]
|
729
|
+
comp.result = previous.output()
|
730
|
+
else:
|
731
|
+
try:
|
732
|
+
comp.result = others.output()
|
733
|
+
except AttributeError:
|
734
|
+
self.logger.warning(
|
735
|
+
"There is no Previous Component Output"
|
736
|
+
)
|
737
|
+
comp.result = None
|
738
|
+
_exit = False
|
739
|
+
continue
|
740
|
+
else:
|
741
|
+
self._on_error(status="error", exc=err, step_name=step_name)
|
742
|
+
except Exception as err:
|
743
|
+
self._on_exception(step_name, err)
|
744
|
+
# passing variables between components
|
745
|
+
await self.exchange_variables(comp, result=result)
|
746
|
+
try:
|
747
|
+
# stop stats:
|
748
|
+
if self.enable_stat is True:
|
749
|
+
self._final_stats = await self.stat.stop()
|
750
|
+
except Exception as err:
|
751
|
+
self.logger.error(str(err))
|
752
|
+
# Empty Pile
|
753
|
+
self._pile_ = []
|
754
|
+
if _exit is True:
|
755
|
+
# TODO: checking the failed list for returning errors.
|
756
|
+
self.logger.error(f"Task Steps Failed: {failed!r}")
|
757
|
+
self._state = TaskState.DONE_WITH_WARNINGS
|
758
|
+
self._not_found(status="done_warning", exc=f"Not Found on: {failed!r}")
|
759
|
+
return False
|
760
|
+
else:
|
761
|
+
if check_empty(result):
|
762
|
+
if self.is_subtask is False:
|
763
|
+
self._state = TaskState.DONE_WITH_NODATA
|
764
|
+
# mark data not found, is a warning
|
765
|
+
self._not_found(status="not_found", exc=None)
|
766
|
+
else:
|
767
|
+
self._state = TaskState.DONE_WITH_NODATA
|
768
|
+
else:
|
769
|
+
if self.is_subtask is False:
|
770
|
+
# avoid firing OnDone when is a subtask
|
771
|
+
self._on_done(result)
|
772
|
+
if self._ignore_results is True:
|
773
|
+
return True
|
774
|
+
else:
|
775
|
+
return result
|
776
|
+
|
777
|
+
def plot(self, filename: str = None) -> None:
|
778
|
+
self.pile().plot_task(filename=filename)
|