[elbe-devel] [PATCH 07/11] elbepack: migrate command_out_stderr to subprocess package

Thomas Weißschuh thomas.weissschuh at linutronix.de
Wed Mar 13 16:54:56 CET 2024


The subprocess APIs are more powerful, better documented and
standardized.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/initvmaction.py   | 27 +++++++++++++--------------
 elbepack/pbuilderaction.py | 32 ++++++++++++++++----------------
 elbepack/shellhelper.py    | 42 ------------------------------------------
 elbepack/xmlpreprocess.py  | 18 ++++++++----------
 4 files changed, 37 insertions(+), 82 deletions(-)

diff --git a/elbepack/initvmaction.py b/elbepack/initvmaction.py
index bd56682da991..7f5b871e3403 100644
--- a/elbepack/initvmaction.py
+++ b/elbepack/initvmaction.py
@@ -12,11 +12,11 @@ import time
 
 import elbepack
 from elbepack.config import cfg
-from elbepack.directories import elbe_exe
+from elbepack.directories import elbe_exe, run_elbe
 from elbepack.elbexml import ElbeXML, ValidationError, ValidationMode
 from elbepack.filesystem import TmpdirFilesystem
 from elbepack.repodir import Repodir, RepodirError
-from elbepack.shellhelper import command_out_stderr, system
+from elbepack.shellhelper import system
 from elbepack.treeutils import etree
 from elbepack.xmlpreprocess import PreprocessWrapper
 
@@ -215,11 +215,11 @@ class EnsureAction(InitVMAction):
         elif self.initvm_state() == libvirt.VIR_DOMAIN_RUNNING:
             stop = time.time() + 300
             while True:
-                cmd = command_out_stderr(f'{sys.executable} {elbe_exe} control list_projects')
-                if cmd[0] == 0:
+                ps = run_elbe(['control', 'list_projects'], capture_output=True)
+                if ps.returncode == 0:
                     break
                 if time.time() > stop:
