Skip to content

Commit

Permalink
Store environment name in each action
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rikardg committed Jan 14, 2025
1 parent 143ed64 commit d7890e5
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 21 deletions.
7 changes: 5 additions & 2 deletions src/bygg/cmd/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@ class ByggContext:

@dataclass
class EntryPoint:
def __repr__(self):
return self.name

name: str
description: str


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
]
32 changes: 23 additions & 9 deletions src/bygg/cmd/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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({})
)
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down
17 changes: 15 additions & 2 deletions src/bygg/cmd/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand All @@ -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
6 changes: 4 additions & 2 deletions src/bygg/cmd/list_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 5 additions & 3 deletions src/bygg/cmd/tree.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions src/bygg/core/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -62,6 +63,7 @@ class Action(ActionContext):
"""

scheduler: Scheduler | None = None
_current_environment: str | None = None

command: Command | None
dependency_files: set[str]
Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()


Expand Down
2 changes: 2 additions & 0 deletions tests/test_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
@pytest.fixture
def init_scheduler():
Scheduler()
Action._current_environment = "test_Action"
yield
Action._current_environment = None
Action.scheduler = None


Expand Down
16 changes: 13 additions & 3 deletions tests/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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
2 changes: 2 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit d7890e5

Please sign in to comment.