[Git][reproducible-builds/diffoscope][fix/python-libarchive-2.8] 6 commits: Move the computation of the terminal line eraser into logging.py

Mattia Rizzolo gitlab at salsa.debian.org
Sun Jul 8 18:06:25 CEST 2018


Mattia Rizzolo pushed to branch fix/python-libarchive-2.8 at Reproducible Builds / diffoscope


Commits:
701d6c9f by Mattia Rizzolo at 2018-07-08T17:06:23+02:00
Move the computation of the terminal line eraser into logging.py

Signed-off-by: Mattia Rizzolo <mattia at debian.org>

- - - - -
615095a2 by Mattia Rizzolo at 2018-07-08T17:07:30+02:00
logging: always clean the line before printing a log message

Signed-off-by: Mattia Rizzolo <mattia at debian.org>

- - - - -
e75be7e7 by Mattia Rizzolo at 2018-07-08T17:07:52+02:00
main: remove terminal line cleaning, that is now taken care by the logging module

Signed-off-by: Mattia Rizzolo <mattia at debian.org>

- - - - -
fd6eff94 by Mattia Rizzolo at 2018-07-08T17:19:14+02:00
main: clean the terminal line before printing a traceback

Signed-off-by: Mattia Rizzolo <mattia at debian.org>

- - - - -
90028d41 by Mattia Rizzolo at 2018-07-08T17:49:23+02:00
comparators: do not shadow the original import errors

Fixes: MR: !7
Signed-off-by: Mattia Rizzolo <mattia at debian.org>

- - - - -
5ed8e48b by anthraxx at 2018-07-08T16:06:02+00:00
libarchive: add compatibility with python-libarchive >= 2.8

Python librarchive 2.8 removed the mtime_nsec property from
ArchiveEntry so lets wire the ffi function if available

- - - - -


5 changed files:

- diffoscope/comparators/__init__.py
- diffoscope/comparators/utils/libarchive.py
- diffoscope/logging.py
- diffoscope/main.py
- diffoscope/progress.py


Changes:

=====================================
diffoscope/comparators/__init__.py
=====================================
--- a/diffoscope/comparators/__init__.py
+++ b/diffoscope/comparators/__init__.py
@@ -19,8 +19,13 @@
 # You should have received a copy of the GNU General Public License
 # along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
 
+import sys
 import logging
 import importlib
+import traceback
+
+from ..logging import line_ereser
+
 
 logger = logging.getLogger(__name__)
 
@@ -108,6 +113,7 @@ class ComparatorManager(object):
         self.classes = []
 
         for xs in self.COMPARATORS:
+            errors = []
             for x in xs:
                 package, klass_name = x.rsplit('.', 1)
 
@@ -115,16 +121,22 @@ class ComparatorManager(object):
                     mod = importlib.import_module(
                         'diffoscope.comparators.{}'.format(package)
                     )
-                except ImportError:
+                except ImportError as e:
+                    errors.append((x, e))
                     continue
 
                 self.classes.append(getattr(mod, klass_name))
                 break
             else:  # noqa
