[rtems-central commit] util: Add function to run commands

Sebastian Huber sebh at rtems.org
Wed Mar 10 09:02:05 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    5277664d16385f35b25f8862c3971988e42dd798
Changeset: http://git.rtems.org/rtems-central/commit/?id=5277664d16385f35b25f8862c3971988e42dd798

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Mar  8 17:06:49 2021 +0100

util: Add function to run commands

---

 rtems_spec_to_x.py           | 25 +++++--------------------
 rtemsspec/tests/test_util.py | 20 ++++++++++++++++++--
 rtemsspec/util.py            | 37 +++++++++++++++++++++++++++++++++++--
 3 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/rtems_spec_to_x.py b/rtems_spec_to_x.py
index 06653cf..10ccc78 100755
--- a/rtems_spec_to_x.py
+++ b/rtems_spec_to_x.py
@@ -25,10 +25,9 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
+import logging
 import os
 import string
-import subprocess
-from typing import List
 
 import rtemsspec.applconfig
 import rtemsspec.build
@@ -39,21 +38,6 @@ import rtemsspec.util
 import rtemsspec.validation
 
 
-def _run_command(args: List[str], cwd: str) -> int:
-    task = subprocess.Popen(args,
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.STDOUT,
-                            cwd=cwd)
-    assert task.stdout is not None
-    while True:
-        line = task.stdout.readline()
-        if line:
-            print(line.decode("utf-8").strip())
-        elif task.poll() is not None:
-            break
-    return task.wait()
-
-
 def _run_pre_qualified_only_build(config: dict, item_cache: ItemCache) -> None:
     files = rtemsspec.build.gather_files(config, item_cache)
     source_dir = config["source-directory"]
@@ -63,11 +47,11 @@ def _run_pre_qualified_only_build(config: dict, item_cache: ItemCache) -> None:
         content = string.Template(config["config-ini"]).substitute(config)
         config_ini.write(content)
     specs = os.path.relpath(os.path.join(source_dir, "spec"), workspace_dir)
-    _run_command([
+    rtemsspec.util.run_command([
         "./waf", "configure", "--rtems-specs", specs, "--rtems-top-group",
         "/build/grp"
     ], workspace_dir)
-    _run_command(["./waf"], workspace_dir)
+    rtemsspec.util.run_command(["./waf"], workspace_dir)
 
 
 def _run_pre_qualified_doxygen(config: dict) -> None:
@@ -84,11 +68,12 @@ def _run_pre_qualified_doxygen(config: dict) -> None:
         content = Template(doxyfile_template.read()).substitute(doxyfile_vars)
         with open(os.path.join(workspace_dir, "Doxyfile"), "w") as doxyfile:
             doxyfile.write(content)
-    _run_command(["doxygen"], workspace_dir)
+    rtemsspec.util.run_command(["doxygen"], workspace_dir)
 
 
 def main() -> None:
     """ Generates glossaries of terms according to the configuration. """
+    logging.basicConfig(level="DEBUG")
     config = rtemsspec.util.load_config("config.yml")
     item_cache = ItemCache(config["spec"])
     rtemsspec.glossary.generate(config["glossary"], item_cache)
diff --git a/rtemsspec/tests/test_util.py b/rtemsspec/tests/test_util.py
index c85e683..7affd79 100644
--- a/rtemsspec/tests/test_util.py
+++ b/rtemsspec/tests/test_util.py
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-2-Clause
 """ Unit tests for the rtemsspec.util module. """
 
-# Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+# Copyright (C) 2020, 2021 embedded brains GmbH (http://www.embedded-brains.de)
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -25,8 +25,10 @@
 # POSSIBILITY OF SUCH DAMAGE.
 
 import os
+import logging
 
-from rtemsspec.util import copy_files, load_config
+from rtemsspec.util import copy_files, load_config, run_command
+from rtemsspec.tests.util import get_and_clear_log
 
 
 def test_copy_files(tmpdir):
@@ -43,3 +45,17 @@ def test_load_config():
     config = load_config(filename)
     assert config["a"] == "b"
     assert config["c"] == "d"
+
+
+def test_run(caplog):
+    caplog.set_level(logging.DEBUG)
+    status = run_command(["echo", "A"])
+    assert status == 0
+    assert get_and_clear_log(caplog) == """INFO run in '.': 'echo' 'A'
+DEBUG A"""
+    stdout = []
+    status = run_command(["echo", "A"], stdout=stdout)
+    assert status == 0
+    assert stdout[0].strip() == "A"
+    status = run_command(["sleep", "0.1"])
+    assert status == 0
diff --git a/rtemsspec/util.py b/rtemsspec/util.py
index d2403cd..bf07b5f 100644
--- a/rtemsspec/util.py
+++ b/rtemsspec/util.py
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-2-Clause
 """ This module provides utility functions. """
 
-# Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+# Copyright (C) 2020, 2021 embedded brains GmbH (http://www.embedded-brains.de)
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -24,9 +24,11 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
+import logging
 import os
 import shutil
-from typing import Any, List
+import subprocess
+from typing import Any, List, Optional
 import yaml
 
 
@@ -63,3 +65,34 @@ def load_config(config_filename: str) -> Any:
     IncludeLoader.add_constructor("!include", IncludeLoader.include)
     with open(config_filename, "r") as config_file:
         return yaml.load(config_file.read(), Loader=IncludeLoader)
+
+
+def run_command(args: List[str],
+                cwd: str = ".",
+                stdout: Optional[List[str]] = None,
+                env=None) -> int:
+    """
+    Runs the command in a subprocess in the working directory and environment.
+
+    Optionally, the standard output of the subprocess is returned.  Returns the
+    exit status of the subprocess.
+    """
+    logging.info("run in '%s': %s", cwd, " ".join(f"'{arg}'" for arg in args))
+    task = subprocess.Popen(args,
+                            stdin=subprocess.PIPE,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.STDOUT,
+                            cwd=cwd,
+                            env=env)
+    assert task.stdout is not None
+    while True:
+        raw_line = task.stdout.readline()
+        if raw_line:
+            line = raw_line.decode("utf-8").rstrip()
+            if stdout is None:
+                logging.debug("%s", line)
+            else:
+                stdout.append(line)
+        elif task.poll() is not None:
+            break
+    return task.wait()



More information about the vc mailing list