[elbe-devel] [PATCH v2 4/5] Python3: harmonize binary/unicode strings

Bastian Germann bage at linutronix.de
Mon Jan 13 14:24:50 CET 2020


Am 13.12.19 um 12:45 schrieb Christian Teklenborg:
> Python 2 has binary strings as default whereas Python 3 has unicode strings.
> This requires changing the string handling at some places to explicitly use one
> or the other. This involves opening some files in binary mode and converting
> Popen streams to unicode strings.
> 
> The binascii.b2a_base64 call returns binary strings on Python 3 even though it
> could return unicode strings (base64 is ASCII). So we safely convert it via
> decode('ascii').
> 
> Signed-off-by: Christian Teklenborg <chris at linutronix.de>

Reviewed-by: Bastian Germann <bage at linutronix.de>

> ---
>  elbepack/daemons/soap/esoap.py |  8 ++++----
>  elbepack/kvm.py                | 10 ++++------
>  elbepack/log.py                |  5 ++++-
>  elbepack/shellhelper.py        |  6 ++++++
>  elbepack/soapclient.py         |  4 ++--
>  5 files changed, 20 insertions(+), 13 deletions(-)
> 
> diff --git a/elbepack/daemons/soap/esoap.py b/elbepack/daemons/soap/esoap.py
> index 468df8a5..7d76d6a3 100644
> --- a/elbepack/daemons/soap/esoap.py
> +++ b/elbepack/daemons/soap/esoap.py
> @@ -159,7 +159,7 @@ class ESoap (ServiceBase):
>                  self.app.pm.set_current_project_xml(uid, fn)
>              return -2
>  
> -        with open(fn, 'a') as fp:
> +        with open(fn, 'ab') as fp:
>              fp.write(binascii.a2b_base64(blob))
>  
>          return part + 1
> @@ -264,7 +264,7 @@ class ESoap (ServiceBase):
>          cdrom_fname = os.path.join(builddir, "uploaded_cdrom.iso")
>  
>          # Now append data to cdrom_file
> -        fp = open(cdrom_fname, "a")
> +        fp = open(cdrom_fname, "ab")
>          fp.write(binascii.a2b_base64(data))
>          fp.close()
>  
> @@ -297,7 +297,7 @@ class ESoap (ServiceBase):
>          pdebuild_fname = os.path.join(builddir, "current_pdebuild.tar.gz")
>  
>          # Now write empty File
> -        fp = open(pdebuild_fname, "a")
> +        fp = open(pdebuild_fname, "ab")
>          fp.write(binascii.a2b_base64(data))
>          fp.close()
>  
> @@ -331,7 +331,7 @@ class ESoap (ServiceBase):
>          orig_fname = os.path.join(builddir, self.app.pm.get_orig_fname(uid))
>  
>          # Now append to File
> -        fp = open(orig_fname, "a")
> +        fp = open(orig_fname, "ab")
>          fp.write(binascii.a2b_base64(data))
>          fp.close()
>  
> diff --git a/elbepack/kvm.py b/elbepack/kvm.py
> index 62f2ddeb..8ea0e6dd 100644
> --- a/elbepack/kvm.py
> +++ b/elbepack/kvm.py
> @@ -6,7 +6,8 @@
>  # SPDX-License-Identifier: GPL-3.0-or-later
>  
>  import os
> -import subprocess
> +
> +from elbepack.shellhelper import command_out
>  
>  kvm_exe_list = [
>      '/usr/bin/kvm',
> @@ -21,11 +22,8 @@ def find_kvm_exe():
>      for fname in kvm_exe_list:
>          if os.path.isfile(fname) and os.access(fname, os.X_OK):
>              # determine kvm version
> -            cmd = subprocess.Popen(
> -                fname + ' --version',
> -                shell=True,
> -                stdout=subprocess.PIPE)
> -            for line in cmd.stdout:
> +            _, stdout = command_out(fname + ' --version')
> +            for line in stdout.splitlines():
>                  if "version" in line:
>                      version = line.split()[3].split('(')[0].strip()
>  
> diff --git a/elbepack/log.py b/elbepack/log.py
> index 43e04985..bffc6c1d 100644
> --- a/elbepack/log.py
> +++ b/elbepack/log.py
> @@ -11,6 +11,7 @@ import select
>  import threading
>  from contextlib import contextmanager
>  
> +from io import TextIOWrapper, BytesIO
>  
>  root = logging.getLogger()
>  root.setLevel(logging.DEBUG)
> @@ -241,7 +242,7 @@ class AsyncLogging(object):
>  
>      def run(self):
>          alive = True
> -        rest = ""
> +        rest = bytes()
>          while alive:
>              events = self.epoll.poll()
>              for _, event in events:
> @@ -256,6 +257,8 @@ class AsyncLogging(object):
>              if not rest:
>                  break
>  
> +        rest = TextIOWrapper(BytesIO(rest), encoding='utf-8', errors='replace').read()
> +
>          if self.lines:
>              self.lines[-1] += rest
>              self.block.info("\n".join(self.lines))
> diff --git a/elbepack/shellhelper.py b/elbepack/shellhelper.py
> index 0895c0b0..c73642c7 100644
> --- a/elbepack/shellhelper.py
> +++ b/elbepack/shellhelper.py
> @@ -12,6 +12,7 @@ from subprocess import Popen, PIPE, STDOUT, call
>  
>  from elbepack.log import async_logging
>  
> +from io import TextIOWrapper, BytesIO
>  
>  log = logging.getLogger("log")
>  soap = logging.getLogger("soap")
> @@ -54,6 +55,8 @@ def command_out(cmd, stdin=None, output=PIPE, env_add=None):
>                    stdout=output, stderr=STDOUT, stdin=PIPE, env=new_env)
>          out, _ = p.communicate(input=stdin)
>  
> +    out = TextIOWrapper(BytesIO(out), encoding='utf-8', errors='replace').read()
> +
>      return p.returncode, out
>  
>  
> @@ -81,6 +84,9 @@ def command_out_stderr(cmd, stdin=None, env_add=None):
>                    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
>  
>  
> diff --git a/elbepack/soapclient.py b/elbepack/soapclient.py
> index c654e410..cb8dbd8f 100644
> --- a/elbepack/soapclient.py
> +++ b/elbepack/soapclient.py
> @@ -87,7 +87,7 @@ class ElbeSoapClient(object):
>          self.service.login(user, passwd)
>  
>      def download_file(self, builddir, filename, dst_fname):
> -        fp = open(dst_fname, "w")
> +        fp = open(dst_fname, "wb")
>          part = 0
>  
>          # XXX the retry logic might get removed in the future, if the error
> @@ -327,7 +327,7 @@ class SetXmlAction(ClientAction):
>          part = 0
>          with open(filename, "rb") as fp:
>              while True:
> -                xml_base64 = binascii.b2a_base64(fp.read(size))
> +                xml_base64 = binascii.b2a_base64(fp.read(size)).decode('ascii')
>                  # finish upload
>                  if len(xml_base64) == 1:
>                      part = client.service.upload_file(builddir,
> 



More information about the elbe-devel mailing list