lib.ExecContext: Add open() + close() around _run()

Enclose ExecContext._run() in an open() / close() - pair. This is convenient for the caller in that it doesn't need to take care of opening and closing for one call only, and inconvenient in that it forces the caller to conciously add an open() / close() - pair around multiple run() calls where it wants the context to stay open in between. Or use the ExecContext as a context manager.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-04-25 08:29:55 +02:00
commit a9475de48e
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
2 changed files with 41 additions and 36 deletions

View file

@ -33,8 +33,6 @@ class CmdListRepos(Cmd): # export
case 'ssh': case 'ssh':
if re.match(r'ssh://.*git\.janware\.com/', args.base_url): if re.match(r'ssh://.*git\.janware\.com/', args.base_url):
from jw.pkg.lib.ec.SSHClient import SSHClient, ssh_client from jw.pkg.lib.ec.SSHClient import SSHClient, ssh_client
ssh: SSHClient|None = None
try:
ssh = ssh_client(args.base_url, interactive=self.app.interactive, verbose_default=self.app.verbose) ssh = ssh_client(args.base_url, interactive=self.app.interactive, verbose_default=self.app.verbose)
if username is not None: if username is not None:
ssh.set_username(username) ssh.set_username(username)
@ -44,11 +42,6 @@ class CmdListRepos(Cmd): # export
result = await ssh.run(cmd) result = await ssh.run(cmd)
print('\n'.join(result.stdout.decode().splitlines())) print('\n'.join(result.stdout.decode().splitlines()))
return return
except:
raise
finally:
if ssh is not None:
await ssh.close()
case 'https': case 'https':
from jw.pkg.lib.base import InputMode from jw.pkg.lib.base import InputMode
cmd_input = InputMode.NonInteractive cmd_input = InputMode.NonInteractive

View file

@ -287,6 +287,11 @@ class ExecContext(Base):
# be returned by CallContext and is very much allowed # be returned by CallContext and is very much allowed
assert cmd_input is not None, 'Invalid: cmd_input is None' assert cmd_input is not None, 'Invalid: cmd_input is None'
# Enclose multiple run() calls in an additional open() / close() pair
# if you want the context to stay open between the calls
await self.open()
try:
ret = Result(None, None, 1) ret = Result(None, None, 1)
with self.CallContext(self, title=title, cmd=cmd, cmd_input=cmd_input, mod_env=mod_env, wd=wd, with self.CallContext(self, title=title, cmd=cmd, cmd_input=cmd_input, mod_env=mod_env, wd=wd,
log_prefix='|', throw=throw, verbose=verbose) as cc: log_prefix='|', throw=throw, verbose=verbose) as cc:
@ -303,6 +308,9 @@ class ExecContext(Base):
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)
finally:
await self.close()
return ret return ret
async def _sudo( async def _sudo(
@ -482,10 +490,14 @@ class ExecContext(Base):
cmds.append({'cmd': ['chmod', mode, out]}) cmds.append({'cmd': ['chmod', mode, out]})
if atomic: if atomic:
cmds.append({'cmd': ['mv', out, path]}) cmds.append({'cmd': ['mv', out, path]})
await self.open()
try:
for cmd in cmds: for cmd in cmds:
log(DEBUG, f'{self.log_name}: Running {pretty_cmd(cmd['cmd'], wd)}') log(DEBUG, f'{self.log_name}: Running {pretty_cmd(cmd['cmd'], wd)}')
ret = await __run(**cmd) ret = await __run(**cmd)
return ret return ret
finally:
await self.close()
except: except:
if throw: if throw:
raise raise