-                raise ImportError("Could not import {}{}".format(
-                    "any of" if len(xs) > 1 else '',
+                logger.error("Could not import {}{}".format(
+                    "any of " if len(xs) > 1 else '',
                     ', '.join(xs)
                 ))
+                for x in errors:
+                    logger.error("Original error for %s:", x[0])
+                    sys.stderr.buffer.write(line_ereser())
+                    traceback.print_exception(None, x[1], x[1].__traceback__)
+                sys.exit(2)
 
         logger.debug("Loaded %d comparator classes", len(self.classes))
 


=====================================
diffoscope/comparators/utils/libarchive.py
=====================================
--- a/diffoscope/comparators/utils/libarchive.py
+++ b/diffoscope/comparators/utils/libarchive.py
@@ -80,6 +80,14 @@ if not hasattr(libarchive.ffi, 'entry_gname'):
         'entry_gname', [libarchive.ffi.c_archive_entry_p], ctypes.c_char_p)
     libarchive.ArchiveEntry.gname = property(
         lambda self: libarchive.ffi.entry_gname(self._entry_p))
+# Monkeypatch libarchive-c (>= 2.8)
+# Wire mtime_nsec attribute as some libarchive versions (>=2.8) don't expose it
+# for ArchiveEntry. Doing this allows a unified API no matter which version is
+# available.
+if not hasattr(libarchive.ArchiveEntry, 'mtime_nsec') and hasattr(libarchive.ffi, 'entry_mtime_nsec'):
+    libarchive.ArchiveEntry.mtime_nsec = property(
+        lambda self: libarchive.ffi.entry_mtime_nsec(self._entry_p))
+
 
 # Monkeypatch libarchive-c so we always get pathname as (Unicode) str
 # Otherwise, we'll get sometimes str and sometimes bytes and always pain.


=====================================
diffoscope/logging.py
=====================================
--- a/diffoscope/logging.py
+++ b/diffoscope/logging.py
@@ -17,10 +17,27 @@
 # You should have received a copy of the GNU General Public License
 # along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
 
+import sys
 import contextlib
 import logging
 
 
+def line_ereser(fd=sys.stderr) -> bytes:
+    ereser = b''  # avoid None to avoid 'NoneType + str/bytes' failures
+    if fd.isatty():
+        from curses import tigetstr, setupterm
+        setupterm(fd=fd.fileno())
+        ereser = tigetstr('el')
+
+    if not ereser and fd.isatty():
+        # is a tty, but doesn't support the proper scape code, so let's fake it
+        from shutil import get_terminal_size
+        width = get_terminal_size().columns
+        ereser = b'\r{}\r'.format(b' ' * width)
+
+    return ereser
+
+
 @contextlib.contextmanager
 def setup_logging(debug, log_handler):
     logger = logging.getLogger()
@@ -32,6 +49,7 @@ def setup_logging(debug, log_handler):
     logger.addHandler(ch)
 
     formatter = logging.Formatter(
+        line_ereser().decode('ascii') +
         '%(asctime)s %(levelname).1s: %(name)s: %(message)s',
         '%Y-%m-%d %H:%M:%S',
     )


=====================================
diffoscope/main.py
=====================================
--- a/diffoscope/main.py
+++ b/diffoscope/main.py
@@ -33,7 +33,7 @@ from .path import set_path
 from .tools import tool_prepend_prefix, tool_required, OS_NAMES, get_current_os
 from .config import Config
 from .locale import set_locale
-from .logging import setup_logging
+from .logging import line_ereser, setup_logging
 from .progress import ProgressManager, Progress
 from .profiling import ProfileManager, profile
 from .tempfiles import clean_all_temp_files
@@ -459,13 +459,12 @@ def main(args=None):
             post_parse(parsed_args)
             sys.exit(run_diffoscope(parsed_args))
     except KeyboardInterrupt:
-        if log_handler:
-            log_handler.progressbar.bar.erase_line()
         logger.info('Keyboard Interrupt')
         sys.exit(2)
     except BrokenPipeError:
         sys.exit(2)
     except Exception:
+        sys.stderr.buffer.write(line_ereser())
         traceback.print_exc()
         if parsed_args and parsed_args.debugger:
             import pdb


=====================================
diffoscope/progress.py
=====================================
--- a/diffoscope/progress.py
+++ b/diffoscope/progress.py
@@ -24,6 +24,9 @@ import json
 import signal
 import logging
 
+from .logging import line_ereser
+
+
 logger = logging.getLogger(__name__)
 
 
@@ -215,12 +218,7 @@ class ProgressBar(object):
                 kwargs.setdefault('fd', sys.stderr)
                 super().__init__(*args, **kwargs)
                 # Terminal handling after parent init since that sets self.fd
-                if self.fd.isatty():
-                    from curses import tigetstr, setupterm
-                    setupterm()
-                    self.erase_to_eol = tigetstr('el')
-                else:
-                    self.erase_to_eol = None
+                self.erase_to_eol = line_ereser(self.fd)
 
             def _need_update(self):
                 return True
@@ -228,13 +226,7 @@ class ProgressBar(object):
             def erase_line(self):
                 if self.erase_to_eol:
                     self.fd.buffer.write(self.erase_to_eol)
-                elif self.fd.isatty():
-                    print(end='\r', file=self.fd)
-                    print(' ' * self.term_width, end='', file=self.fd)
-                else:
-                    # Do not flush if nothing was written
-                    return
-                self.fd.flush()
+                    self.fd.flush()
 
             def finish(self):
                 self.finished = True



View it on GitLab: https://salsa.debian.org/reproducible-builds/diffoscope/compare/41b1a70ad8732c94a3f62dd751cdc0e0bd2be83c...5ed8e48bbb175e686f74e4a1d849986a52bec926

-- 
View it on GitLab: https://salsa.debian.org/reproducible-builds/diffoscope/compare/41b1a70ad8732c94a3f62dd751cdc0e0bd2be83c...5ed8e48bbb175e686f74e4a1d849986a52bec926
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.reproducible-builds.org/pipermail/rb-commits/attachments/20180708/5fa09d81/attachment.html>


More information about the rb-commits mailing list