-                    print(f'Waited for 5 minutes and the daemon is still not active: {cmd[2]}',
+                    print(f'Waited for 5 minutes and the daemon is still not active: {ps.stderr}',
                           file=sys.stderr)
                     sys.exit(123)
                 time.sleep(10)
@@ -300,21 +300,20 @@ def submit_and_dl_result(xmlfile, cdrom, opt):
         with PreprocessWrapper(xmlfile, opt) as ppw:
             xmlfile = ppw.preproc
 
-            ret, prjdir, err = command_out_stderr(
-                f'{sys.executable} {elbe_exe} control create_project')
-            if ret != 0:
+            ps = run_elbe(['control', 'create_project'], capture_output=True, encoding='utf-8')
+            if ps.returncode != 0:
                 print('elbe control create_project failed.', file=sys.stderr)
-                print(err, file=sys.stderr)
+                print(ps.stderr, file=sys.stderr)
                 print('Giving up', file=sys.stderr)
                 sys.exit(128)
 
-            prjdir = prjdir.strip()
+            prjdir = ps.stdout.strip()
 
-            cmd = f'{sys.executable} {elbe_exe} control set_xml {prjdir} {xmlfile}'
-            ret, _, err = command_out_stderr(cmd)
-            if ret != 0:
+            ps = run_elbe(['control', 'set_xml', prjdir, xmlfile],
+                          capture_output=True, encoding='utf-8')
+            if ps.returncode != 0:
                 print('elbe control set_xml failed2', file=sys.stderr)
-                print(err, file=sys.stderr)
+                print(ps.stderr, file=sys.stderr)
                 print('Giving up', file=sys.stderr)
                 sys.exit(129)
     except subprocess.CalledProcessError:
diff --git a/elbepack/pbuilderaction.py b/elbepack/pbuilderaction.py
index 908db86fbd64..35f0220095c4 100644
--- a/elbepack/pbuilderaction.py
+++ b/elbepack/pbuilderaction.py
@@ -6,9 +6,9 @@ import os
 import subprocess
 import sys
 
-from elbepack.directories import elbe_exe
+from elbepack.directories import elbe_exe, run_elbe
 from elbepack.filesystem import TmpdirFilesystem
-from elbepack.shellhelper import command_out_stderr, system
+from elbepack.shellhelper import system
 from elbepack.xmlpreprocess import PreprocessWrapper
 
 
@@ -77,22 +77,22 @@ class CreateAction(PBuilderAction):
         if opt.xmlfile:
             try:
                 with PreprocessWrapper(opt.xmlfile, opt) as ppw:
-                    ret, prjdir, err = command_out_stderr(
-                        f'{sys.executable} {elbe_exe} control create_project')
-                    if ret != 0:
+                    ps = run_elbe(['control', 'create_project'],
+                                  capture_output=True, encoding='utf-8')
+                    if ps.returncode != 0:
                         print('elbe control create_project failed.',
                               file=sys.stderr)
-                        print(err, file=sys.stderr)
+                        print(ps.stderr, file=sys.stderr)
                         print('Giving up', file=sys.stderr)
                         sys.exit(152)
 
-                    prjdir = prjdir.strip()
-                    ret, _, err = command_out_stderr(
-                        f'{sys.executable} {elbe_exe} control set_xml "{prjdir}" "{ppw.preproc}"')
+                    prjdir = ps.stdout.strip()
+                    ps = run_elbe(['control', 'set_xml', prjdir, ppw.preproc],
+                                  capture_output=True, encoding='utf-8')
 
-                    if ret != 0:
+                    if ps.returncode != 0:
                         print('elbe control set_xml failed.', file=sys.stderr)
-                        print(err, file=sys.stderr)
+                        print(ps.stderr, file=sys.stderr)
                         print('Giving up', file=sys.stderr)
                         sys.exit(153)
             except subprocess.CalledProcessError:
@@ -185,15 +185,15 @@ class BuildAction(PBuilderAction):
         tmp = TmpdirFilesystem()
 
         if opt.xmlfile:
-            ret, prjdir, err = command_out_stderr(
-                f'{sys.executable} {elbe_exe} control create_project --retries 60 "{opt.xmlfile}"')
-            if ret != 0:
+            ps = run_elbe(['control', 'create_project', '--retries', '60', opt.xmlfile],
+                          capture_output=True, encoding='utf-8')
+            if ps.returncode != 0:
                 print('elbe control create_project failed.', file=sys.stderr)
-                print(err, file=sys.stderr)
+                print(ps.stderr, file=sys.stderr)
                 print('Giving up', file=sys.stderr)
                 sys.exit(160)
 
-            prjdir = prjdir.strip()
+            prjdir = ps.stdout.strip()
 
             try:
                 system(f'{sys.executable} {elbe_exe} control build_pbuilder "{prjdir}"')
diff --git a/elbepack/shellhelper.py b/elbepack/shellhelper.py
index 483e6eacaebc..5449b8bea243 100644
--- a/elbepack/shellhelper.py
+++ b/elbepack/shellhelper.py
@@ -86,48 +86,6 @@ def command_out(cmd, stdin=None, output=PIPE, env_add=None):
     return p.returncode, out
 
 
-def command_out_stderr(cmd, stdin=None, env_add=None):
-    """command_out_stderr() - Execute cmd in a shell.
-
-    Returns a tuple of the exitcode, stdout and stderr of cmd.
-
-    --
-
-    >>> command_out_stderr("$TRUE && cat -", stdin=b"ELBE", env_add={"TRUE":"true"})
-    (0, 'ELBE', '')
-
-    >>> command_out_stderr("1>&2 cat - && false", stdin=b"ELBE")
-    (1, '', 'ELBE')
-
-    >>> command_out_stderr("1>&2 cat - && false", stdin="ELBE")
-    (1, '', 'ELBE')
-
-    >>> command_out_stderr("true")
-    (0, '', '')
-
-    """
-    new_env = os.environ.copy()
-    if env_add:
-        new_env.update(env_add)
-
-    if isinstance(stdin, str):
-        stdin = stdin.encode()
-
-    if stdin is None:
-        p = Popen(cmd, shell=True,
-                  stdout=PIPE, stderr=PIPE, env=new_env)
-        output, stderr = p.communicate()
-    else:
-        p = Popen(cmd, shell=True,
-                  stdout=PIPE, stderr=PIPE, stdin=PIPE, env=new_env)
-        output, stderr = p.communicate(input=stdin)
-
-    output = TextIOWrapper(BytesIO(output), encoding='utf-8', errors='replace').read()
-    stderr = TextIOWrapper(BytesIO(stderr), encoding='utf-8', errors='replace').read()
-
-    return p.returncode, output, stderr
-
-
 def do(cmd, allow_fail=False, stdin=None, env_add=None, log_cmd=None):
     """do() - Execute cmd in a shell and redirect outputs to logging.
 
diff --git a/elbepack/xmlpreprocess.py b/elbepack/xmlpreprocess.py
index 02d33383e82d..46bd8f157ee5 100644
--- a/elbepack/xmlpreprocess.py
+++ b/elbepack/xmlpreprocess.py
@@ -16,10 +16,9 @@ from urllib.request import urlopen
 
 from elbepack.archivedir import ArchivedirError, combinearchivedir
 from elbepack.config import cfg
-from elbepack.directories import elbe_exe
+from elbepack.directories import run_elbe
 from elbepack.isooptions import iso_option_valid
 from elbepack.schema import xml_schema_file
-from elbepack.shellhelper import command_out_stderr
 from elbepack.validate import error_log_to_strings
 
 from lxml import etree
@@ -421,22 +420,21 @@ class PreprocessWrapper:
     def __init__(self, xmlfile, opt):
         self.xmlfile = xmlfile
         self.outxml = None
-        self.options = ''
+        self.options = []
 
         if opt.variant:
-            self.options += f' --variants "{opt.variant}"'
+            self.options.extend(['--variants', opt.variant])
 
     def __enter__(self):
         fname = f'elbe-{time.time_ns()}.xml'
         self.outxml = os.path.join(tempfile.gettempdir(), fname)
 
-        cmd = (f'{sys.executable} {elbe_exe} preprocess {self.options} '
-               f'-o {self.outxml} {self.xmlfile}')
-        ret, _, err = command_out_stderr(cmd)
-        if ret != 0:
+        ps = run_elbe(['preprocess', *self.options, '-o', self.outxml, self.xmlfile],
+                      capture_output=True, encoding='utf-8')
+        if ps.returncode != 0:
             print('elbe preprocess failed.', file=sys.stderr)
-            print(err, file=sys.stderr)
-            raise subprocess.CalledProcessError(ret, cmd)
+            print(ps.stderr, file=sys.stderr)
+            raise subprocess.CalledProcessError(ps.returncode, ps.args)
 
         return self
 

-- 
2.44.0



More information about the elbe-devel mailing list