[elbe-devel] [PATCH 2/2] elbepack: log: simplify log handler housekeeping

Thomas Weißschuh thomas.weissschuh at linutronix.de
Thu Aug 22 14:24:07 CEST 2024


The log module creates custom log handlers for each project.
These are then stored in a thread-local variable to clean them up when
not needed anymore.
This can be simplified by using a contextmanager, which coincidentally
is already used today.
Only the doctests can't use this because of syntax limitations in the
doctest module.
Push the added complexity into the doctests instead of the main logging
module where it affects everything.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/log.py         | 20 +++++++++-----------
 elbepack/shellhelper.py | 16 ++++++++--------
 2 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/elbepack/log.py b/elbepack/log.py
index 6613e500b042..b49c9a47acb5 100644
--- a/elbepack/log.py
+++ b/elbepack/log.py
@@ -12,7 +12,6 @@ from contextlib import contextmanager
 
 
 root = logging.getLogger()
-local = threading.local()
 context_fmt = logging.Formatter('%(context)s%(message)s')
 msgonly_fmt = logging.Formatter('%(message)s')
 log = logging.getLogger('log')
@@ -147,18 +146,18 @@ _logging_methods = {
 
 @contextmanager
 def elbe_logging(*args, **kwargs):
+    cleanup = open_logging(*args, **kwargs)
     try:
-        open_logging(*args, **kwargs)
         yield
     finally:
-        close_logging()
+        cleanup()
 
 
 def open_logging(**targets):
-
-    close_logging()
     root.setLevel(logging.DEBUG)
 
+    handlers = []
+
     for key, call in _logging_methods.items():
         if key in targets:
             destinations = targets[key]
@@ -166,16 +165,15 @@ def open_logging(**targets):
                 destinations = [destinations]
 
             for h in call(destinations):
-                local.handlers.append(h)
+                handlers.append(h)
                 root.addHandler(h)
 
-
-def close_logging():
-    if hasattr(local, 'handlers'):
-        for h in local.handlers:
+    def _cleanup():
+        for h in handlers:
             root.removeHandler(h)
             h.close()
-    local.handlers = []
+
+    return _cleanup
 
 
 class AsyncLogging(threading.Thread):
diff --git a/elbepack/shellhelper.py b/elbepack/shellhelper.py
index 42ba8299fa30..8cedf4867ce1 100644
--- a/elbepack/shellhelper.py
+++ b/elbepack/shellhelper.py
@@ -43,8 +43,7 @@ def run(cmd, /, *, check=True, log_cmd=None, **kwargs):
     >>> import os
     >>> import sys
     >>> from elbepack.log import open_logging
-    >>> open_logging(streams=os.devnull)
-
+    >>> cleanup = open_logging(streams=os.devnull)
     >>> run(['echo', 'ELBE'])
     CompletedProcess(args=['echo', 'ELBE'], returncode=0)
 
@@ -64,12 +63,12 @@ def run(cmd, /, *, check=True, log_cmd=None, **kwargs):
 
     >>> run(['echo', 'ELBE'], stdout=ELBE_LOGGING)
     CompletedProcess(args=['echo', 'ELBE'], returncode=0)
+    >>> cleanup()
 
     Let's redirect the loggers to current stdout
 
     >>> from elbepack.log import open_logging
-    >>> open_logging(streams=sys.stdout)
-
+    >>> cleanup = open_logging(streams=sys.stdout)
     >>> run(['echo', 'ELBE'], stdout=ELBE_LOGGING)
     [CMD] echo ELBE
     ELBE
@@ -78,6 +77,7 @@ def run(cmd, /, *, check=True, log_cmd=None, **kwargs):
 
     >>> run(['echo', 'ELBE'], capture_output=True)
     CompletedProcess(args=['echo', 'ELBE'], returncode=0, stdout=b'ELBE\\n', stderr=b'')
+    >>> cleanup()
     """
     stdout = kwargs.pop('stdout', None)
     stderr = kwargs.pop('stderr', None)
@@ -105,8 +105,7 @@ def do(cmd, /, *, env_add=None, **kwargs):
     Let's redirect the loggers to current stdout
     >>> import sys
     >>> from elbepack.log import open_logging
-    >>> open_logging(streams=sys.stdout)
-
+    >>> cleanup = open_logging(streams=sys.stdout)
     >>> do("true")
     [CMD] true
 
@@ -125,6 +124,7 @@ def do(cmd, /, *, env_add=None, **kwargs):
     Traceback (most recent call last):
     ...
     subprocess.CalledProcessError: ...
+    >>> cleanup()
     """
 
     new_env = os.environ.copy()
@@ -144,12 +144,12 @@ def chroot(directory, cmd, /, *, env_add=None, **kwargs):
 
     >>> import sys
     >>> from elbepack.log import open_logging
-    >>> open_logging(streams=sys.stdout)
-
+    >>> cleanup = open_logging(streams=sys.stdout)
     >>> chroot("/", "true") # doctest: +ELLIPSIS
     Traceback (most recent call last):
     ...
     subprocess.CalledProcessError: ...
+    >>> cleanup()
     """
 
     new_env = {'LANG': 'C',

-- 
2.46.0



More information about the elbe-devel mailing list