jazzoo 0.1.0__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.
- jazzoo-0.1.0/LICENSE +21 -0
- jazzoo-0.1.0/MANIFEST.in +2 -0
- jazzoo-0.1.0/PKG-INFO +18 -0
- jazzoo-0.1.0/README.short.md +5 -0
- jazzoo-0.1.0/pyproject.toml +42 -0
- jazzoo-0.1.0/setup.cfg +11 -0
- jazzoo-0.1.0/setup.py +18 -0
- jazzoo-0.1.0/src/jazzoo/__init__.py +57 -0
- jazzoo-0.1.0/src/jazzoo/aliases/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/aliases/errors.py +5 -0
- jazzoo-0.1.0/src/jazzoo/aliases/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/aliases/rules/expand_alias.py +38 -0
- jazzoo-0.1.0/src/jazzoo/aliases/rules/get_alias_config_file.py +7 -0
- jazzoo-0.1.0/src/jazzoo/aliases/rules/read_aliases.py +36 -0
- jazzoo-0.1.0/src/jazzoo/blocks/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/blocks/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/blocks/actions/run_block.py +80 -0
- jazzoo-0.1.0/src/jazzoo/blocks/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/blocks/models/block.py +21 -0
- jazzoo-0.1.0/src/jazzoo/blocks/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/__init__.py +19 -0
- jazzoo-0.1.0/src/jazzoo/commands/__main__.py +5 -0
- jazzoo-0.1.0/src/jazzoo/commands/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/actions/confirm_command.py +36 -0
- jazzoo-0.1.0/src/jazzoo/commands/actions/run.py +100 -0
- jazzoo-0.1.0/src/jazzoo/commands/actions/run_docker.py +67 -0
- jazzoo-0.1.0/src/jazzoo/commands/entrypoints/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/entrypoints/jaz_run.py +76 -0
- jazzoo-0.1.0/src/jazzoo/commands/errors.py +26 -0
- jazzoo-0.1.0/src/jazzoo/commands/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/models/command_result.py +15 -0
- jazzoo-0.1.0/src/jazzoo/commands/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/rules/find_executable.py +18 -0
- jazzoo-0.1.0/src/jazzoo/commands/rules/has_terminal.py +9 -0
- jazzoo-0.1.0/src/jazzoo/commands/rules/is_confirm_on.py +7 -0
- jazzoo-0.1.0/src/jazzoo/commands/rules/needs_tty.py +9 -0
- jazzoo-0.1.0/src/jazzoo/commands/settings.py +7 -0
- jazzoo-0.1.0/src/jazzoo/commands/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/commands/utils/dataclass.py +34 -0
- jazzoo-0.1.0/src/jazzoo/commands/utils/format_command.py +9 -0
- jazzoo-0.1.0/src/jazzoo/commands/utils/ignoring_sigint.py +18 -0
- jazzoo-0.1.0/src/jazzoo/config/__init__.py +17 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/vendor.txt +1 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/LICENSE +20 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/__init__.py +390 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/composer.py +139 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/constructor.py +748 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/dumper.py +62 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/emitter.py +1137 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/error.py +75 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/events.py +86 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/loader.py +63 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/nodes.py +49 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/parser.py +589 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/reader.py +185 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/representer.py +389 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/resolver.py +227 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/scanner.py +1435 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/serializer.py +111 -0
- jazzoo-0.1.0/src/jazzoo/config/_vendor/yaml/tokens.py +104 -0
- jazzoo-0.1.0/src/jazzoo/config/errors.py +14 -0
- jazzoo-0.1.0/src/jazzoo/config/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/config/models/loaded_config.py +17 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/expand_include_path.py +73 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/get_config.py +26 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/get_loaded_config.py +63 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/get_value.py +199 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/prepare_config.py +5 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/read_config_file.py +30 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/read_config_layers.py +58 -0
- jazzoo-0.1.0/src/jazzoo/config/rules/split_config_path.py +7 -0
- jazzoo-0.1.0/src/jazzoo/config/settings.py +6 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/dataclass.py +34 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/format_config_path.py +5 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/merge_config.py +11 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/render_scalar.py +17 -0
- jazzoo-0.1.0/src/jazzoo/config/utils/split_expressions.py +59 -0
- jazzoo-0.1.0/src/jazzoo/enums.py +15 -0
- jazzoo-0.1.0/src/jazzoo/environment/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/environment/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/environment/actions/load_config.py +26 -0
- jazzoo-0.1.0/src/jazzoo/environment/actions/load_env.py +30 -0
- jazzoo-0.1.0/src/jazzoo/environment/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/environment/utils/parse_dotenv.py +17 -0
- jazzoo-0.1.0/src/jazzoo/errors.py +43 -0
- jazzoo-0.1.0/src/jazzoo/expressions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/expressions/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/expressions/actions/evaluate.py +17 -0
- jazzoo-0.1.0/src/jazzoo/expressions/actions/evaluate_expression.py +344 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/boolean.py +25 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/literal.py +11 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/path_join.py +12 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/pipe.py +13 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/reference.py +21 -0
- jazzoo-0.1.0/src/jazzoo/expressions/models/ternary.py +20 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/apply_builtin_pipe.py +55 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/get_by_path.py +47 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/is_truthy.py +22 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/parse_expression.py +201 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/parse_references.py +318 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/resolve_reference.py +71 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/split_reference_path.py +25 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/substitute_references.py +51 -0
- jazzoo-0.1.0/src/jazzoo/expressions/rules/tokenize_expression.py +207 -0
- jazzoo-0.1.0/src/jazzoo/expressions/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/expressions/utils/join_path.py +13 -0
- jazzoo-0.1.0/src/jazzoo/expressions/utils/render_value.py +22 -0
- jazzoo-0.1.0/src/jazzoo/expressions/utils/shell_quote.py +6 -0
- jazzoo-0.1.0/src/jazzoo/expressions/utils/strip_one_newline.py +5 -0
- jazzoo-0.1.0/src/jazzoo/functions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/functions/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/functions/actions/call_builtin_function.py +62 -0
- jazzoo-0.1.0/src/jazzoo/functions/actions/call_function.py +262 -0
- jazzoo-0.1.0/src/jazzoo/functions/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/functions/models/call_site.py +25 -0
- jazzoo-0.1.0/src/jazzoo/functions/models/curried_function.py +18 -0
- jazzoo-0.1.0/src/jazzoo/functions/models/function.py +32 -0
- jazzoo-0.1.0/src/jazzoo/functions/models/parameter.py +11 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/format_signature.py +18 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/get_function_by_path.py +25 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/get_target_by_path.py +41 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/get_targets.py +13 -0
- jazzoo-0.1.0/src/jazzoo/functions/rules/parse_curry.py +81 -0
- jazzoo-0.1.0/src/jazzoo/modules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/modules/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/modules/actions/parse_module.py +248 -0
- jazzoo-0.1.0/src/jazzoo/modules/actions/resolve_import.py +261 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/absent.py +14 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/assignment.py +13 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/builtin_call.py +14 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/frame.py +86 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/import_statement.py +26 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/module.py +28 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/parsed_source.py +15 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/scope.py +13 -0
- jazzoo-0.1.0/src/jazzoo/modules/models/variable.py +13 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/get_module_by_path.py +22 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/list_targets.py +46 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_attribute_line.py +31 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_body.py +136 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_call_arguments.py +19 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_dependencies.py +20 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_import_statement.py +101 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_parameters.py +18 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/parse_source.py +154 -0
- jazzoo-0.1.0/src/jazzoo/modules/rules/validate_module.py +489 -0
- jazzoo-0.1.0/src/jazzoo/runtime/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/runtime/entrypoints/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/runtime/entrypoints/jazzoo.py +214 -0
- jazzoo-0.1.0/src/jazzoo/runtime/entrypoints/zoo.py +150 -0
- jazzoo-0.1.0/src/jazzoo/runtime/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/runtime/utils/format_error.py +13 -0
- jazzoo-0.1.0/src/jazzoo/runtime/utils/test_utils.py +103 -0
- jazzoo-0.1.0/src/jazzoo/settings.py +40 -0
- jazzoo-0.1.0/src/jazzoo/utils/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/utils/dataclass.py +34 -0
- jazzoo-0.1.0/src/jazzoo/utils/indent_of.py +2 -0
- jazzoo-0.1.0/src/jazzoo/utils/join_continuations.py +25 -0
- jazzoo-0.1.0/src/jazzoo/utils/split_top_level.py +31 -0
- jazzoo-0.1.0/src/jazzoo/zoo/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/activate_zoo_env.py +16 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/create_venv.py +148 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/forget_zoo_env.py +31 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/init_zoo_env.py +129 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/install_fish_files.py +84 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/run_in_zoo_env.py +29 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/write_latest_zoo_env_scripts.py +21 -0
- jazzoo-0.1.0/src/jazzoo/zoo/actions/write_recent_zoo_envs.py +19 -0
- jazzoo-0.1.0/src/jazzoo/zoo/errors.py +61 -0
- jazzoo-0.1.0/src/jazzoo/zoo/models/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/zoo/models/zoo_env.py +9 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/__init__.py +0 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/find_zoo_env_of_venv.py +14 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/format_zoo_env_list.py +18 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_activate_filename.py +8 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_fish_config_dir.py +8 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_jazzoo_version.py +30 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_recent_zoo_env.py +10 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_shell_name.py +8 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_zoo_env.py +17 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_zoo_env_dir.py +7 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_zoo_link.py +7 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/get_zoo_venv_dir.py +6 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/list_zoo_envs.py +17 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/read_recent_zoo_envs.py +17 -0
- jazzoo-0.1.0/src/jazzoo/zoo/rules/validate_zoo_env_name.py +13 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/PKG-INFO +18 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/SOURCES.txt +221 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/dependency_links.txt +1 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/entry_points.txt +5 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/requires.txt +3 -0
- jazzoo-0.1.0/src/jazzoo.egg-info/top_level.txt +1 -0
- jazzoo-0.1.0/tests/test_boolean_operators.py +614 -0
- jazzoo-0.1.0/tests/test_cli.py +404 -0
- jazzoo-0.1.0/tests/test_comments.py +224 -0
- jazzoo-0.1.0/tests/test_console_output.py +265 -0
- jazzoo-0.1.0/tests/test_dataclass.py +165 -0
- jazzoo-0.1.0/tests/test_errors.py +302 -0
- jazzoo-0.1.0/tests/test_export_layers.py +523 -0
- jazzoo-0.1.0/tests/test_exports.py +264 -0
- jazzoo-0.1.0/tests/test_expressions.py +371 -0
- jazzoo-0.1.0/tests/test_functions.py +810 -0
- jazzoo-0.1.0/tests/test_imports.py +363 -0
- jazzoo-0.1.0/tests/test_inline_calls.py +145 -0
- jazzoo-0.1.0/tests/test_load_env.py +124 -0
- jazzoo-0.1.0/tests/test_local_functions.py +411 -0
- jazzoo-0.1.0/tests/test_module_state_across_imports.py +199 -0
- jazzoo-0.1.0/tests/test_package_structure.py +70 -0
- jazzoo-0.1.0/tests/test_pipes_and_currying.py +521 -0
- jazzoo-0.1.0/tests/test_shebang_blocks.py +345 -0
- jazzoo-0.1.0/tests/test_structured_values.py +1025 -0
- jazzoo-0.1.0/tests/test_substitutions.py +739 -0
- jazzoo-0.1.0/tests/test_system_variables.py +338 -0
jazzoo-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maarten Nieber
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jazzoo-0.1.0/MANIFEST.in
ADDED
jazzoo-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jazzoo
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A beast of a task-runner
|
|
5
|
+
Author: Maarten Nieber
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest; extra == "dev"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# jazzoo
|
|
15
|
+
|
|
16
|
+
A beast of a task-runner.
|
|
17
|
+
|
|
18
|
+
Docs coming soon.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "jazzoo"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A beast of a task-runner"
|
|
5
|
+
readme = "README.short.md"
|
|
6
|
+
authors = [{ name = "Maarten Nieber" }]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
# Uncomment at launch, when the GitHub repo is public
|
|
13
|
+
# [project.urls]
|
|
14
|
+
# Homepage = "https://github.com/mnieber/jazzoo"
|
|
15
|
+
# Issues = "https://github.com/mnieber/jazzoo/issues"
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = ["pytest"]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
jazzoo = "jazzoo.runtime.entrypoints.jazzoo:main"
|
|
22
|
+
jaz = "jazzoo.runtime.entrypoints.jazzoo:main"
|
|
23
|
+
jaz-run = "jazzoo.commands.entrypoints.jaz_run:main"
|
|
24
|
+
zoo = "jazzoo.runtime.entrypoints.zoo:main"
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.package-dir]
|
|
27
|
+
"" = "src"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.package-data]
|
|
33
|
+
"jazzoo.config._vendor" = ["vendor.txt"]
|
|
34
|
+
"jazzoo.config._vendor.yaml" = ["LICENSE"]
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
testpaths = ["tests"]
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
# setuptools 77 is the first that understands license = "MIT"
|
|
41
|
+
requires = ["setuptools>=77", "wheel"]
|
|
42
|
+
build-backend = "setuptools.build_meta"
|
jazzoo-0.1.0/setup.cfg
ADDED
jazzoo-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from setuptools import setup
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_placeholder():
|
|
7
|
+
this_directory = Path(__file__).parent
|
|
8
|
+
pkg_directory = this_directory / "src" / "jazzoo"
|
|
9
|
+
|
|
10
|
+
if not pkg_directory.exists():
|
|
11
|
+
pkg_directory.mkdir(parents=True)
|
|
12
|
+
with open(pkg_directory / "__init__.py", "w") as f:
|
|
13
|
+
f.write("# Placeholder for package")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
create_placeholder()
|
|
18
|
+
setup()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from jazzoo.commands import (
|
|
2
|
+
CommandAbortedError,
|
|
3
|
+
CommandError,
|
|
4
|
+
CommandFailedError,
|
|
5
|
+
CommandNotFoundError,
|
|
6
|
+
CommandResult,
|
|
7
|
+
run,
|
|
8
|
+
run_docker,
|
|
9
|
+
)
|
|
10
|
+
from jazzoo.config import (
|
|
11
|
+
ConfigError,
|
|
12
|
+
ConfigExpansionError,
|
|
13
|
+
ConfigFileError,
|
|
14
|
+
ConfigKeyError,
|
|
15
|
+
get_config,
|
|
16
|
+
prepare_config,
|
|
17
|
+
)
|
|
18
|
+
from jazzoo.errors import (
|
|
19
|
+
ArgumentError,
|
|
20
|
+
ExecutionError,
|
|
21
|
+
JazzooError,
|
|
22
|
+
ModuleImportError,
|
|
23
|
+
ParseError,
|
|
24
|
+
ResolutionError,
|
|
25
|
+
)
|
|
26
|
+
from jazzoo.expressions.actions.evaluate import evaluate
|
|
27
|
+
from jazzoo.functions.rules.get_function_by_path import get_function_by_path
|
|
28
|
+
from jazzoo.functions.rules.get_targets import get_targets
|
|
29
|
+
from jazzoo.modules.actions.parse_module import parse_module
|
|
30
|
+
from jazzoo.modules.rules.get_module_by_path import get_module_by_path
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"ArgumentError",
|
|
34
|
+
"CommandAbortedError",
|
|
35
|
+
"CommandError",
|
|
36
|
+
"CommandFailedError",
|
|
37
|
+
"CommandNotFoundError",
|
|
38
|
+
"CommandResult",
|
|
39
|
+
"ConfigError",
|
|
40
|
+
"ConfigExpansionError",
|
|
41
|
+
"ConfigFileError",
|
|
42
|
+
"ConfigKeyError",
|
|
43
|
+
"ExecutionError",
|
|
44
|
+
"JazzooError",
|
|
45
|
+
"ModuleImportError",
|
|
46
|
+
"ParseError",
|
|
47
|
+
"ResolutionError",
|
|
48
|
+
"evaluate",
|
|
49
|
+
"get_config",
|
|
50
|
+
"get_function_by_path",
|
|
51
|
+
"get_module_by_path",
|
|
52
|
+
"get_targets",
|
|
53
|
+
"parse_module",
|
|
54
|
+
"prepare_config",
|
|
55
|
+
"run",
|
|
56
|
+
"run_docker",
|
|
57
|
+
]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import shlex
|
|
2
|
+
import typing as T
|
|
3
|
+
|
|
4
|
+
from jazzoo.aliases.errors import AliasError
|
|
5
|
+
from jazzoo.aliases.rules.get_alias_config_file import get_alias_config_file
|
|
6
|
+
from jazzoo.aliases.rules.read_aliases import read_aliases
|
|
7
|
+
|
|
8
|
+
# The options of jaz that an expansion may contain
|
|
9
|
+
_ALLOWED_OPTIONS = ("--confirm", "--trace")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def expand_alias(name: str) -> T.Optional[T.List[str]]:
|
|
13
|
+
config_file = get_alias_config_file()
|
|
14
|
+
expansion = read_aliases(config_file).get(name)
|
|
15
|
+
if expansion is None:
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
tokens = shlex.split(expansion)
|
|
20
|
+
except ValueError as error:
|
|
21
|
+
raise AliasError(
|
|
22
|
+
f'alias "{name}" has an invalid expansion: {error}', filename=config_file
|
|
23
|
+
)
|
|
24
|
+
if not tokens:
|
|
25
|
+
raise AliasError(f'alias "{name}" has an empty expansion', filename=config_file)
|
|
26
|
+
|
|
27
|
+
# Only the options that change how the target runs are allowed
|
|
28
|
+
for token in tokens:
|
|
29
|
+
option = token.partition("=")[0]
|
|
30
|
+
if option.startswith("-") and option not in _ALLOWED_OPTIONS:
|
|
31
|
+
raise AliasError(
|
|
32
|
+
f'alias "{name}" may not use the option {option}',
|
|
33
|
+
filename=config_file,
|
|
34
|
+
)
|
|
35
|
+
if all(token in _ALLOWED_OPTIONS for token in tokens):
|
|
36
|
+
raise AliasError(f'alias "{name}" names no target', filename=config_file)
|
|
37
|
+
|
|
38
|
+
return tokens
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import configparser
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import typing as T
|
|
5
|
+
|
|
6
|
+
from jazzoo.aliases.errors import AliasError
|
|
7
|
+
|
|
8
|
+
# A target path: names separated by dots
|
|
9
|
+
_ALIAS_NAME_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_-]*(\.[A-Za-z_][A-Za-z0-9_-]*)*$")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def read_aliases(config_file: str) -> T.Dict[str, str]:
|
|
13
|
+
if not os.path.exists(config_file):
|
|
14
|
+
return {}
|
|
15
|
+
|
|
16
|
+
# No section is special: a section header cannot contain a newline, so the
|
|
17
|
+
# default section of configparser never occurs
|
|
18
|
+
parser = configparser.ConfigParser(
|
|
19
|
+
interpolation=None, strict=True, default_section="\n"
|
|
20
|
+
)
|
|
21
|
+
# Alias names are case-sensitive
|
|
22
|
+
parser.optionxform = str # type: ignore[assignment]
|
|
23
|
+
try:
|
|
24
|
+
with open(config_file, encoding="utf-8") as f:
|
|
25
|
+
parser.read_file(f, source=config_file)
|
|
26
|
+
except (OSError, UnicodeDecodeError, configparser.Error) as error:
|
|
27
|
+
raise AliasError(f"invalid config file: {error}", filename=config_file)
|
|
28
|
+
|
|
29
|
+
if not parser.has_section("alias"):
|
|
30
|
+
return {}
|
|
31
|
+
|
|
32
|
+
aliases = dict(parser.items("alias"))
|
|
33
|
+
for name in aliases:
|
|
34
|
+
if not _ALIAS_NAME_RE.match(name):
|
|
35
|
+
raise AliasError(f'invalid alias name "{name}"', filename=config_file)
|
|
36
|
+
return aliases
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import stat
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import tempfile
|
|
6
|
+
import typing as T
|
|
7
|
+
|
|
8
|
+
from jazzoo.errors import ExecutionError
|
|
9
|
+
from jazzoo.settings import DEFAULT_SHEBANG
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def run_block(
|
|
13
|
+
shebang: T.Optional[str],
|
|
14
|
+
body: str,
|
|
15
|
+
filename: T.Optional[str] = None,
|
|
16
|
+
line: T.Optional[int] = None,
|
|
17
|
+
is_quiet: bool = False,
|
|
18
|
+
is_interactive: bool = False,
|
|
19
|
+
) -> str:
|
|
20
|
+
"""Run one block as a single subprocess and return its raw stdout.
|
|
21
|
+
|
|
22
|
+
The block is written to a temporary executable file so the shebang selects the
|
|
23
|
+
interpreter, exactly as it would for a script on disk.
|
|
24
|
+
"""
|
|
25
|
+
shebang = shebang or DEFAULT_SHEBANG
|
|
26
|
+
script = shebang + "\n" + body
|
|
27
|
+
if not script.endswith("\n"):
|
|
28
|
+
script += "\n"
|
|
29
|
+
|
|
30
|
+
handle = tempfile.NamedTemporaryFile(
|
|
31
|
+
mode="w", suffix=".jaz-block", delete=False, encoding="utf-8"
|
|
32
|
+
)
|
|
33
|
+
try:
|
|
34
|
+
handle.write(script)
|
|
35
|
+
handle.close()
|
|
36
|
+
os.chmod(handle.name, os.stat(handle.name).st_mode | stat.S_IEXEC)
|
|
37
|
+
|
|
38
|
+
if is_interactive:
|
|
39
|
+
# Whatever was echoed must reach the console before the block's output
|
|
40
|
+
sys.stdout.flush()
|
|
41
|
+
sys.stderr.flush()
|
|
42
|
+
completed = subprocess.run([handle.name])
|
|
43
|
+
else:
|
|
44
|
+
completed = subprocess.run(
|
|
45
|
+
[handle.name],
|
|
46
|
+
capture_output=True,
|
|
47
|
+
text=True,
|
|
48
|
+
)
|
|
49
|
+
finally:
|
|
50
|
+
os.unlink(handle.name)
|
|
51
|
+
|
|
52
|
+
# An interactive block writes to the console itself, and Jazzoo never sees its
|
|
53
|
+
# output, not even in a quiet call.
|
|
54
|
+
if is_interactive:
|
|
55
|
+
if completed.returncode != 0:
|
|
56
|
+
raise ExecutionError(
|
|
57
|
+
f"recipe failed with exit code {completed.returncode}: "
|
|
58
|
+
f"command failed: {body.strip()}",
|
|
59
|
+
filename=filename,
|
|
60
|
+
line=line,
|
|
61
|
+
)
|
|
62
|
+
return ""
|
|
63
|
+
|
|
64
|
+
# The block's own output goes to the console as well as being captured for
|
|
65
|
+
# ⚙️.stdout, so a target behaves like the commands it runs. A quiet block keeps
|
|
66
|
+
# its stdout for the caller, but its stderr is always shown.
|
|
67
|
+
if completed.stdout and not is_quiet:
|
|
68
|
+
print(completed.stdout, end="")
|
|
69
|
+
if completed.stderr:
|
|
70
|
+
print(completed.stderr, end="", file=sys.stderr)
|
|
71
|
+
|
|
72
|
+
if completed.returncode != 0:
|
|
73
|
+
message = completed.stderr.strip() or f"command failed: {body.strip()}"
|
|
74
|
+
raise ExecutionError(
|
|
75
|
+
f"recipe failed with exit code {completed.returncode}: {message}",
|
|
76
|
+
filename=filename,
|
|
77
|
+
line=line,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return completed.stdout
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import typing as T
|
|
2
|
+
|
|
3
|
+
from jazzoo.enums import BlockMode
|
|
4
|
+
from jazzoo.utils.dataclass import dataclass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class BlockLine:
|
|
9
|
+
text: str
|
|
10
|
+
line: int
|
|
11
|
+
# Set by a leading `@`, which hides the echoed command but not its output.
|
|
12
|
+
is_quiet: bool = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class Block:
|
|
17
|
+
mode: BlockMode
|
|
18
|
+
# The interpreter line, e.g. "#!/usr/bin/env python3". None in jazzoo mode.
|
|
19
|
+
shebang: T.Optional[str] = None
|
|
20
|
+
lines: T.List[BlockLine] = []
|
|
21
|
+
filename: T.Optional[str] = None
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .actions.run import run
|
|
2
|
+
from .actions.run_docker import run_docker
|
|
3
|
+
from .errors import (
|
|
4
|
+
CommandAbortedError,
|
|
5
|
+
CommandError,
|
|
6
|
+
CommandFailedError,
|
|
7
|
+
CommandNotFoundError,
|
|
8
|
+
)
|
|
9
|
+
from .models.command_result import CommandResult
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"CommandAbortedError",
|
|
13
|
+
"CommandError",
|
|
14
|
+
"CommandFailedError",
|
|
15
|
+
"CommandNotFoundError",
|
|
16
|
+
"CommandResult",
|
|
17
|
+
"run",
|
|
18
|
+
"run_docker",
|
|
19
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import typing as T
|
|
3
|
+
|
|
4
|
+
from ..errors import CommandAbortedError, CommandError
|
|
5
|
+
from ..settings import CONFIRM_PROMPT, TERMINAL
|
|
6
|
+
from ..utils.format_command import format_command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def confirm_command(
|
|
10
|
+
command: T.Union[str, T.List[str]], cwd: T.Optional[str] = None
|
|
11
|
+
) -> bool:
|
|
12
|
+
try:
|
|
13
|
+
reader = open(TERMINAL, "r", encoding="utf-8")
|
|
14
|
+
writer = open(TERMINAL, "w", encoding="utf-8")
|
|
15
|
+
except OSError:
|
|
16
|
+
raise CommandError("--confirm needs a terminal")
|
|
17
|
+
|
|
18
|
+
with reader, writer:
|
|
19
|
+
# Asks again until the answer is y, n, q or Enter
|
|
20
|
+
while True:
|
|
21
|
+
writer.write(format_command(command, cwd or os.getcwd()) + "\n")
|
|
22
|
+
writer.write(CONFIRM_PROMPT)
|
|
23
|
+
writer.flush()
|
|
24
|
+
|
|
25
|
+
line = reader.readline()
|
|
26
|
+
# An empty line has a newline; no newline means the end of input
|
|
27
|
+
if not line:
|
|
28
|
+
raise CommandAbortedError("aborted by the user")
|
|
29
|
+
|
|
30
|
+
answer = line.strip().lower()
|
|
31
|
+
if answer in ("", "y"):
|
|
32
|
+
return True
|
|
33
|
+
if answer == "n":
|
|
34
|
+
return False
|
|
35
|
+
if answer == "q":
|
|
36
|
+
raise CommandAbortedError("aborted by the user")
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import signal
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import typing as T
|
|
7
|
+
|
|
8
|
+
from ..errors import CommandFailedError
|
|
9
|
+
from ..models.command_result import CommandResult
|
|
10
|
+
from ..rules.find_executable import find_executable
|
|
11
|
+
from ..rules.is_confirm_on import is_confirm_on
|
|
12
|
+
from ..utils.format_command import format_command
|
|
13
|
+
from ..utils.ignoring_sigint import ignoring_sigint
|
|
14
|
+
from .confirm_command import confirm_command
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run(
|
|
18
|
+
command: T.Union[str, T.List[str]],
|
|
19
|
+
cwd: T.Optional[str] = None,
|
|
20
|
+
env: T.Optional[T.Dict[str, str]] = None,
|
|
21
|
+
capture: bool = False,
|
|
22
|
+
check: bool = True,
|
|
23
|
+
echo: bool = False,
|
|
24
|
+
) -> CommandResult:
|
|
25
|
+
# Check the arguments before anything runs
|
|
26
|
+
if isinstance(command, str):
|
|
27
|
+
if not command.strip():
|
|
28
|
+
raise ValueError("the command is empty")
|
|
29
|
+
elif not command:
|
|
30
|
+
raise ValueError("the command is empty")
|
|
31
|
+
if cwd is not None and not os.path.isdir(cwd):
|
|
32
|
+
raise ValueError(f"directory not found: {cwd}")
|
|
33
|
+
|
|
34
|
+
environ = {**os.environ, **(env or {})}
|
|
35
|
+
|
|
36
|
+
# A string runs in bash; a list runs directly
|
|
37
|
+
if isinstance(command, str):
|
|
38
|
+
args = ["bash", "-c", command]
|
|
39
|
+
executable = shutil.which("bash") or "/bin/bash"
|
|
40
|
+
else:
|
|
41
|
+
args = list(command)
|
|
42
|
+
executable = find_executable(args[0], environ)
|
|
43
|
+
|
|
44
|
+
# The prompt shows the command, so it replaces the echo
|
|
45
|
+
if is_confirm_on():
|
|
46
|
+
if not confirm_command(command, cwd):
|
|
47
|
+
skipped_output = "" if capture else None
|
|
48
|
+
return CommandResult(
|
|
49
|
+
command=command,
|
|
50
|
+
returncode=0,
|
|
51
|
+
stdout=skipped_output,
|
|
52
|
+
stderr=skipped_output,
|
|
53
|
+
skipped=True,
|
|
54
|
+
)
|
|
55
|
+
elif echo:
|
|
56
|
+
print(format_command(command, cwd))
|
|
57
|
+
|
|
58
|
+
# The command writes to the same file descriptors as the script, so what the
|
|
59
|
+
# script printed before must come first
|
|
60
|
+
sys.stdout.flush()
|
|
61
|
+
sys.stderr.flush()
|
|
62
|
+
|
|
63
|
+
output = subprocess.PIPE if capture else None
|
|
64
|
+
process = subprocess.Popen(
|
|
65
|
+
args,
|
|
66
|
+
executable=executable,
|
|
67
|
+
cwd=cwd,
|
|
68
|
+
env=environ,
|
|
69
|
+
stdout=output,
|
|
70
|
+
stderr=output,
|
|
71
|
+
text=True,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# SIGINT is ignored only after the command has started, because an ignored
|
|
75
|
+
# signal would be inherited by the command. A ctrl-c then reaches the command
|
|
76
|
+
# only.
|
|
77
|
+
with ignoring_sigint():
|
|
78
|
+
stdout, stderr = process.communicate()
|
|
79
|
+
|
|
80
|
+
if process.returncode == -signal.SIGINT:
|
|
81
|
+
raise KeyboardInterrupt
|
|
82
|
+
|
|
83
|
+
result = CommandResult(
|
|
84
|
+
command=command,
|
|
85
|
+
returncode=process.returncode,
|
|
86
|
+
stdout=stdout,
|
|
87
|
+
stderr=stderr,
|
|
88
|
+
)
|
|
89
|
+
if check and result.returncode != 0:
|
|
90
|
+
raise CommandFailedError(_failure_message(result, cwd), result)
|
|
91
|
+
return result
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _failure_message(result: CommandResult, cwd: T.Optional[str]) -> str:
|
|
95
|
+
message = f"command failed with exit code {result.returncode}: " + format_command(
|
|
96
|
+
result.command, cwd
|
|
97
|
+
)
|
|
98
|
+
if result.stderr and result.stderr.strip():
|
|
99
|
+
message += "\n" + result.stderr.strip()
|
|
100
|
+
return message
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import typing as T
|
|
2
|
+
|
|
3
|
+
from ..models.command_result import CommandResult
|
|
4
|
+
from ..rules.needs_tty import needs_tty
|
|
5
|
+
|
|
6
|
+
Command = T.Union[str, T.List[str]]
|
|
7
|
+
RunFunction = T.Callable[..., CommandResult]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run_docker(
|
|
11
|
+
container: str,
|
|
12
|
+
user: T.Optional[str] = None,
|
|
13
|
+
workdir: T.Optional[str] = None,
|
|
14
|
+
env: T.Optional[T.Dict[str, str]] = None,
|
|
15
|
+
shell: str = "bash",
|
|
16
|
+
) -> T.Callable[[RunFunction], RunFunction]:
|
|
17
|
+
if not container or not container.strip():
|
|
18
|
+
raise ValueError("the container is empty")
|
|
19
|
+
|
|
20
|
+
container_env = dict(env or {})
|
|
21
|
+
|
|
22
|
+
def decorator(run: RunFunction) -> RunFunction:
|
|
23
|
+
def run_in_container(
|
|
24
|
+
command: Command,
|
|
25
|
+
cwd: T.Optional[str] = None,
|
|
26
|
+
env: T.Optional[T.Dict[str, str]] = None,
|
|
27
|
+
capture: bool = False,
|
|
28
|
+
check: bool = True,
|
|
29
|
+
echo: bool = False,
|
|
30
|
+
) -> CommandResult:
|
|
31
|
+
# Check the command before the docker command hides it
|
|
32
|
+
if isinstance(command, str):
|
|
33
|
+
if not command.strip():
|
|
34
|
+
raise ValueError("the command is empty")
|
|
35
|
+
command_args = [shell, "-c", command]
|
|
36
|
+
elif not command:
|
|
37
|
+
raise ValueError("the command is empty")
|
|
38
|
+
else:
|
|
39
|
+
command_args = list(command)
|
|
40
|
+
|
|
41
|
+
# The options come in a fixed order
|
|
42
|
+
docker_command = ["docker", "exec", "--interactive"]
|
|
43
|
+
if needs_tty(capture):
|
|
44
|
+
docker_command.append("--tty")
|
|
45
|
+
if user:
|
|
46
|
+
docker_command += ["--user", user]
|
|
47
|
+
# A cwd only replaces the workdir for this call
|
|
48
|
+
call_workdir = cwd or workdir
|
|
49
|
+
if call_workdir:
|
|
50
|
+
docker_command += ["--workdir", call_workdir]
|
|
51
|
+
for name, value in {**container_env, **(env or {})}.items():
|
|
52
|
+
docker_command += ["--env", f"{name}={value}"]
|
|
53
|
+
docker_command += [container, *command_args]
|
|
54
|
+
|
|
55
|
+
# The cwd and env belong to the container, not to the docker client
|
|
56
|
+
return run(
|
|
57
|
+
docker_command,
|
|
58
|
+
cwd=None,
|
|
59
|
+
env=None,
|
|
60
|
+
capture=capture,
|
|
61
|
+
check=check,
|
|
62
|
+
echo=echo,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return run_in_container
|
|
66
|
+
|
|
67
|
+
return decorator
|
|
File without changes
|