]> git.apps.os.sepia.ceph.com Git - teuthology.git/commitdiff
py3: get rid of cStringIO
authorKyr Shatskyy <kyrylo.shatskyy@suse.com>
Sat, 14 Mar 2020 23:33:17 +0000 (00:33 +0100)
committerKyr Shatskyy <kyrylo.shatskyy@suse.com>
Sun, 15 Mar 2020 00:35:24 +0000 (01:35 +0100)
Signed-off-by: Kyr Shatskyy <kyrylo.shatskyy@suse.com>
19 files changed:
scripts/test/script.py
teuthology/kill.py
teuthology/misc.py
teuthology/orchestra/remote.py
teuthology/orchestra/run.py
teuthology/orchestra/test/test_remote.py
teuthology/orchestra/test/test_run.py
teuthology/packaging.py
teuthology/provision/cloud/base.py
teuthology/provision/cloud/util.py
teuthology/repo_utils.py
teuthology/suite/placeholder.py
teuthology/suite/run.py
teuthology/suite/test/test_run_.py
teuthology/task/__init__.py
teuthology/task/install/deb.py
teuthology/task/mpi.py
teuthology/task/pcp.py
teuthology/task/selinux.py

index 43f24548cbb1316d375b25a9dcd44af85801d648..db88f8f5eef5e7b446bbdd942fb55061b6854e8a 100644 (file)
@@ -1,5 +1,6 @@
 import subprocess
 from pytest import raises
+from six import ensure_str
 
 
 class Script(object):
@@ -7,7 +8,7 @@ class Script(object):
 
     def test_help(self):
         args = (self.script_name, '--help')
-        out = subprocess.check_output(args)
+        out = ensure_str(subprocess.check_output(args))
         assert out.startswith('usage')
 
     def test_invalid(self):
index c6fd61293aaa7f40cbf0566a43a4f448a4ecc126..f61e6a150b985249dadc86c3efda56cb5f38608c 100755 (executable)
@@ -8,6 +8,8 @@ import tempfile
 import logging
 import getpass
 
+from six import ensure_str
+
 from teuthology import beanstalk
 from teuthology import report
 from teuthology.config import config
@@ -220,7 +222,7 @@ def nuke_targets(targets_dict, owner):
     for target in targets:
         to_nuke.append(misc.decanonicalize_hostname(target))
 
-    target_file = tempfile.NamedTemporaryFile(delete=False)
+    target_file = tempfile.NamedTemporaryFile(delete=False, mode='w+t')
     target_file.write(yaml.safe_dump(targets_dict))
     target_file.close()
 
@@ -238,9 +240,9 @@ def nuke_targets(targets_dict, owner):
         nuke_args,
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT)
-    for line in iter(proc.stdout.readline, ''):
-        line = line.replace('\r', '').replace('\n', '')
-        log.info(line)
+    for line in iter(proc.stdout.readline, b''):
+        line = line.replace(b'\r', b'').replace(b'\n', b'')
+        log.info(ensure_str(line))
         sys.stdout.flush()
 
     os.unlink(target_file.name)
index 46847bfe0191788284740495ca8d25b23991f911..1ab68f009e3450aaa5f953fa1dd60722e70cb68f 100644 (file)
@@ -29,7 +29,7 @@ from teuthology.config import config
 from teuthology.contextutil import safe_while
 from teuthology.orchestra.opsys import DEFAULT_OS_VERSION
 
-from six import reraise
+from six import (reraise, ensure_str)
 
 log = logging.getLogger(__name__)
 
