mirror of
ssh://git.janware.com/janware/proj/jw-pkg
synced 2026-04-25 17:45:55 +02:00
lib.ExecContext: Align .sudo() prototype to .run()
ExecContext's .sudo() omits many of run()'s parameters, and this
commit adds them. To avoid redundancy around repeating and massaging
the long parameter list of both functions and their return values, it
also adds some deeper changes:
- Make run(), _run(), sudo() and _sudo() always return instances of
Result. Before it was allowed to return a triplet of stdout,
stderr, and exit status.
- Have ExecContext stay out of the business of decoding the result
entirely. Result provides a convenience method .decode()
operating on stdout and stderr and leaves the decision to the
caller.
This entails miniscule adaptations in calling code, namely in
App.os_release, util.get_profile_env() and CmdListRepos._run().
- Wrap the _run() and _sudo() callbacks in a context manager object
of type CallContext to avoid code duplication.
- Consistently name the first argument to run(), _run(), sudo() and
_sudo() "cmd", not "args". The latter suggests that the caller is
omitting the executable, which is not the case.
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
37af0a05e9
commit
02697af568
6 changed files with 165 additions and 100 deletions
|
|
@ -16,7 +16,7 @@ class Local(Base):
|
|||
|
||||
async def _run(
|
||||
self,
|
||||
args: list[str],
|
||||
cmd: list[str],
|
||||
wd: str|None,
|
||||
verbose: bool,
|
||||
cmd_input: str|None,
|
||||
|
|
@ -57,11 +57,11 @@ class Local(Base):
|
|||
old_env = os.environ.copy()
|
||||
try:
|
||||
os.environ.update(env)
|
||||
return pty.spawn(args, master_read=reader)
|
||||
return pty.spawn(cmd, master_read=reader)
|
||||
finally:
|
||||
os.environ.clear()
|
||||
os.environ.update(old_env)
|
||||
return pty.spawn(args, master_read=reader)
|
||||
return pty.spawn(cmd, master_read=reader)
|
||||
|
||||
stdout_chunks: list[bytes] = []
|
||||
enc_for_verbose = sys.stdout.encoding or "utf-8"
|
||||
|
|
@ -71,13 +71,13 @@ class Local(Base):
|
|||
|
||||
# PTY merges stdout/stderr
|
||||
stdout = b"".join(stdout_chunks) if stdout_chunks else None
|
||||
return stdout, None, exit_code
|
||||
return Result(stdout, None, exit_code)
|
||||
|
||||
# -- non-interactive mode
|
||||
stdin = asyncio.subprocess.DEVNULL if cmd_input is None else asyncio.subprocess.PIPE
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
*args,
|
||||
*cmd,
|
||||
stdin=stdin,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
|
|
@ -127,13 +127,13 @@ class Local(Base):
|
|||
stdout = b"".join(stdout_parts) if stdout_parts else None
|
||||
stderr = b"".join(stderr_parts) if stderr_parts else None
|
||||
|
||||
return stdout, stderr, exit_code
|
||||
return Result(stdout, stderr, exit_code)
|
||||
|
||||
finally:
|
||||
if cwd is not None:
|
||||
os.chdir(cwd)
|
||||
|
||||
async def _sudo(self, cmd: list[str], mod_env: dict[str, str], opts: list[str], verbose: bool) -> Result:
|
||||
async def _sudo(self, cmd: list[str], mod_env: dict[str, str], opts: list[str], *args, **kwargs) -> Result:
|
||||
env: dict[str, str]|None = None
|
||||
cmd_input: str|None = None
|
||||
if mod_env:
|
||||
|
|
@ -146,8 +146,4 @@ class Local(Base):
|
|||
cmdline.append('--preserve-env=' + ','.join(mod_env.keys()))
|
||||
cmdline.extend(opts)
|
||||
cmdline.extend(cmd)
|
||||
if self.interactive:
|
||||
cmd_input = "mode:interactive"
|
||||
# Need to call the base class function, because _run() needs more
|
||||
# parameters than we have values for
|
||||
return await self.run(cmdline, throw=True, verbose=verbose, env=env, cmd_input=cmd_input)
|
||||
return await self._run(cmdline, *args, **kwargs)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue