[Debian-med-packaging] Bug#1008402: khmer: FTBFS: dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.10 3.9" returned exit code 13

Stefano Rivera stefanor at debian.org
Sun Apr 3 00:03:04 BST 2022


Hi Lucas (2022.03.26_17:21:07_-0400)
> > self = FileType('wb'), string = '-'
> > 
> >     def __call__(self, string):
> >         # the special argument "-" means sys.std{in,out}
> >         if string == '-':
> >             if 'r' in self._mode:
> >                 return _sys.stdin.buffer if 'b' in self._mode else _sys.stdin
> >             elif any(c in self._mode for c in 'wax'):
> > >               return _sys.stdout.buffer if 'b' in self._mode else _sys.stdout
> > E               AttributeError: '_io.StringIO' object has no attribute 'buffer'

I assume the big relevant change here is
https://bugs.python.org/issue14156 being fixed

I experimented a little and got to this patch, but it isn't complete
yet.

SR

-- 
Stefano Rivera
  http://tumbleweed.org.za/
-------------- next part --------------
--- a/tests/khmer_tst_utils.py
+++ b/tests/khmer_tst_utils.py
@@ -44,18 +44,13 @@
 import sys
 import traceback
 import subprocess
-from io import open  # pylint: disable=redefined-builtin
+from io import BufferedWriter, BytesIO, StringIO, TextIOWrapper
 from hashlib import md5
 
 from khmer import reverse_complement as revcomp
 
 import pytest
 
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import StringIO
-
 
 def _equals_rc(query, match):
     return (query == match) or (revcomp(query) == match)
@@ -151,6 +146,25 @@
     return -1
 
 
+class StdIOBuffer(TextIOWrapper):
+    '''Replacement for writable io.StringIO that behaves more like real file
+    Unlike StringIO, provides a buffer attribute that holds the underlying
+    binary data, allowing it to replace sys.stdout/sys.stderr in more
+    contexts.
+    '''
+
+    name = 'StdIOBuffer'
+
+    def __init__(self, initial_value='', newline='\n'):
+        initial_value = initial_value.encode('utf-8')
+        super().__init__(BufferedWriter(BytesIO(initial_value)),
+                         'utf-8', newline=newline)
+
+    def getvalue(self):
+        self.flush()
+        return self.buffer.raw.getvalue().decode('utf-8')
+
+
 def runscript(scriptname, args, in_directory=None,
               fail_ok=False, sandbox=False):
     """Run a Python script using exec().
@@ -172,9 +186,8 @@
         sys.argv = sysargs
 
         oldout, olderr = sys.stdout, sys.stderr
-        sys.stdout = StringIO()
-        sys.stdout.name = "StringIO"
-        sys.stderr = StringIO()
+        sys.stdout = StdIOBuffer()
+        sys.stderr = StdIOBuffer()
 
         if in_directory:
             os.chdir(in_directory)
--- a/khmer/khmer_args.py
+++ b/khmer/khmer_args.py
@@ -158,14 +158,16 @@
 
 # Temporary fix to argparse FileType which ignores the
 # binary mode flag. Upstream bug tracked in https://bugs.python.org/issue14156
+# Fixed in 3.9.12 and 3.10.3.
 # pylint: disable=too-few-public-methods,missing-docstring
 class FileType(argparse.FileType):
     def __call__(self, fname):
         # detect if stdout is being faked (StringIO during unit tests) in
         # which case we do not have to do anything
         if (fname == '-' and
-                sys.version_info.major == 3 and
-                not isinstance(sys.stdout, StringIO)):
+                not isinstance(sys.stdout, StringIO) and
+                (sys.version_info < (3, 9, 12) or
+                 (3, 10) < sys.version_info < (3, 10, 3))):
             if 'r' in self._mode:
                 fname = sys.stdin.fileno()
             elif 'w' in self._mode:
--- a/khmer/kfile.py
+++ b/khmer/kfile.py
@@ -209,6 +209,8 @@
     """Take in a file object and checks to see if it's a block or fifo."""
     if fthing is sys.stdout or fthing is sys.stdin:
         return True
+    elif not hasattr(fthing, 'name'):
+        return True
     else:
         mode = os.stat(fthing.name).st_mode
         return S_ISBLK(mode) or S_ISCHR(mode)
--- a/scripts/trim-low-abund.py
+++ b/scripts/trim-low-abund.py
@@ -512,7 +512,7 @@
 
     if args.output is None:
         log_info('output in *.abundtrim')
-    elif args.output.name == 1:
+    elif not hasattr(args.output, 'name') or args.output.name == 1:
         log_info('output streamed to stdout')
     elif args.output.name:
         log_info('output in {}'.format(args.output.name))


More information about the Debian-med-packaging mailing list