labtasker 0.2.9__tar.gz → 0.2.11__tar.gz
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.
- {labtasker-0.2.9 → labtasker-0.2.11}/PKG-INFO +3 -2
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/__init__.py +1 -1
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/client_api.py +16 -12
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/api.py +22 -4
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cli_utils.py +2 -2
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/events.py +2 -2
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/job_runner.py +18 -9
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/query_transpiler.py +23 -4
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/utils.py +27 -1
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/constants.py +0 -1
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/database.py +1 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/pyproject.toml +4 -3
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_job_runner.py +36 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/LICENSE +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/MANIFEST.in +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/README.md +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/__main__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/api_models.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/cli.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/config.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/event.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/init.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/loop.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/queue.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/task.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/cli/worker.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/LabCmd.g4 +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/LabCmdLexer.g4 +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/LabCmd.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/LabCmdLexer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/LabCmdListener.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/parser.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/config.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/context.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/exceptions.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/heartbeat.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/logging.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/pager.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/paths.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/plugin_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/resolver/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/resolver/models.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/resolver/utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/version_checker.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/templates/labtasker_root/.gitignore +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/templates/labtasker_root/client.toml +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/templates/labtasker_root/logs/.gitkeep +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/filtering.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/security.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/cli.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/config.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/db_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/dependencies.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/embedded_db.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/endpoints.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/event_manager.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/fsm.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/server/logging.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/README.txt +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/BufferedTokenStream.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/CommonTokenFactory.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/CommonTokenStream.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/FileStream.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/InputStream.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/IntervalSet.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/LL1Analyzer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/Lexer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/ListTokenSource.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/Parser.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/ParserInterpreter.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/ParserRuleContext.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/PredictionContext.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/Recognizer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/RuleContext.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/StdinStream.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/Token.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/TokenStreamRewriter.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/Utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/_pygrun.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATN.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNConfig.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNConfigSet.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNDeserializationOptions.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNDeserializer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNSimulator.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNState.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ATNType.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/LexerATNSimulator.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/LexerAction.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/LexerActionExecutor.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/ParserATNSimulator.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/PredictionMode.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/SemanticContext.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/Transition.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/atn/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/dfa/DFA.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/dfa/DFASerializer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/dfa/DFAState.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/dfa/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/error/DiagnosticErrorListener.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/error/ErrorListener.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/error/ErrorStrategy.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/error/Errors.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/error/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/Chunk.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/ParseTreeMatch.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/ParseTreePattern.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/ParseTreePatternMatcher.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/RuleTagToken.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/TokenTagToken.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/Tree.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/Trees.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/tree/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/xpath/XPath.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/xpath/XPathLexer.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/antlr4/xpath/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker/vendor/vendor.txt +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/labtasker.egg-info/SOURCES.txt +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/setup.cfg +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/demo_pager_iterator.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/dummy_jobs/job_1.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/database/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/database/mock.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/database/real.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/logging.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/mock_datetime_now.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/server/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/server/async_app.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/fixtures/server/sync_app.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_api_models.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_basic.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_config.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_event.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_init.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_loop.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_queue.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_task.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_cli/test_worker.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_cli_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/test_concurrency_job_flow_event.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/test_event_listener_basic.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/test_event_listener_entity_data.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/test_various_actions.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_event/utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_heartbeat.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_logging.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_loop_internal_error_handler.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_pager_iterator.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_parser.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/test_behavior.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/test_matching.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/test_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_query_transpiler/utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_resolver.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_concurrency/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_concurrency/run_concurrent.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_concurrency/test_runner_concurrency_success_failure.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_concurrency/test_runner_high_concurrency.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_timeout/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_timeout/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_timeout/test_job_runner_timeout.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_timeout/test_job_runner_with_resolver_timeout.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_runner_with_resolver.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_server_notification_and_client_version.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_client/test_core/test_version_checker.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_filtering/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_filtering/exception_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_filtering/test_exception_filtering.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_mock_time.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_security.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/conftest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/test_database_basic.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/test_fetch_extra_filter.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/test_query_dict_to_mongo_filter.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_database/test_required_field_fetching.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_db_utils/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_db_utils/test_arg_match.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_db_utils/test_keys_to_query_dict.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_db_utils/test_keys_to_query_dict_deepest.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_db_utils/test_keys_to_query_dict_topmost.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_embedded_db.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_endpoint/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_endpoint/test_event_basic.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_endpoint/test_server.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_endpoint/test_server_async.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_endpoint/test_server_async_ping.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_fsm.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_server/test_get_verified_queue_dependency.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_utils/__init__.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/test_utils/test_utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tests/utils.py +0 -0
- {labtasker-0.2.9 → labtasker-0.2.11}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labtasker
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: A task queue system for lab experiments
|
|
5
5
|
Author-email: Your Name <your.email@example.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -32,7 +32,7 @@ Requires-Dist: pyyaml<7.0.0,>=6.0.0
|
|
|
32
32
|
Requires-Dist: tomlkit<0.14.0,>=0.13.2
|
|
33
33
|
Requires-Dist: importlib-metadata<9.0.0,>=8.5.0
|
|
34
34
|
Requires-Dist: packaging<26.0,>=24.2
|
|
35
|
-
Requires-Dist: sse-starlette<
|
|
35
|
+
Requires-Dist: sse-starlette<4.0.0,>=2.1.3
|
|
36
36
|
Requires-Dist: httpx-sse<0.5.0,>=0.4.0
|
|
37
37
|
Requires-Dist: stamina<26.0.0,>=25.1.0
|
|
38
38
|
Requires-Dist: noneprompt<0.2.0,>=0.1.9
|
|
@@ -57,6 +57,7 @@ Requires-Dist: asgi-lifespan<3.0.0,>=2.1.0; extra == "dev"
|
|
|
57
57
|
Requires-Dist: tox<4.29.0,>=4.24.0; extra == "dev"
|
|
58
58
|
Requires-Dist: pytest-dependency<0.7.0,>=0.6.0; extra == "dev"
|
|
59
59
|
Requires-Dist: pytest-sugar<2.0.0,>=1.0.0; extra == "dev"
|
|
60
|
+
Requires-Dist: rust-just<2.0.0,>=1.42.4; extra == "dev"
|
|
60
61
|
Provides-Extra: doc
|
|
61
62
|
Requires-Dist: mkdocs-material<9.7.0,>=9.6.5; extra == "doc"
|
|
62
63
|
Requires-Dist: mkdocs-glightbox<0.5.0,>=0.4.0; extra == "doc"
|
|
@@ -42,31 +42,35 @@ __all__ = [
|
|
|
42
42
|
"connect_events",
|
|
43
43
|
"EventListener",
|
|
44
44
|
# http api (you should be careful with these unless you know what you are doing)
|
|
45
|
+
"get_httpx_client",
|
|
45
46
|
"close_httpx_client",
|
|
46
47
|
"health_check",
|
|
47
|
-
"submit_task",
|
|
48
|
-
"delete_worker",
|
|
49
48
|
"create_queue",
|
|
50
|
-
"
|
|
49
|
+
"get_queue",
|
|
51
50
|
"delete_queue",
|
|
52
|
-
"
|
|
53
|
-
"delete_worker",
|
|
51
|
+
"submit_task",
|
|
54
52
|
"fetch_task",
|
|
55
|
-
"get_queue",
|
|
56
|
-
"health_check",
|
|
57
|
-
"ls_tasks",
|
|
58
|
-
"ls_workers",
|
|
59
|
-
"refresh_task_heartbeat",
|
|
60
53
|
"report_task_status",
|
|
54
|
+
"refresh_task_heartbeat",
|
|
55
|
+
"create_worker",
|
|
56
|
+
"ls_workers",
|
|
57
|
+
"report_worker_status",
|
|
58
|
+
"ls_tasks",
|
|
59
|
+
"update_tasks",
|
|
60
|
+
"delete_task",
|
|
61
|
+
"update_queue",
|
|
62
|
+
"delete_worker",
|
|
61
63
|
# utilities
|
|
62
64
|
"run_with_pty",
|
|
63
65
|
"run_with_subprocess",
|
|
64
66
|
]
|
|
65
67
|
|
|
68
|
+
assert len(set(__all__)) == len(__all__), "Duplicated symbols in __all__"
|
|
69
|
+
|
|
66
70
|
|
|
67
71
|
def loop(
|
|
68
72
|
required_fields: Optional[List[str]] = None,
|
|
69
|
-
extra_filter: Optional[Dict[str, Any]] = None,
|
|
73
|
+
extra_filter: Optional[Union[str, Dict[str, Any]]] = None,
|
|
70
74
|
cmd: Optional[Union[str, List[str]]] = None,
|
|
71
75
|
worker_id: Optional[str] = None,
|
|
72
76
|
create_worker_kwargs: Optional[Dict[str, Any]] = None,
|
|
@@ -78,7 +82,7 @@ def loop(
|
|
|
78
82
|
|
|
79
83
|
Args:
|
|
80
84
|
required_fields: Fields (or extra fields other than specified using Required(...)) required for task execution in a dot-separated manner. E.g. ["arg1.arg11", "arg2.arg22"]
|
|
81
|
-
extra_filter: Additional filtering criteria for tasks
|
|
85
|
+
extra_filter: Additional filtering criteria for tasks. Dict in MongoDB syntax or string in Python syntax is allowed.
|
|
82
86
|
cmd: Command line arguments that runs current process. Default to sys.argv
|
|
83
87
|
worker_id: Specific worker ID to use
|
|
84
88
|
create_worker_kwargs: Arguments for default worker creation
|
|
@@ -35,6 +35,7 @@ from labtasker.client.core.utils import (
|
|
|
35
35
|
cast_http_error,
|
|
36
36
|
display_server_notifications,
|
|
37
37
|
raise_for_status,
|
|
38
|
+
transpile_query_safe,
|
|
38
39
|
)
|
|
39
40
|
from labtasker.constants import Priority
|
|
40
41
|
from labtasker.security import SecretStr, get_auth_headers
|
|
@@ -67,7 +68,13 @@ def _network_err_retry(func):
|
|
|
67
68
|
@wraps(func)
|
|
68
69
|
def wrapper(*args, **kwargs):
|
|
69
70
|
return stamina.retry(
|
|
70
|
-
on=httpx.TransportError,
|
|
71
|
+
on=httpx.TransportError,
|
|
72
|
+
attempts=10,
|
|
73
|
+
timeout=100.0,
|
|
74
|
+
wait_initial=0.5,
|
|
75
|
+
wait_max=16.0,
|
|
76
|
+
wait_jitter=1.0,
|
|
77
|
+
wait_exp_base=2.0,
|
|
71
78
|
)(func)(*args, **kwargs)
|
|
72
79
|
|
|
73
80
|
return wrapper
|
|
@@ -193,7 +200,7 @@ def fetch_task(
|
|
|
193
200
|
heartbeat_timeout: Optional[float] = None,
|
|
194
201
|
start_heartbeat: bool = True,
|
|
195
202
|
required_fields: Optional[List[str]] = None,
|
|
196
|
-
extra_filter: Optional[Dict[str, Any]] = None,
|
|
203
|
+
extra_filter: Optional[Union[str, Dict[str, Any]]] = None,
|
|
197
204
|
client: Optional[httpx.Client] = None,
|
|
198
205
|
cmd: Optional[Union[str, List[str]]] = None,
|
|
199
206
|
) -> TaskFetchResponse:
|
|
@@ -206,6 +213,9 @@ def fetch_task(
|
|
|
206
213
|
"Either eta_max or start_heartbeat must be specified."
|
|
207
214
|
)
|
|
208
215
|
|
|
216
|
+
if isinstance(extra_filter, str): # transpile to mongodb query
|
|
217
|
+
extra_filter = transpile_query_safe(query_str=extra_filter)
|
|
218
|
+
|
|
209
219
|
payload = TaskFetchRequest(
|
|
210
220
|
worker_id=worker_id,
|
|
211
221
|
eta_max=eta_max,
|
|
@@ -303,7 +313,7 @@ def ls_workers(
|
|
|
303
313
|
worker_id: Optional[str] = None,
|
|
304
314
|
worker_name: Optional[str] = None,
|
|
305
315
|
status: Optional[str] = None,
|
|
306
|
-
extra_filter: Optional[Dict[str, Any]] = None,
|
|
316
|
+
extra_filter: Optional[Union[str, Dict[str, Any]]] = None,
|
|
307
317
|
limit: int = 100,
|
|
308
318
|
offset: int = 0,
|
|
309
319
|
sort: Optional[List[Tuple[str, int]]] = None,
|
|
@@ -312,6 +322,10 @@ def ls_workers(
|
|
|
312
322
|
"""List workers."""
|
|
313
323
|
if client is None:
|
|
314
324
|
client = get_httpx_client()
|
|
325
|
+
|
|
326
|
+
if isinstance(extra_filter, str): # transpile to mongodb query
|
|
327
|
+
extra_filter = transpile_query_safe(query_str=extra_filter)
|
|
328
|
+
|
|
315
329
|
payload = WorkerLsRequest(
|
|
316
330
|
worker_id=worker_id,
|
|
317
331
|
worker_name=worker_name,
|
|
@@ -364,7 +378,7 @@ def ls_tasks(
|
|
|
364
378
|
task_id: Optional[str] = None,
|
|
365
379
|
task_name: Optional[str] = None,
|
|
366
380
|
status: Optional[str] = None,
|
|
367
|
-
extra_filter: Optional[Dict[str, Any]] = None,
|
|
381
|
+
extra_filter: Optional[Union[str, Dict[str, Any]]] = None,
|
|
368
382
|
limit: int = 100,
|
|
369
383
|
offset: int = 0,
|
|
370
384
|
sort: Optional[List[Tuple[str, int]]] = None,
|
|
@@ -373,6 +387,10 @@ def ls_tasks(
|
|
|
373
387
|
"""List tasks in a queue."""
|
|
374
388
|
if client is None:
|
|
375
389
|
client = get_httpx_client()
|
|
390
|
+
|
|
391
|
+
if isinstance(extra_filter, str): # transpile to mongodb query
|
|
392
|
+
extra_filter = transpile_query_safe(query_str=extra_filter)
|
|
393
|
+
|
|
376
394
|
payload = TaskLsRequest(
|
|
377
395
|
task_id=task_id,
|
|
378
396
|
task_name=task_name,
|
|
@@ -34,7 +34,7 @@ from labtasker.client.core.exceptions import (
|
|
|
34
34
|
QueryTranspilerError,
|
|
35
35
|
)
|
|
36
36
|
from labtasker.client.core.logging import stderr_console
|
|
37
|
-
from labtasker.client.core.
|
|
37
|
+
from labtasker.client.core.utils import transpile_query_safe
|
|
38
38
|
from labtasker.utils import parse_time_interval, unflatten_dict
|
|
39
39
|
|
|
40
40
|
DT = TypeVar("DT")
|
|
@@ -84,7 +84,7 @@ def parse_filter(filter_str: Optional[str]) -> Optional[Dict[str, Any]]:
|
|
|
84
84
|
return parse_dict(d_str=filter_str)
|
|
85
85
|
except typer.BadParameter:
|
|
86
86
|
try:
|
|
87
|
-
return
|
|
87
|
+
return transpile_query_safe(query_str=filter_str) # type: ignore[arg-type]
|
|
88
88
|
except QueryTranspilerError as e:
|
|
89
89
|
raise typer.BadParameter(f"Invalid filter str: {e}") from e
|
|
90
90
|
|
|
@@ -176,9 +176,9 @@ class EventListener:
|
|
|
176
176
|
self._retry_context_iter = stamina.retry_context(
|
|
177
177
|
on=httpx.TransportError,
|
|
178
178
|
attempts=10,
|
|
179
|
-
timeout=
|
|
179
|
+
timeout=100.0,
|
|
180
180
|
wait_initial=0.5,
|
|
181
|
-
wait_max=
|
|
181
|
+
wait_max=16.0,
|
|
182
182
|
wait_jitter=1.0,
|
|
183
183
|
wait_exp_base=2.0,
|
|
184
184
|
).__iter__()
|
|
@@ -12,6 +12,7 @@ import labtasker
|
|
|
12
12
|
from labtasker.api_models import TaskUpdateRequest
|
|
13
13
|
from labtasker.client.core.api import (
|
|
14
14
|
create_worker,
|
|
15
|
+
delete_worker,
|
|
15
16
|
fetch_task,
|
|
16
17
|
get_queue,
|
|
17
18
|
report_task_status,
|
|
@@ -37,6 +38,7 @@ from labtasker.client.core.exceptions import (
|
|
|
37
38
|
from labtasker.client.core.heartbeat import end_heartbeat, start_heartbeat
|
|
38
39
|
from labtasker.client.core.logging import log_to_file, logger, stderr_console
|
|
39
40
|
from labtasker.client.core.paths import get_labtasker_log_dir, set_labtasker_log_dir
|
|
41
|
+
from labtasker.client.core.utils import transpile_query_safe
|
|
40
42
|
from labtasker.utils import parse_time_interval
|
|
41
43
|
|
|
42
44
|
__all__ = [
|
|
@@ -105,7 +107,7 @@ def dump_task_info():
|
|
|
105
107
|
|
|
106
108
|
def loop_run(
|
|
107
109
|
required_fields: List[str],
|
|
108
|
-
extra_filter: Optional[Dict[str, Any]] = None,
|
|
110
|
+
extra_filter: Optional[Union[str, Dict[str, Any]]] = None,
|
|
109
111
|
cmd: Optional[Union[str, List[str]]] = None,
|
|
110
112
|
worker_id: Optional[str] = None,
|
|
111
113
|
create_worker_kwargs: Optional[Dict[str, Any]] = None,
|
|
@@ -141,6 +143,9 @@ def loop_run(
|
|
|
141
143
|
f"Invalid eta_max {eta_max}. ETA max must be a valid duration string (e.g. '1h', '1h30m', '50s')"
|
|
142
144
|
)
|
|
143
145
|
|
|
146
|
+
if isinstance(extra_filter, str): # transpile to mongodb query
|
|
147
|
+
extra_filter = transpile_query_safe(query_str=extra_filter)
|
|
148
|
+
|
|
144
149
|
# Check connection and authentication
|
|
145
150
|
try:
|
|
146
151
|
get_queue()
|
|
@@ -155,9 +160,12 @@ def loop_run(
|
|
|
155
160
|
raise e
|
|
156
161
|
|
|
157
162
|
# Create worker if not exists
|
|
163
|
+
auto_create_worker = False
|
|
164
|
+
|
|
158
165
|
if current_worker_id() is None:
|
|
159
|
-
|
|
160
|
-
|
|
166
|
+
auto_create_worker = worker_id is None
|
|
167
|
+
worker_id = worker_id or create_worker(**(create_worker_kwargs or {}))
|
|
168
|
+
set_current_worker_id(worker_id)
|
|
161
169
|
|
|
162
170
|
if cmd is None:
|
|
163
171
|
cmd = sys.argv
|
|
@@ -270,12 +278,9 @@ def loop_run(
|
|
|
270
278
|
resp = update_tasks(
|
|
271
279
|
task_updates=[
|
|
272
280
|
TaskUpdateRequest(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
"retries": 0,
|
|
277
|
-
"worker_id": None,
|
|
278
|
-
}
|
|
281
|
+
task_id=current_task_id(), # noqa
|
|
282
|
+
status="pending", # running -> pending
|
|
283
|
+
retries=0,
|
|
279
284
|
)
|
|
280
285
|
]
|
|
281
286
|
)
|
|
@@ -336,6 +341,10 @@ def loop_run(
|
|
|
336
341
|
finish(status="success")
|
|
337
342
|
end_heartbeat()
|
|
338
343
|
except _LabtaskerLoopExit:
|
|
344
|
+
# clean up the worker
|
|
345
|
+
if auto_create_worker: # worker is managed automatically
|
|
346
|
+
delete_worker(worker_id=current_worker_id())
|
|
347
|
+
|
|
339
348
|
logger.info("Exiting task loop.")
|
|
340
349
|
break
|
|
341
350
|
except WorkerSuspended:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ast
|
|
2
|
+
import difflib
|
|
2
3
|
from datetime import timezone
|
|
3
|
-
from typing import Any, Dict, List, NoReturn, Type
|
|
4
|
+
from typing import Any, Dict, List, NoReturn, Optional, Type
|
|
4
5
|
|
|
5
6
|
import dateparser
|
|
6
7
|
from rich.console import Console
|
|
@@ -154,9 +155,10 @@ class QueryTranspiler(ast.NodeVisitor):
|
|
|
154
155
|
ast.Or: "$or", # a or b -> {$or: [a, b]}
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
def __init__(self, query_str: str):
|
|
158
|
+
def __init__(self, query_str: str, allowed_fields: Optional[List[str]] = None):
|
|
158
159
|
super().__init__()
|
|
159
160
|
self.query_str = query_str
|
|
161
|
+
self.allowed_fields = allowed_fields
|
|
160
162
|
|
|
161
163
|
def _report_error(
|
|
162
164
|
self, node: ast.AST, msg: str, exception: Type[QueryTranspilerError]
|
|
@@ -701,6 +703,20 @@ class QueryTranspiler(ast.NodeVisitor):
|
|
|
701
703
|
Python: field_name
|
|
702
704
|
MongoDB: "field_name" (as a field reference)
|
|
703
705
|
"""
|
|
706
|
+
if self.allowed_fields and node.id not in self.allowed_fields:
|
|
707
|
+
suggestions = difflib.get_close_matches(
|
|
708
|
+
node.id, self.allowed_fields, n=1, cutoff=0.6
|
|
709
|
+
)
|
|
710
|
+
suggestion_msg = (
|
|
711
|
+
f" Maybe you meant '{suggestions[0]}'?" if suggestions else ""
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
self._report_error(
|
|
715
|
+
node=node,
|
|
716
|
+
msg=f"Field '{node.id}' is unknown or not allowed.{suggestion_msg}"
|
|
717
|
+
f"\nAllowed fields: {', '.join(sorted(self.allowed_fields))}",
|
|
718
|
+
exception=QueryTranspilerValueError,
|
|
719
|
+
)
|
|
704
720
|
return node.id
|
|
705
721
|
|
|
706
722
|
def visit_Attribute(self, node: ast.Attribute) -> str:
|
|
@@ -960,7 +976,9 @@ class QueryTranspiler(ast.NodeVisitor):
|
|
|
960
976
|
)
|
|
961
977
|
|
|
962
978
|
|
|
963
|
-
def transpile_query(
|
|
979
|
+
def transpile_query(
|
|
980
|
+
query_str: str, allowed_fields: Optional[List[str]] = None
|
|
981
|
+
) -> Dict[str, Any]:
|
|
964
982
|
"""
|
|
965
983
|
Transpile a Python-like query string and convert it to a MongoDB query object.
|
|
966
984
|
|
|
@@ -969,6 +987,7 @@ def transpile_query(query_str: str) -> Dict[str, Any]:
|
|
|
969
987
|
|
|
970
988
|
Args:
|
|
971
989
|
query_str: A string containing a Python-like expression to be converted
|
|
990
|
+
allowed_fields: A list of allowed fields (e.g. ast.Name.id). If None, allowed_fields will not be checked.
|
|
972
991
|
|
|
973
992
|
Returns:
|
|
974
993
|
A dictionary representing the equivalent MongoDB query
|
|
@@ -979,7 +998,7 @@ def transpile_query(query_str: str) -> Dict[str, Any]:
|
|
|
979
998
|
try:
|
|
980
999
|
query_str = query_str.strip()
|
|
981
1000
|
parsed_ast = ast.parse(query_str)
|
|
982
|
-
visitor = QueryTranspiler(query_str=query_str)
|
|
1001
|
+
visitor = QueryTranspiler(query_str=query_str, allowed_fields=allowed_fields)
|
|
983
1002
|
result = visitor.visit(parsed_ast)
|
|
984
1003
|
|
|
985
1004
|
if isinstance(result, bool) or isinstance(result, int):
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
import subprocess
|
|
4
4
|
import sys
|
|
5
5
|
import threading
|
|
6
|
-
from functools import wraps
|
|
6
|
+
from functools import partial, wraps
|
|
7
7
|
from typing import Any, Callable, Optional
|
|
8
8
|
|
|
9
9
|
import httpx
|
|
@@ -20,6 +20,7 @@ from labtasker.client.core.exceptions import (
|
|
|
20
20
|
)
|
|
21
21
|
from labtasker.client.core.logging import stderr_console, stdout_console
|
|
22
22
|
from labtasker.client.core.paths import get_labtasker_client_config_path
|
|
23
|
+
from labtasker.client.core.query_transpiler import transpile_query
|
|
23
24
|
|
|
24
25
|
server_notification_prefix = {
|
|
25
26
|
"info": "[bold dodger_blue1]INFO(notification):[/bold dodger_blue1] ",
|
|
@@ -33,6 +34,31 @@ server_notification_level = {
|
|
|
33
34
|
"high": 2,
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
transpile_query_safe = partial(
|
|
38
|
+
transpile_query,
|
|
39
|
+
allowed_fields=[
|
|
40
|
+
"task_id",
|
|
41
|
+
"queue_id",
|
|
42
|
+
"status",
|
|
43
|
+
"task_name",
|
|
44
|
+
"created_at",
|
|
45
|
+
"start_time",
|
|
46
|
+
"last_heartbeat",
|
|
47
|
+
"last_modified",
|
|
48
|
+
"heartbeat_timeout",
|
|
49
|
+
"task_timeout",
|
|
50
|
+
"max_retries",
|
|
51
|
+
"retries",
|
|
52
|
+
"priority",
|
|
53
|
+
"metadata",
|
|
54
|
+
"args",
|
|
55
|
+
"cmd",
|
|
56
|
+
"summary",
|
|
57
|
+
"worker_id",
|
|
58
|
+
"worker_name",
|
|
59
|
+
],
|
|
60
|
+
)
|
|
61
|
+
|
|
36
62
|
|
|
37
63
|
def json_serializer(obj: Any, **kwargs) -> str:
|
|
38
64
|
return json.dumps(to_jsonable_python(obj), **kwargs)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "labtasker"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.11"
|
|
8
8
|
description = "A task queue system for lab experiments"
|
|
9
9
|
authors = [{ name = "Your Name", email = "your.email@example.com" }]
|
|
10
10
|
license = { text = "Apache License 2.0" }
|
|
@@ -36,7 +36,7 @@ dependencies = [
|
|
|
36
36
|
"tomlkit (>=0.13.2,<0.14.0)",
|
|
37
37
|
"importlib-metadata (>=8.5.0,<9.0.0)",
|
|
38
38
|
"packaging (>=24.2,<26.0)",
|
|
39
|
-
"sse-starlette (>=2.1.3,<
|
|
39
|
+
"sse-starlette (>=2.1.3,<4.0.0)",
|
|
40
40
|
"httpx-sse (>=0.4.0,<0.5.0)",
|
|
41
41
|
"stamina (>=25.1.0,<26.0.0)",
|
|
42
42
|
"noneprompt (>=0.1.9,<0.2.0)",
|
|
@@ -64,6 +64,7 @@ dev = [
|
|
|
64
64
|
"tox (>=4.24.0,<4.29.0)",
|
|
65
65
|
"pytest-dependency (>=0.6.0,<0.7.0)",
|
|
66
66
|
"pytest-sugar (>=1.0.0,<2.0.0)",
|
|
67
|
+
"rust-just (>=1.42.4,<2.0.0)",
|
|
67
68
|
]
|
|
68
69
|
doc = [
|
|
69
70
|
"mkdocs-material (>=9.6.5,<9.7.0)",
|
|
@@ -132,7 +133,7 @@ disable_error_code = [
|
|
|
132
133
|
"no-redef",
|
|
133
134
|
"import-untyped"
|
|
134
135
|
]
|
|
135
|
-
python_version = "
|
|
136
|
+
python_version = "0.2.11"
|
|
136
137
|
warn_unused_configs = true
|
|
137
138
|
ignore_missing_imports = true
|
|
138
139
|
show_error_codes = true
|
|
@@ -90,6 +90,42 @@ def test_job_success(setup_tasks):
|
|
|
90
90
|
assert task.status == "success"
|
|
91
91
|
|
|
92
92
|
|
|
93
|
+
def test_job_str_filter(setup_tasks):
|
|
94
|
+
"""Test if Pythonic query str as extra_filter works"""
|
|
95
|
+
tasks = ls_tasks()
|
|
96
|
+
assert tasks.found
|
|
97
|
+
assert len(tasks.content) == TOTAL_TASKS
|
|
98
|
+
|
|
99
|
+
idx = -1
|
|
100
|
+
|
|
101
|
+
@loop_run(
|
|
102
|
+
required_fields=["arg1", "arg2"],
|
|
103
|
+
eta_max="1h",
|
|
104
|
+
pass_args_dict=True,
|
|
105
|
+
extra_filter="args.arg2.arg3 < 2", # only run the first two tasks
|
|
106
|
+
)
|
|
107
|
+
def job(args):
|
|
108
|
+
nonlocal idx
|
|
109
|
+
idx += 1
|
|
110
|
+
task_name = task_info().task_name
|
|
111
|
+
assert task_name == f"test_task_{idx}"
|
|
112
|
+
assert args["arg1"] == idx
|
|
113
|
+
assert args["arg2"]["arg3"] == idx
|
|
114
|
+
|
|
115
|
+
time.sleep(0.5) # a tiny delay to ensure the tasks api request are processed
|
|
116
|
+
|
|
117
|
+
finish("success")
|
|
118
|
+
|
|
119
|
+
job()
|
|
120
|
+
|
|
121
|
+
assert idx + 1 == 2, idx
|
|
122
|
+
|
|
123
|
+
tasks = ls_tasks(extra_filter="args.arg2.arg3 < 2")
|
|
124
|
+
assert tasks.found
|
|
125
|
+
for task in tasks.content:
|
|
126
|
+
assert task.status == "success"
|
|
127
|
+
|
|
128
|
+
|
|
93
129
|
def test_job_manual_failure(setup_tasks):
|
|
94
130
|
cnt = 0
|
|
95
131
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/LabCmdLexer.py
RENAMED
|
File without changes
|
{labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/core/cmd_parser/generated/LabCmdListener.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labtasker-0.2.9 → labtasker-0.2.11}/labtasker/client/templates/labtasker_root/logs/.gitkeep
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|