@@ -647,7 +647,7 @@ def remove_lines_from_file(remote, path, line_is_valid_test,
     on when the main site goes up and down.
     """
     # read in the specified file
-    in_data = get_file(remote, path, False)
+    in_data = ensure_str(get_file(remote, path, False))
     out_data = ""
 
     first_line = True
@@ -685,7 +685,7 @@ def append_lines_to_file(remote, path, lines, sudo=False):
 
     temp_file_path = remote.mktemp()
 
-    data = get_file(remote, path, sudo)
+    data = ensure_str(get_file(remote, path, sudo))
 
     # add the additional data and write it back out, using a temp file
     # in case of connectivity of loss, and then mv it to the
@@ -705,7 +705,7 @@ def prepend_lines_to_file(remote, path, lines, sudo=False):
 
     temp_file_path = remote.mktemp()
 
-    data = get_file(remote, path, sudo)
+    data = ensure_str(get_file(remote, path, sudo))
 
     # add the additional data and write it back out, using a temp file
     # in case of connectivity of loss, and then mv it to the
@@ -810,7 +810,7 @@ def get_scratch_devices(remote):
     """
     devs = []
     try:
-        file_data = get_file(remote, "/scratch_devs")
+        file_data = ensure_str(get_file(remote, "/scratch_devs"))
         devs = file_data.split()
     except Exception:
         devs = remote.sh('ls /dev/[sv]d?').strip().split('\n')
@@ -1136,11 +1136,11 @@ def _ssh_keyscan(hostname):
     )
     p.wait()
     for line in p.stderr.readlines():
-        line = line.strip()
+        line = ensure_str(line.strip())
         if line and not line.startswith('#'):
             log.error(line)
     for line in p.stdout.readlines():
-        host, key = line.strip().split(' ', 1)
+        host, key = ensure_str(line.strip()).split(' ', 1)
         return key
 
 
@@ -1310,15 +1310,16 @@ def sh(command, log_limit=1024, cwd=None, env=None):
     truncated = False
     with proc.stdout:
         for line in iter(proc.stdout.readline, b''):
+            line = ensure_str(line)
             lines.append(line)
             line = line.strip()
             if len(line) > log_limit:
                 truncated = True
-                log.debug(str(line)[:log_limit] +
+                log.debug(line[:log_limit] +
                           "... (truncated to the first " + str(log_limit) +
                           " characters)")
             else:
-                log.debug(str(line))
+                log.debug(line)
     output = "".join(lines)
     if proc.wait() != 0:
         if truncated:
@@ -1331,4 +1332,4 @@ def sh(command, log_limit=1024, cwd=None, env=None):
             cmd=command,
             output=output
         )
-    return output.decode('utf-8')
+    return output
index 721d809ce0972e30b7746570fbcf03059bf30741..f03447d9adf52b2689341e4c0a4c15bd4f2e4ee4 100644 (file)
@@ -1,6 +1,9 @@
 """
 Support for paramiko remote objects.
 """
+
+from six import ensure_str
+
 import teuthology.lock.query
 import teuthology.lock.util
 from teuthology.orchestra import run
@@ -13,7 +16,7 @@ from teuthology.misc import host_shortname
 import time
 import re
 import logging
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import pwd
 import tempfile
@@ -236,12 +239,12 @@ class Remote(object):
             remote_date = remote.sh('date')
         """
         if 'stdout' not in kwargs:
-            kwargs['stdout'] = StringIO()
+            kwargs['stdout'] = BytesIO()
         if 'args' not in kwargs:
             kwargs['args'] = script
         proc=self.run(**kwargs)
-        return proc.stdout.getvalue()
-
+        out=proc.stdout.getvalue()
+        return ensure_str(out)
 
     def sh_file(self, script, label="script", sudo=False, **kwargs):
         """
index 8992ec31b79043cf42398aad947c5d09abb0907c..4cb5f94203d0ba917bfa25c5d19c3b7e008ed660 100644 (file)
@@ -1,7 +1,9 @@
 """
 Paramiko run support
 """
-from cStringIO import StringIO
+
+import io
+
 from paramiko import ChannelFile
 
 import gevent
@@ -11,6 +13,8 @@ import pipes
 import logging
 import shutil
 
+from teuthology.util.compat import PY3
+
 from teuthology.contextutil import safe_while
 from teuthology.exceptions import (CommandCrashedError, CommandFailedError,
                                    ConnectionLostError)
@@ -268,15 +272,39 @@ def copy_to_log(f, logger, loglevel=logging.INFO, capture=None):
     # Work-around for http://tracker.ceph.com/issues/8313
     if isinstance(f, ChannelFile):
         f._flags += ChannelFile.FLAG_BINARY
-
     for line in f:
         if capture:
