From d7890e56db9aa0ef1a690d3254958d635bd5850d Mon Sep 17 00:00:00 2001 From: Rikard Gillemyr Date: Wed, 15 Jan 2025 00:04:42 +0100 Subject: [PATCH] Store environment name in each action Store the name of the environment it belongs to in each action so that the command line commands will only operate on actions from the correct environment. Previously, actions belonging to the ambient environment would be listed also under any other environment if that environment was already activated in the shell. --- src/bygg/cmd/datastructures.py | 7 +++++-- src/bygg/cmd/dispatcher.py | 32 +++++++++++++++++++++++--------- src/bygg/cmd/environments.py | 17 +++++++++++++++-- src/bygg/cmd/list_actions.py | 6 ++++-- src/bygg/cmd/tree.py | 8 +++++--- src/bygg/core/action.py | 7 +++++++ tests/conftest.py | 2 ++ tests/test_action.py | 2 ++ tests/test_tree.py | 16 +++++++++++++--- tests/test_utils.py | 2 ++ 10 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/bygg/cmd/datastructures.py b/src/bygg/cmd/datastructures.py index 5098104..a30d409 100644 --- a/src/bygg/cmd/datastructures.py +++ b/src/bygg/cmd/datastructures.py @@ -49,6 +49,9 @@ class ByggContext: @dataclass class EntryPoint: + def __repr__(self): + return self.name + name: str description: str @@ -56,9 +59,9 @@ class EntryPoint: NO_DESCRIPTION = "No description" -def get_entrypoints(ctx: ByggContext) -> list[EntryPoint]: +def get_entrypoints(ctx: ByggContext, environment_name: str) -> list[EntryPoint]: return [ EntryPoint(x.name, x.description or NO_DESCRIPTION) for x in ctx.scheduler.build_actions.values() - if x.is_entrypoint + if x.is_entrypoint and x.environment == environment_name ] diff --git a/src/bygg/cmd/dispatcher.py b/src/bygg/cmd/dispatcher.py index eab7253..41662cd 100644 --- a/src/bygg/cmd/dispatcher.py +++ b/src/bygg/cmd/dispatcher.py @@ -264,15 +264,21 @@ def run_or_collect_in_environment( logger.info("Running-collecting: in ambient environment") load_environment(ctx, environment_name) - logger.debug("morot %s", get_entrypoints(ctx)) - subprocess_data.found_actions = {e.name for e in get_entrypoints(ctx)} - subprocess_data.list = list_collect_for_environment(ctx) + logger.debug( + "Entrypoints found for %s: %s", + environment_name, + get_entrypoints(ctx, environment_name), + ) + subprocess_data.found_actions = { + e.name for e in get_entrypoints(ctx, environment_name) + } + subprocess_data.list = list_collect_for_environment(ctx, environment_name) subprocess_data.tree = ( # Only collect tree data if not completing, since the completion tester in # pytest messes with code that is loaded dynamically in examples/trivial so that # tree doesn't work. Might be fixable, but that's for future Homer. Completion # code works fine when called interactively and not from pytest. - tree_collect_for_environment(ctx) + tree_collect_for_environment(ctx, environment_name) if not is_completing() else SubProcessIpcDataTree({}) ) @@ -388,10 +394,11 @@ def subprocess_dispatcher(parser, args_namespace): args = ByggNamespace(**vars(args_namespace)) assert args.is_restarted_with_env + environment_name = args.is_restarted_with_env logger.info( "Running action '%s' in environment '%s'.", args.actions, - args.is_restarted_with_env, + environment_name, ) # Read static configuration @@ -401,13 +408,20 @@ def subprocess_dispatcher(parser, args_namespace): ctx = init_bygg_context(configuration, parser, args_namespace) ctx.ipc_data = SubProcessIpcData() - load_environment(ctx, args.is_restarted_with_env) + load_environment(ctx, environment_name) - ctx.ipc_data.found_actions = {e.name for e in get_entrypoints(ctx)} + logger.debug( + "Entrypoints found for %s: %s", + environment_name, + get_entrypoints(ctx, environment_name), + ) + ctx.ipc_data.found_actions = { + e.name for e in get_entrypoints(ctx, environment_name) + } action = args.actions[0] if args.actions else None - ctx.ipc_data.list = list_collect_for_environment(ctx) - ctx.ipc_data.tree = tree_collect_for_environment(ctx) + ctx.ipc_data.list = list_collect_for_environment(ctx, environment_name) + ctx.ipc_data.tree = tree_collect_for_environment(ctx, environment_name) ipc_filename = args.ipc_filename[0] if args.ipc_filename else None if ipc_filename: diff --git a/src/bygg/cmd/environments.py b/src/bygg/cmd/environments.py index 0036253..60b20ae 100644 --- a/src/bygg/cmd/environments.py +++ b/src/bygg/cmd/environments.py @@ -112,7 +112,7 @@ def load_environment(ctx: ByggContext, environment_name: str): return None python_build_file = environment.byggfile if environment else PYTHON_INPUTFILE - load_python_build_file(python_build_file) + load_python_build_file(python_build_file, environment_name) return None @@ -149,10 +149,11 @@ def register_actions_from_configuration( outputs=action.outputs, dependencies=action.dependencies, command=shell_command, + environment=action.environment, ) -def load_python_build_file(build_file: str): +def load_python_build_file(build_file: str, environment_name: str): # modify load path to make the current directory importable preamble = """\ import os @@ -163,4 +164,16 @@ def load_python_build_file(build_file: str): if os.path.isfile(build_file): with open(build_file, "r") as f: + Action._current_environment = environment_name + logger.info( + "Loading Python file %s for environment %s", + build_file, + environment_name, + ) exec(textwrap.dedent(preamble) + f.read(), globals()) + logger.info( + "Back from loading Python file %s for environment %s", + build_file, + environment_name, + ) + Action._current_environment = None diff --git a/src/bygg/cmd/list_actions.py b/src/bygg/cmd/list_actions.py index c1d32dd..03dfd8f 100644 --- a/src/bygg/cmd/list_actions.py +++ b/src/bygg/cmd/list_actions.py @@ -18,9 +18,11 @@ HEADER = f"{TS.BOLD}Available actions:{TS.RESET}" -def list_collect_for_environment(ctx: ByggContext) -> SubProcessIpcDataList: +def list_collect_for_environment( + ctx: ByggContext, environment_name: str +) -> SubProcessIpcDataList: """Collects the currently loaded entrypoints""" - entrypoints = get_entrypoints(ctx) + entrypoints = get_entrypoints(ctx, environment_name) sorted_actions = sorted(entrypoints, key=lambda x: x.name) default_action_name = ctx.configuration.settings.default_action diff --git a/src/bygg/cmd/tree.py b/src/bygg/cmd/tree.py index ad9fb08..09d968e 100644 --- a/src/bygg/cmd/tree.py +++ b/src/bygg/cmd/tree.py @@ -1,6 +1,6 @@ import itertools -from bygg.cmd.datastructures import SubProcessIpcDataTree, get_entrypoints +from bygg.cmd.datastructures import ByggContext, SubProcessIpcDataTree, get_entrypoints from bygg.output.output import TerminalStyle as TS @@ -51,7 +51,9 @@ def print_tree(ipc_data_tree: SubProcessIpcDataTree, actions: list[str]): print("\n" + "\n".join(trees)) -def tree_collect_for_environment(ctx) -> SubProcessIpcDataTree: +def tree_collect_for_environment( + ctx: ByggContext, environment_name: str +) -> SubProcessIpcDataTree: """Collect the currently loaded entrypoints and render their respective dependency trees. @@ -66,7 +68,7 @@ def tree_collect_for_environment(ctx) -> SubProcessIpcDataTree: └── no_outputs_A """ - entrypoints = get_entrypoints(ctx) + entrypoints = get_entrypoints(ctx, environment_name) indent = 4 style = TreeStyleUnicode(indent) diff --git a/src/bygg/core/action.py b/src/bygg/core/action.py index 0040276..a4dd449 100644 --- a/src/bygg/core/action.py +++ b/src/bygg/core/action.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Callable, Iterable, Literal, Optional from bygg.core.common_types import CommandStatus +from bygg.logging import logger if TYPE_CHECKING: from bygg.core.scheduler import Scheduler @@ -62,6 +63,7 @@ class Action(ActionContext): """ scheduler: Scheduler | None = None + _current_environment: str | None = None command: Command | None dependency_files: set[str] @@ -78,6 +80,7 @@ def __init__( command: Command | None = None, scheduling_type: SchedulingType = "processpool", description: str | None = None, + environment: Optional[str] = None, ): self.name = name self.message = message @@ -97,6 +100,10 @@ def __init__( else None ) + self.environment = environment or Action._current_environment + assert self.environment + logger.info("Constructing Action for environment %s", self.environment) + self.dependency_files = set() assert self.scheduler diff --git a/tests/conftest.py b/tests/conftest.py index dc93f7c..1e52491 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,7 +21,9 @@ def scheduler_fixture(): scheduler = Scheduler() cache_file = get_closed_tmpfile() scheduler.init_cache(cache_file) + Action._current_environment = "scheduler_fixture" yield (scheduler, cache_file) + Action._current_environment = None scheduler.shutdown() diff --git a/tests/test_action.py b/tests/test_action.py index a617365..cd9f3a5 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -7,7 +7,9 @@ @pytest.fixture def init_scheduler(): Scheduler() + Action._current_environment = "test_Action" yield + Action._current_environment = None Action.scheduler = None diff --git a/tests/test_tree.py b/tests/test_tree.py index 0f53da4..01cdf81 100644 --- a/tests/test_tree.py +++ b/tests/test_tree.py @@ -9,6 +9,7 @@ from bygg.cmd.configuration import Byggfile from bygg.cmd.datastructures import ByggContext, SubProcessIpcData from bygg.cmd.tree import print_tree, tree_collect_for_environment +from bygg.core.action import Action from bygg.core.runner import ProcessRunner from bygg.core.scheduler import Scheduler @@ -43,7 +44,10 @@ def test_tree_single_action( ): scheduler, _ = scheduler_single_action ctx = create_byggcontext(scheduler) - print_tree(tree_collect_for_environment(ctx), ["action1"]) + assert Action._current_environment + print_tree( + tree_collect_for_environment(ctx, Action._current_environment), ["action1"] + ) stdout, _ = capsys.readouterr() assert stdout == snapshot @@ -53,7 +57,10 @@ def test_tree_four_nonbranching_actions( ): scheduler, _ = scheduler_four_nonbranching_actions ctx = create_byggcontext(scheduler) - print_tree(tree_collect_for_environment(ctx), ["action1"]) + assert Action._current_environment + print_tree( + tree_collect_for_environment(ctx, Action._current_environment), ["action1"] + ) stdout, _ = capsys.readouterr() assert stdout == snapshot @@ -63,6 +70,9 @@ def test_tree_branching_actions( ): scheduler, _ = scheduler_branching_actions ctx = create_byggcontext(scheduler) - print_tree(tree_collect_for_environment(ctx), ["action1"]) + assert Action._current_environment + print_tree( + tree_collect_for_environment(ctx, Action._current_environment), ["action1"] + ) stdout, _ = capsys.readouterr() assert stdout == snapshot diff --git a/tests/test_utils.py b/tests/test_utils.py index 4efbf77..1118df9 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -53,8 +53,10 @@ def test_filenames_from_pattern(test_case): def test_shell_command(): + Action._current_environment = "test_shell_command" shell_command = create_shell_command("echo 'shell action output'") status = shell_command(Action("test context", inputs=set(), outputs=set())) assert status.rc == 0 assert status.output == "shell action output\n" + Action._current_environment = None