diff --git a/src/python/jw/pkg/lib/ExecContext.py b/src/python/jw/pkg/lib/ExecContext.py index dd6a62fc..3888df70 100644 --- a/src/python/jw/pkg/lib/ExecContext.py +++ b/src/python/jw/pkg/lib/ExecContext.py @@ -3,7 +3,8 @@ from __future__ import annotations import abc, re, sys -from typing import NamedTuple, TYPE_CHECKING +from enum import Enum, auto +from typing import NamedTuple, TypeAlias, TYPE_CHECKING if TYPE_CHECKING: from typing import Self, Type @@ -12,6 +13,14 @@ if TYPE_CHECKING: from .log import * from .util import pretty_cmd +class InputMode(Enum): + Interactive = auto() + NonInteractive = auto() + OptInteractive = auto() + Auto = auto() + +Input: TypeAlias = InputMode | None | str + class Result(NamedTuple): stdout: str|None @@ -34,7 +43,7 @@ class ExecContext(abc.ABC): parent: ExecContext, title: str, cmd: list[str], - cmd_input: str|None, + cmd_input: Input, wd: str|None, log_prefix: str, throw: bool, @@ -53,13 +62,13 @@ class ExecContext(abc.ABC): # or False interactive: bool|None = None match cmd_input: - case 'mode:interactive': + case InputMode.Interactive: interactive = True - case 'mode:non-interactive': + case InputMode.NonInteractive: interactive = False - case 'mode:opt-interactive': + case InputMode.OptInteractive: interactive = parent.interactive - case 'mode:auto': + case InputMode.Auto: interactive = sys.stdin.isatty() if interactive is None: interactive = parent.interactive @@ -68,7 +77,7 @@ class ExecContext(abc.ABC): assert interactive in [ True, False ] self.__interactive = interactive - self.__cmd_input = cmd_input if cmd_input[:5] != 'mode:' else None + self.__cmd_input = cmd_input if not isinstance(cmd_input, InputMode) else None self.__throw = throw self.__verbose = verbose if verbose is not None else parent.verbose_default self.__pretty_cmd: str|None = None @@ -97,6 +106,10 @@ class ExecContext(abc.ABC): def verbose(self) -> bool: return self.__verbose + @property + def cmd_input(self) -> bool: + return self.__cmd_input + @property def pretty_cmd(self) -> str: if self.__pretty_cmd is None: @@ -159,7 +172,7 @@ class ExecContext(abc.ABC): wd: str|None = None, throw: bool = True, verbose: bool|None = None, - cmd_input: str|None = 'mode:opt-interactive', + cmd_input: Input = InputMode.OptInteractive, env: dict[str, str]|None = None, title: str=None ) -> Result: @@ -172,12 +185,12 @@ class ExecContext(abc.ABC): throw: Raise an exception on non-zero exit status if True verbose: Emit log output while the command runs cmd_input: - - "mode:opt-interactive" -> Let --interactive govern how to handle interactivity (default) - - "mode:interactive" -> Inherit terminal stdin - - "mode:auto" -> Inherit terminal stdin if it is a TTY - - "mode:non-interactive" -> stdin from /dev/null - - None -> Alias for mode:non-interactive - - otherwise -> Feed cmd_input to stdin + - "InputMode.OptInteractive" -> Let --interactive govern how to handle interactivity (default) + - "InputMode.Interactive" -> Inherit terminal stdin + - "InputMode.Auto" -> Inherit terminal stdin if it is a TTY + - "InputMode.NonInteractive" -> stdin from /dev/null + - None -> Alias for InputMode.NonInteractive + - otherwise -> Feed cmd_input to stdin env: The environment the command should be run in Returns: @@ -193,7 +206,7 @@ class ExecContext(abc.ABC): cmd=cmd, wd=wd, verbose=cc.verbose, - cmd_input=cmd_input, + cmd_input=cc.cmd_input, env=env, interactive=cc.interactive, log_prefix = cc.log_prefix @@ -230,7 +243,7 @@ class ExecContext(abc.ABC): opts=opts, wd=wd, verbose=cc.verbose, - cmd_input=cmd_input, + cmd_input=cc.cmd_input, env=env, interactive=cc.interactive, log_prefix = cc.log_prefix,