lib.ExecContext: Code beautification

- Move _sudo() above sudo()

    To have a pattern in lib.ExecContext and avoid future churn: If a
    public wrapper calls a protected method, define the protected
    method above the respective wrapper.

  - sudo(): Make cmd_input default equal to run(): InputMode.OptInteractive

  - CallContext: Expose parameters throw, wd, cmd as properties for
    later use

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-04-14 20:39:11 +02:00
commit 8ef478e63f

View file

@ -11,7 +11,6 @@ if TYPE_CHECKING:
from types import TracebackType from types import TracebackType
from .log import * from .log import *
from .util import pretty_cmd
class InputMode(Enum): class InputMode(Enum):
Interactive = auto() Interactive = auto()
@ -49,14 +48,15 @@ class ExecContext(abc.ABC):
throw: bool, throw: bool,
verbose: bool verbose: bool
) -> None: ) -> None:
self.__parent = parent
self.__title = title
self.__delim = title if title is not None else f'---- {parent.uri}: Running {pretty_cmd(cmd, wd)} -'
delim_len = 120
self.__delim += '-' * max(0, delim_len - len(self.__delim))
self.__cmd = cmd self.__cmd = cmd
self.__wd = wd self.__wd = wd
self.__log_prefix = log_prefix self.__log_prefix = log_prefix
self.__parent = parent
self.__title = title
self.__pretty_cmd: str|None = None
self.__delim = title if title is not None else f'---- {parent.uri}: Running {self.pretty_cmd} -'
delim_len = 120
self.__delim += '-' * max(0, delim_len - len(self.__delim))
# -- At the end of this dance, interactive needs to be either True # -- At the end of this dance, interactive needs to be either True
# or False # or False
@ -80,7 +80,6 @@ class ExecContext(abc.ABC):
self.__cmd_input = cmd_input if not isinstance(cmd_input, InputMode) else None self.__cmd_input = cmd_input if not isinstance(cmd_input, InputMode) else None
self.__throw = throw self.__throw = throw
self.__verbose = verbose if verbose is not None else parent.verbose_default self.__verbose = verbose if verbose is not None else parent.verbose_default
self.__pretty_cmd: str|None = None
def __enter__(self) -> CallContext: def __enter__(self) -> CallContext:
self.log_delim(start=True) self.log_delim(start=True)
@ -110,9 +109,22 @@ class ExecContext(abc.ABC):
def cmd_input(self) -> bool: def cmd_input(self) -> bool:
return self.__cmd_input return self.__cmd_input
@property
def throw(self) -> bool:
return self.__throw
@property
def wd(self) -> str|None:
return self.__wd
@property
def cmd(self) -> list[str]:
return self.__cmd
@property @property
def pretty_cmd(self) -> str: def pretty_cmd(self) -> str:
if self.__pretty_cmd is None: if self.__pretty_cmd is None:
from .util import pretty_cmd
self.__pretty_cmd = pretty_cmd(self.__cmd, self.__wd) self.__pretty_cmd = pretty_cmd(self.__cmd, self.__wd)
return self.__pretty_cmd return self.__pretty_cmd
@ -204,19 +216,23 @@ class ExecContext(abc.ABC):
log_prefix='|', throw=throw, verbose=verbose) as cc: log_prefix='|', throw=throw, verbose=verbose) as cc:
try: try:
ret = await self._run( ret = await self._run(
cmd=cmd, cmd=cc.cmd,
wd=wd, wd=wd,
verbose=cc.verbose, verbose=cc.verbose,
cmd_input=cc.cmd_input, cmd_input=cc.cmd_input,
env=env, env=env,
interactive=cc.interactive, interactive=cc.interactive,
log_prefix = cc.log_prefix log_prefix=cc.log_prefix
) )
except Exception as e: except Exception as e:
return cc.exception(ret, e) return cc.exception(ret, e)
cc.check_exit_code(ret) cc.check_exit_code(ret)
return ret return ret
@abc.abstractmethod
async def _sudo(self, *args, **kwargs) -> Result:
pass
async def sudo( async def sudo(
self, self,
cmd: list[str], cmd: list[str],
@ -225,7 +241,7 @@ class ExecContext(abc.ABC):
wd: str|None = None, wd: str|None = None,
throw: bool = True, throw: bool = True,
verbose: bool|None = None, verbose: bool|None = None,
cmd_input: str|None = None, cmd_input: Input = InputMode.OptInteractive,
env: dict[str, str]|None = None, env: dict[str, str]|None = None,
title: str=None, title: str=None,
) -> Result: ) -> Result:
@ -239,7 +255,7 @@ class ExecContext(abc.ABC):
log_prefix='|', throw=throw, verbose=verbose) as cc: log_prefix='|', throw=throw, verbose=verbose) as cc:
try: try:
ret = await self._sudo( ret = await self._sudo(
cmd=cmd, cmd=cc.cmd,
mod_env=mod_env, mod_env=mod_env,
opts=opts, opts=opts,
wd=wd, wd=wd,
@ -247,17 +263,13 @@ class ExecContext(abc.ABC):
cmd_input=cc.cmd_input, cmd_input=cc.cmd_input,
env=env, env=env,
interactive=cc.interactive, interactive=cc.interactive,
log_prefix = cc.log_prefix, log_prefix=cc.log_prefix,
) )
except Exception as e: except Exception as e:
return cc.exception(ret, e) return cc.exception(ret, e)
cc.check_exit_code(ret) cc.check_exit_code(ret)
return ret return ret
@abc.abstractmethod
async def _sudo(self, *args, **kwargs) -> Result:
pass
@classmethod @classmethod
def create(cls, uri: str, *args, **kwargs) -> Self: def create(cls, uri: str, *args, **kwargs) -> Self:
tokens = re.split(r'://', uri) tokens = re.split(r'://', uri)