-            capture.write(line)
+            #out = ensure_str(line)
+            if PY3:
+                if isinstance(line, str):
+                    out = line.encode()
+                else:
+                    out = line.decode()
+                if isinstance(capture, io.StringIO):
+                    capture.write(out)
+                elif isinstance(capture, io.BytesIO):
+                    capture.write(out.encode())
+            else:
+                if isinstance(line, str):
+                    out = line.decode()
+                else:
+                    out = line.encode()
+                if isinstance(capture, io.StringIO):
+                    capture.write(out)
+                elif isinstance(capture, io.BytesIO):
+                    capture.write(out.encode())
+                else:
+                    # isinstance does not work with cStringIO.StringIO and
+                    # fails with error:
+                    #   TypeError: isinstance() arg 2 must be a class, type,
+                    #   or tuple of classes and types
+                    capture.write(out.encode())
         line = line.rstrip()
         # Second part of work-around for http://tracker.ceph.com/issues/8313
         try:
-            line = unicode(line, 'utf-8', 'replace').encode('utf-8')
-            logger.log(loglevel, line.decode('utf-8'))
+            if isinstance(line, bytes):
+                line = line.decode('utf-8', 'replace')
+            logger.log(loglevel, line)
         except (UnicodeDecodeError, UnicodeEncodeError):
             logger.exception("Encountered unprintable line in command output")
 
@@ -286,8 +314,13 @@ def copy_and_close(src, fdst):
     copyfileobj call wrapper.
     """
     if src is not None:
-        if isinstance(src, basestring):
-            src = StringIO(src)
+        if isinstance(src, bytes):
+            src = io.BytesIO(src)
+        elif isinstance(src, str):
+            if PY3:
+                src = io.StringIO(src)
+            else:
+                src = io.BytesIO(src)
         shutil.copyfileobj(src, fdst)
     fdst.close()
 
index 6a77201634fedd6472125157ff7e8b9060256ce6..9a94bfc43c51ba734a0e7bb6610e1e1784511865 100644 (file)
@@ -1,6 +1,6 @@
 from mock import patch, Mock, MagicMock
 
-from cStringIO import StringIO
+from io import BytesIO
 
 from teuthology.orchestra import remote
 from teuthology.orchestra import opsys
@@ -74,7 +74,7 @@ class TestRemote(object):
             'hostname',
             '--fqdn',
             ]
-        stdout = StringIO('test_hostname')
+        stdout = BytesIO(b'test_hostname')
         stdout.seek(0)
         proc = RemoteProcess(
             client=self.m_ssh,
@@ -97,7 +97,7 @@ class TestRemote(object):
             'uname',
             '-m',
             ]
-        stdout = StringIO('test_arch')
+        stdout = BytesIO(b'test_arch')
         stdout.seek(0)
         proc = RemoteProcess(
             client=self.m_ssh,
@@ -116,7 +116,7 @@ class TestRemote(object):
         assert m_run.called_once_with(
             client=self.m_ssh,
             args=args,
-            stdout=StringIO(),
+            stdout=BytesIO(),
             name=r.shortname,
         )
         assert r.arch == 'test_arch'
index acbf85514d2f4d54ea880c8f0ca5188e1c4e27f1..f87909cf211d53928940eda465b4f890777249c2 100644 (file)
@@ -1,4 +1,4 @@
-from StringIO import StringIO
+from io import BytesIO
 
 import paramiko
 import socket
@@ -6,20 +6,23 @@ import socket
 from mock import MagicMock, patch
 from pytest import raises
 
+from six import ensure_str, ensure_binary
+
 from teuthology.orchestra import run
 from teuthology.exceptions import (CommandCrashedError, CommandFailedError,
                                    ConnectionLostError)
 
-
 def set_buffer_contents(buf, contents):
     buf.seek(0)
-    if isinstance(contents, basestring):
+    if isinstance(contents, bytes):
         buf.write(contents)
     elif isinstance(contents, (list, tuple)):
         buf.writelines(contents)
+    elif isinstance(contents, str):
+        buf.write(ensure_binary(contents))
     else:
         raise TypeError(
-            "% is is a %s; should be a string, list or tuple" % (
+            "%s is a %s; should be a byte string, list or tuple" % (
                 contents, type(contents)
             )
         )
@@ -46,7 +49,7 @@ class TestRun(object):
         self.m_stdout_buf = self.m_channelfile(self.m_channel())
         self.m_stderr_buf = self.m_channelfile(self.m_channel())
         """
-        class M_ChannelFile(StringIO):
+        class M_ChannelFile(BytesIO):
             channel = MagicMock(spec=paramiko.Channel)()
 
         self.m_channelfile = M_ChannelFile
@@ -99,29 +102,29 @@ class TestRun(object):
         output = 'foo\nbar'
         set_buffer_contents(self.m_stdout_buf, output)
         self.m_stdout_buf.channel.recv_exit_status.return_value = 0
-        stdout = StringIO()
+        stdout = BytesIO()
         proc = run.run(
             client=self.m_ssh,
             args=['foo', 'bar baz'],
             stdout=stdout,
         )
         assert proc.stdout is stdout
-        assert proc.stdout.read() == output
-        assert proc.stdout.getvalue() == output
+        assert ensure_str(proc.stdout.read()) == output
+        assert ensure_str(proc.stdout.getvalue()) == output
 
     def test_capture_stderr_newline(self):
         output = 'foo\nbar\n'
         set_buffer_contents(self.m_stderr_buf, output)
         self.m_stderr_buf.channel.recv_exit_status.return_value = 0
-        stderr = StringIO()
+        stderr = BytesIO()
         proc = run.run(
             client=self.m_ssh,
             args=['foo', 'bar baz'],
             stderr=stderr,
         )
         assert proc.stderr is stderr
-        assert proc.stderr.read() == output
-        assert proc.stderr.getvalue() == output
+        assert ensure_str(proc.stderr.read()) == output
+        assert ensure_str(proc.stderr.getvalue()) == output
 
     def test_status_bad(self):
         self.m_stdout_buf.channel.recv_exit_status.return_value = 42
@@ -223,7 +226,7 @@ class TestRun(object):
 
     def test_stdout_pipe(self):
         self.m_stdout_buf.channel.recv_exit_status.return_value = 0
-        lines = ['one\n', 'two', '']
+        lines = [b'one\n', b'two', b'']
         set_buffer_contents(self.m_stdout_buf, lines)
         proc = run.run(
             client=self.m_ssh,
@@ -241,7 +244,7 @@ class TestRun(object):
 
     def test_stderr_pipe(self):
         self.m_stdout_buf.channel.recv_exit_status.return_value = 0
-        lines = ['one\n', 'two', '']
+        lines = [b'one\n', b'two', b'']
         set_buffer_contents(self.m_stderr_buf, lines)
         proc = run.run(
             client=self.m_ssh,
index 5ea9bc2958d590d78062381a62587474115fdfac..22eddfb4565bc4031b44dc4b417befdfe606aaf4 100644 (file)
@@ -6,8 +6,11 @@ import requests
 from teuthology.util.compat import urljoin, urlencode
 
 from collections import OrderedDict
-from cStringIO import StringIO
-
+from teuthology.util.compat import PY3
+if PY3:
+    from io import StringIO
+else:
+    from io import BytesIO as StringIO
 from teuthology import repo_utils
 
 from teuthology.config import config
index e06972e072dac12ed68869b07fef44cb964b27ac..fd2ef972a2729477105b338dcb8112eee02e4c5f 100644 (file)
@@ -1,5 +1,6 @@
 import logging
 from copy import deepcopy
+from six import string_types as basestring
 
 from libcloud.compute.providers import get_driver
 from libcloud.compute.types import Provider as lc_Provider
@@ -8,7 +9,6 @@ import teuthology.orchestra.remote
 import teuthology.provision.cloud
 from teuthology.misc import canonicalize_hostname, decanonicalize_hostname
 
-
 log = logging.getLogger(__name__)
 
 
index b5345cb45b3505e410a7a57579c11d8019073e66..c8170a87d4e98427f1ddbef63dc4f2c07c61c909 100644 (file)
@@ -4,15 +4,16 @@ import dateutil.parser
 import json
 import os
 
-from teuthology.util.flock import FileLock
+from six import ensure_str
 
+from teuthology.util.flock import FileLock
 
 def get_user_ssh_pubkey(path='~/.ssh/id_rsa.pub'):
     full_path = os.path.expanduser(path)
     if not os.path.exists(full_path):
         return
     with open(full_path, 'rb') as f:
-        return f.read().strip()
+        return ensure_str(f.read()).strip()
 
 
 def combine_dicts(list_of_dicts, func):
index 20910fc27a3cc7624aff3a2e24ab972c9316b2a8..a9c391fee85a19e1363aefa3cbe0f544e43ae64f 100644 (file)
@@ -3,6 +3,9 @@ import os
 import re
 import shutil
 import subprocess
+
+from six import ensure_str
+
 import time
 
 from teuthology import misc
@@ -60,10 +63,12 @@ def ls_remote(url, ref):
 
     :returns: The sha1 if found; else None
     """
+    sha1 = None
     cmd = "git ls-remote {} {}".format(url, ref)
     result = subprocess.check_output(
         cmd, shell=True).split()
-    sha1 = result[0] if result else None
+    if result:
+        sha1 = ensure_str(result[0])
     log.debug("{} -> {}".format(cmd, sha1))
     return sha1
 
@@ -127,7 +132,7 @@ def clone_repo(repo_url, dest_path, branch, shallow=True):
         stderr=subprocess.STDOUT)
 
     not_found_str = "Remote branch %s not found" % branch
-    out = proc.stdout.read()
+    out = ensure_str(proc.stdout.read())
     result = proc.wait()
     # Newer git versions will bail if the branch is not found, but older ones
     # will not. Fortunately they both output similar text.
@@ -224,7 +229,7 @@ def fetch(repo_path):
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT)
     if proc.wait() != 0:
-        out = proc.stdout.read()
+        out = ensure_str(proc.stdout.read())
         log.error(out)
         raise GitError("git fetch failed!")
 
@@ -252,7 +257,7 @@ def fetch_branch(repo_path, branch, shallow=True):
         stderr=subprocess.STDOUT)
     if proc.wait() != 0:
         not_found_str = "fatal: couldn't find remote ref %s" % branch
-        out = proc.stdout.read()
+        out = ensure_str(proc.stdout.read())
         log.error(out)
         if not_found_str in out.lower():
             raise BranchNotFoundError(branch)
index 9af2ffb78e865b55fba1a5a8204bdcd21cb47173..bdf9cf929b35be956958dd58d9e05bb6dfddb0be 100644 (file)
@@ -27,7 +27,7 @@ def substitute_placeholders(input_dict, values_dict):
     input_dict = copy.deepcopy(input_dict)
 
     def _substitute(input_dict, values_dict):
-        for key, value in input_dict.items():
+        for key, value in list(input_dict.items()):
             if isinstance(value, dict):
                 _substitute(value, values_dict)
             elif isinstance(value, Placeholder):
index 4aa3cf2ada5cb957261aeea41baaa7414d18adbf..6d216dfa1815f4e5cacd2d233c3137d9504507b5 100644 (file)
@@ -361,7 +361,7 @@ class Run(object):
             base_frag_paths = [
                 util.strip_fragment_path(x) for x in fragment_paths
             ]
-            limit = self.args.limit
+            limit = self.args.limit or 0
             if limit > 0 and len(jobs_to_schedule) >= limit:
                 log.info(
                     'Stopped after {limit} jobs due to --limit={limit}'.format(
@@ -548,7 +548,7 @@ class Run(object):
             log.debug("Base job config:\n%s" % self.base_config)
 
         with open(base_yaml_path, 'w+b') as base_yaml:
-            base_yaml.write(str(self.base_config))
+            base_yaml.write(str(self.base_config).encode())
 
         if jobs_to_schedule:
             self.write_rerun_memo()
index b89a710d9ddd751146bcd44c21264361418b1df6..503b25b37378e6f9d46e6262e3ac0c6cb7c2459f 100644 (file)
@@ -6,7 +6,13 @@ import contextlib
 
 from datetime import datetime
 from mock import patch, call, ANY, DEFAULT
-from StringIO import StringIO
+from teuthology.util.compat import PY3
+if PY3:
+    from io import StringIO
+    from io import BytesIO
+else:
+    from io import BytesIO as StringIO
+    from io import BytesIO
 
 from teuthology.config import config, YamlConfig
 from teuthology.exceptions import ScheduleFailError
@@ -201,7 +207,7 @@ class TestScheduleSuite(object):
     @patch('teuthology.suite.util.has_packages_for_distro')
     @patch('teuthology.suite.util.get_package_versions')
     @patch('teuthology.suite.util.get_install_task_flavor')
-    @patch('__builtin__.open')
+    @patch('teuthology.suite.run.open')
     @patch('teuthology.suite.run.build_matrix')
     @patch('teuthology.suite.util.git_ls_remote')
     @patch('teuthology.suite.util.package_version_for_hash')
@@ -236,7 +242,7 @@ class TestScheduleSuite(object):
         m_open.side_effect = [
             StringIO(frag1_read_output),
             StringIO(frag2_read_output),
-            contextlib.closing(StringIO())
+            contextlib.closing(BytesIO())
         ]
         m_get_install_task_flavor.return_value = 'basic'
         m_get_package_versions.return_value = dict()
@@ -277,7 +283,7 @@ class TestScheduleSuite(object):
     @patch('teuthology.suite.util.has_packages_for_distro')
     @patch('teuthology.suite.util.get_package_versions')
     @patch('teuthology.suite.util.get_install_task_flavor')
-    @patch('__builtin__.open', create=True)
+    @patch('teuthology.suite.run.open', create=True)
     @patch('teuthology.suite.run.build_matrix')
     @patch('teuthology.suite.util.git_ls_remote')
     @patch('teuthology.suite.util.package_version_for_hash')
@@ -332,7 +338,7 @@ class TestScheduleSuite(object):
     @patch('teuthology.suite.util.has_packages_for_distro')
     @patch('teuthology.suite.util.get_package_versions')
     @patch('teuthology.suite.util.get_install_task_flavor')
-    @patch('__builtin__.open', create=True)
+    @patch('teuthology.suite.run.open', create=True)
     @patch('teuthology.suite.run.build_matrix')
     @patch('teuthology.suite.util.git_ls_remote')
     @patch('teuthology.suite.util.package_version_for_hash')
@@ -369,7 +375,7 @@ class TestScheduleSuite(object):
         m_open.side_effect = [
             StringIO('field: val\n') for i in range(NUM_FAILS+1)
         ] + [
-            contextlib.closing(StringIO())
+            contextlib.closing(BytesIO())
         ] 
         m_get_install_task_flavor.return_value = 'basic'
         m_get_package_versions.return_value = dict()
index d21ff509e8f6436c3a14c3dc21687700499b2e4d..7bbf6c5e8b02255d09e338aed4170275ba2a7ec5 100644 (file)
@@ -1,5 +1,7 @@
 import logging
 
+from six import string_types as basestring
+
 from teuthology.misc import deep_merge
 from teuthology.orchestra.cluster import Cluster
 
index be4f344da466f896a0478943db69fa22f4ea9c91..0a31b0d11edbf88bace99a090a45b882492c8c38 100644 (file)
@@ -1,7 +1,7 @@
 import logging
 import os
 
-from cStringIO import StringIO
+from io import StringIO
 
 from teuthology.orchestra import run
 
index 4a752b121351403f7a6197bda3e83295cb0bf3d1..b6348c02ed6fb17bdc9e358650ab78ee1f9722a3 100644 (file)
@@ -6,6 +6,7 @@ import logging
 import re
 
 from teuthology import misc as teuthology
+from six import string_types as basestring
 
 log = logging.getLogger(__name__)
 
index 53dcd51f2a74b199814f6115feebbf3f8406e7a1..60aceab8aef02dcddfa53d94fca1444da0b3a0a3 100644 (file)
@@ -14,6 +14,8 @@ from teuthology.orchestra import run
 
 from teuthology import misc
 
+from six import string_types as basestring
+
 from teuthology.task import Task
 
 log = logging.getLogger(__name__)
index bf699f63df9e9e746c5b6ffef9311543c31ba38e..27009073a9c2fb05467ef5d70a2794e83ff54654 100644 (file)
@@ -1,7 +1,7 @@
 import logging
 import os
 
-from cStringIO import StringIO
+from io import StringIO
 
 from teuthology.exceptions import SELinuxError
 from teuthology.misc import get_archive_dir