#414 Python 3 support for tests
Merged 7 years ago by kparal. Opened 7 years ago by churchyard.
taskotron/ churchyard/libtaskotron py3tox  into  develop

@@ -50,7 +50,7 @@ 

      subject_handler = infer_subject_handler(mod)

      try:

          subjects = subject_handler(mod)

-     except exc.TaskotronError, e:

+     except exc.TaskotronError as e:

          mod.fail_json(msg=e.msg)

  

      mod.exit_json(msg="Successfuly acquired subjects", changed=True, subjects=subjects)

@@ -37,7 +37,7 @@ 

      try:

          kojidirective = KojiDirective()

          data = kojidirective.process(mod)

-     except exc.TaskotronError, e:

+     except exc.TaskotronError as e:

          mod.fail_json(msg=e)

  

      subjects = ' '.join(data['downloaded_rpms'])

@@ -1,3 +1,4 @@ 

+ from __future__ import print_function

  import ast

  from libtaskotron.ext.fedora.koji_utils import KojiClient

  from libtaskotron.ext.fedora import rpm_utils

file modified
+11 -10
@@ -17,6 +17,7 @@ 

  # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

  #

  

+ from __future__ import print_function

  import os

  import glob

  import sys
@@ -108,7 +109,7 @@ 

          f.write(text.encode('utf-8'))

          f.close()

      else:

-         print text

+         print(text)

  

  

  def list_modules(module_dir):
@@ -241,7 +242,7 @@ 

      if os.path.basename(fname)[-3:] != '.py':

          return

  

-     print "rendering: %s" % module

+     print("rendering: %s" % module)

  

      doc, examples = get_docstring(fname, verbose=options.verbose)

  
@@ -283,7 +284,7 @@ 

              del doc['version_added']

  

      if 'parameters' in doc:

-         for (k, v) in doc['parameters'].iteritems():

+         for (k, v) in doc['parameters'].items():

              all_keys.append(k)

          all_keys = sorted(all_keys)

          doc['option_keys'] = all_keys
@@ -337,8 +338,8 @@ 

      category_file_path = os.path.join(options.output_dir,

                                        "list_of_%s_modules.rst" % category)

      category_file = open(category_file_path, "w")

-     print "*** recording category %s in %s ***" \

-           % (category, category_file_path)

+     print("*** recording category %s in %s ***" \

+           % (category, category_file_path))

  

      category = category.replace("_", " ")

      category = category.title()
@@ -445,14 +446,14 @@ 

      ''' validate option parser options '''

  

      if not options.module_dir:

-         print >>sys.stderr, "--module-dir is required"

+         print("--module-dir is required", file=sys.stderr)

          sys.exit(1)

      if not os.path.exists(options.module_dir):

-         print >>sys.stderr, "--module-dir does not exist: %s" \

-             % options.module_dir

+         print("--module-dir does not exist: %s" \

+             % options.module_dir, file=sys.stderr)

          sys.exit(1)

      if not options.template_dir:

-         print "--template-dir must be specified"

+         print("--template-dir must be specified")

          sys.exit(1)

  

  
@@ -522,7 +523,7 @@ 

          traceback.print_exc()  # temp

          if verbose is True:

              traceback.print_exc()

-             print "unable to parse %s" % filename

+             print("unable to parse %s" % filename)

      return doc, plainexamples

  

  if __name__ == '__main__':

file modified
+1
@@ -1,6 +1,7 @@ 

  #! /usr/bin/env python

  # encoding: utf-8

  

+ from __future__ import print_function

  import os

  import codecs

  import re

file modified
+1 -1
@@ -31,7 +31,7 @@ 

      meta = ['noarch', 'src']

  

      #: all known architectures

-     known = sorted(set(binary.keys() + list(itertools.chain(*binary.values())) + meta))

+     known = sorted(set(list(binary.keys()) + list(itertools.chain(*binary.values())) + meta))

  

  

  def basearch(arch=None):

@@ -22,7 +22,7 @@ 

          try:

              builder, buildid = jobid.split('/')

              return (builder, buildid)

-         except ValueError, e:

+         except ValueError as e:

              log.debug(e)

              log.warning(

                  'Invalid jobid format detected, resetting to default '

file modified
+4 -2
@@ -6,11 +6,13 @@ 

  '''Helper tools for managing check status, outcome, and output.'''

  

  from __future__ import absolute_import

+ from __future__ import print_function

  import pprint

  import collections

  import yaml

  

  from . import python_utils

+ from .python_utils import basestring, cmp

  from . import exceptions as exc

  from .logger import log

  
@@ -170,7 +172,7 @@ 

  

          self.output.append(message)

          if printout:

-             print message

+             print(message)

  

  

      @classmethod
@@ -319,7 +321,7 @@ 

              data['checkname'] = detail.checkname

          if detail._internal:

              data['_internal'] = detail._internal

-         for key, value in detail.keyvals.iteritems():

+         for key, value in detail.keyvals.items():

              if key in RESERVED_KEYS:

                  log.warn("Reserved key '%s' found in keyvals. Ignoring for "

                           "export purposes.", key)

file modified
+2 -1
@@ -17,6 +17,7 @@ 

  from libtaskotron.config_defaults import (Config, ProductionConfig, TestingConfig, ProfileName,

                                            RuntaskModeName)

  from libtaskotron import file_utils

+ from libtaskotron.python_utils import basestring

  

  CONF_DIRS = [ # local checkout dir first, then system wide dir

      os.path.abspath(os.path.dirname(libtaskotron.__file__) + '/../conf'),
@@ -295,7 +296,7 @@ 

      with open(filename, 'r') as datafile:

          try:

              return yaml.safe_load(datafile.read())

-         except yaml.YAMLError, e:

+         except yaml.YAMLError as e:

              raise exc.TaskotronConfigError(e)

  

  

@@ -10,6 +10,7 @@ 

  from libtaskotron.exceptions import TaskotronDirectiveError

  import libtaskotron.ext.fedora.bodhi_utils as bodhi

  from libtaskotron.ext.fedora.koji_utils import KojiClient

+ from libtaskotron.python_utils import basestring

  from libtaskotron import config

  from libtaskotron import exceptions as exc

  

@@ -194,7 +194,7 @@ 

                  output_data['downloaded_files'].append(

                      file_utils.download(url, '.', localpath)

                  )

-             except exc.TaskotronRemoteError, e:

+             except exc.TaskotronRemoteError as e:

                  if e.errno == 404 and ignore_missing:

                      log.debug('File not found, ignoring: %s', url)

                  else:

@@ -10,6 +10,7 @@ 

  from libtaskotron.ext.fedora.koji_utils import KojiClient

  from libtaskotron.ext.fedora import rpm_utils

  from libtaskotron.logger import log

+ from libtaskotron.python_utils import basestring

  from libtaskotron import file_utils

  

  DOCUMENTATION = """

@@ -140,7 +140,7 @@ 

              self.resultsdb.get_testcase(name)

              self._ensured_testcases.append(name)

              return

-         except resultsdb_api.ResultsDBapiException, e:

+         except resultsdb_api.ResultsDBapiException as e:

              if not e.message.startswith('Testcase not found'):

                  raise e

  
@@ -209,7 +209,7 @@ 

                  log.debug('Namespace %s found in the safe namespaces.', ns)

                  return

  

-         for ns, repos in conf_ns['namespaces_whitelist'].iteritems():

+         for ns, repos in conf_ns['namespaces_whitelist'].items():

              if checkname.startswith(ns+'.'):

                  log.debug('Namespace %s found in the namespace whitelist.', ns)

                  ns_repos = repos
@@ -224,7 +224,7 @@ 

              gitconfig = configparser.ConfigParser()

              gitconfig.read(gitconfig_filename)

              task_repo_url = gitconfig['remote "origin"']['url']

-         except TypeError, e:

+         except TypeError as e:

              log.exception(e)

              raise TaskotronDirectiveError("Could not find task's git remote 'origin' url"

                                            "in %s" % gitconfig_filename)
@@ -304,7 +304,7 @@ 

                  log.debug('Result saved in ResultsDB:\n%s', pprint.pformat(result))

                  detail._internal['resultsdb_result_id'] = result['id']

  

-             except resultsdb_api.ResultsDBapiException, e:

+             except resultsdb_api.ResultsDBapiException as e:

                  log.error(e)

                  log.error("Failed to store to ResultsDB: `%s` `%s` `%s`",

                             detail.item, checkname, detail.outcome)

@@ -71,6 +71,10 @@ 

  directive_class = 'XunitDirective'

  

  

+ # https://github.com/laurentb/xunitparser/issues/10

+ xunitparser.TestSuite._cleanup = False

+ 

+ 

  class XunitDirective(BaseDirective):

  

      aggregations = ['none', 'allpass']

@@ -5,6 +5,8 @@ 

  

  from __future__ import absolute_import

  

+ from libtaskotron.python_utils import basestring

+ 

  DOCUMENTATION = """

  module: yumrepoinfo_directive

  short_description: translate Koji tags into YUM repository URLs

file modified
+3 -3
@@ -24,7 +24,7 @@ 

  

  try:

      from libtaskotron.ext.disposable import vm

- except ImportError, e:

+ except ImportError as e:

      raise exc.TaskotronImportError(e)

  

  
@@ -69,7 +69,7 @@ 

                      self.task_vm.ipaddr)

  

                  return self.task_vm.ipaddr

-             except vm.TestcloudInstanceError, e:

+             except vm.TestcloudInstanceError as e:

                  if retries <= 0:

                      raise exc.TaskotronMinionError('Disposable client failed '

                          'to boot: %s', e)
@@ -132,7 +132,7 @@ 

              subprocess.check_call(['ansible-playbook', '--syntax-check',

                  playbook])

              log.debug('Playbook is syntactically correct: %s', playbook)

-         except subprocess.CalledProcessError, e:

+         except subprocess.CalledProcessError as e:

              log.error('Syntax check failed for playbook %s: %s', playbook,

                        e)

              raise exc.TaskotronPlaybookError(e)

@@ -12,6 +12,7 @@ 

  from libtaskotron import exceptions as exc

  from libtaskotron.logger import log

  from libtaskotron import python_utils

+ from libtaskotron.python_utils import basestring

  

  from . import rpm_utils

  

@@ -73,7 +73,7 @@ 

                  assert len(build[0]) <= 1, 'More than one build returned with latest=True'

                  nvrs.append(build[0][0]['nvr'])

  

-         sorted_nvrs = sorted(nvrs, cmp=rpm_utils.cmpNEVR, reverse=True)

+         sorted_nvrs = sorted(nvrs, key=rpm_utils.sortkeyNEVR, reverse=True)

          if sorted_nvrs:

              return sorted_nvrs[0]

  

@@ -6,6 +6,7 @@ 

  ''' Utility methods related to RPM '''

  

  from __future__ import absolute_import

+ import functools

  import re

  import hawkey

  import subprocess
@@ -105,6 +106,9 @@ 

      return int(rpmver1.evr_cmp(rpmver2, sack))

  

  

+ sortkeyNEVR = functools.cmp_to_key(cmpNEVR)

+ 

+ 

  def install(pkgs):

      '''Install packages from system repositories using DNF. Either root or sudo access required.

  

@@ -6,11 +6,17 @@ 

  '''A wrapper object for yumrepoinfo.conf to access its information easily'''

  

  from __future__ import absolute_import

- import ConfigParser

  import os

- import urllib2

  import socket

  

+ try:

+     import configparser

+     from urllib.request import urlopen

+     from urllib.error import URLError

+ except ImportError:

+     import ConfigParser as configparser

+     from urllib2 import urlopen, URLError

+ 

  from libtaskotron import config

  from libtaskotron.logger import log

  from libtaskotron import arch_utils
@@ -43,6 +49,26 @@ 

      return _yumrepoinfo[arch]

  

  

+ try:

+     class SectionNameInterpolation(configparser.BasicInterpolation):

+         '''In order to make ConfigParser work like it once used to work

+         we add this crazy hack inspired by this Stack Overflow answer

+         https://stackoverflow.com/a/43415907/1839451'''

+         def before_get(self, parser, section, option, value, defaults):

+             value = value.replace('%(__name__)s', section)

+             return super().before_get(parser, section, option, value, defaults)

+ 

+     class YumRepoInfoConfigParser(configparser.SafeConfigParser):

+         '''A SafeConfigParser with above SectionNameInterpolation'''

+         def __init__(self, *args, **kwargs):

+             kwargs['interpolation'] = SectionNameInterpolation()

+             super().__init__(*args, **kwargs)

+ except AttributeError:

+     # On Python 2, interpolation is hardcoded and the above doesn't work

+     # The behavior however is consistent with the above

+     YumRepoInfoConfigParser = configparser.SafeConfigParser

+ 

+ 

  class YumRepoInfo(object):

      '''This class is a wrapper for easily accessing repoinfo.conf file.'''

  
@@ -75,8 +101,7 @@ 

              [os.path.join(confdir, 'yumrepoinfo.conf')

               for confdir in config.CONF_DIRS])

          self.resolve_retry = resolve_retry

-         self.parser = ConfigParser.SafeConfigParser(defaults=

-             {'arch': self.arch})

+         self.parser = YumRepoInfoConfigParser(defaults={'arch': self.arch})

  

          if not self.filelist:

              # no data should be loaded
@@ -145,7 +170,7 @@ 

          '''

          try:

              return self.parser.get(reponame, key)

-         except ConfigParser.Error as e:

+         except configparser.Error as e:

              raise exc.TaskotronConfigError("Can't retrieve key '%s' from repo "

                  "'%s': %s" % (key, reponame, e))

  

file modified
+3 -3
@@ -42,7 +42,7 @@ 

      try:

          os.makedirs(fullpath)

          assert os.path.isdir(fullpath)

-     except OSError, e:

+     except OSError as e:

          if e.errno == 17: # "[Errno 17] File exists"

              # if it is a directory everything is ok

              if os.path.isdir(fullpath):
@@ -120,13 +120,13 @@ 

          log.debug('Downloading%s: %s', ' (cached)' if cachedir else '', url)

          try:

              _download(url, dl_dest)

-         except requests.exceptions.RequestException, e:

+         except requests.exceptions.RequestException as e:

              log.exception('Download failed for: %s', url)

              # the file can be incomplete, remove

              if os.path.exists(dl_dest):

                  try:

                      os.remove(dl_dest)

-                 except OSError, e:

+                 except OSError as e:

                      log.exception('Could not delete incomplete file: %s', dl_dest)

              raise TaskotronRemoteError(e, errno=e.response.status_code)

  

file modified
+1 -1
@@ -12,7 +12,7 @@ 

  

  try:

      from libtaskotron.ext.fedora import rpm_utils

- except ImportError, e:

+ except ImportError as e:

      raise exc.TaskotronImportError(e)

  

  

file modified
+3 -2
@@ -6,6 +6,7 @@ 

  ''' Utility methods related to an operating system '''

  

  from __future__ import absolute_import

+ from __future__ import print_function

  import os

  import subprocess

  
@@ -68,10 +69,10 @@ 

      if 'stdout' in kwargs:

          raise exc.TaskotronValueError('stdout parameter not allowed, it will be overridden')

  

-     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr, bufsize=bufsize, **kwargs)

+     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr, bufsize=bufsize, universal_newlines=True, **kwargs)

      output = []

      for line in iter(proc.stdout.readline, ''):

-         print line,

+         print(line, end=' ')

          output.append(line)

  

      (stdoutdata, stderrdata) = proc.communicate()

@@ -10,6 +10,10 @@ 

  

  import libtaskotron.exceptions as exc

  

+ try:

+     basestring = basestring

+ except NameError:

+     basestring = str

  

  def iterable(obj, item_type=None):

      '''Decide whether ``obj`` is an :class:`~collections.Iterable` (you can
@@ -117,3 +121,17 @@ 

          cmdline.extend(segment)

  

      return cmdline

+ 

+ 

+ def cmp(x, y):

+     """

+     Replacement for built-in function cmp that was removed in Python 3

+ 

+     Compare the two objects x and y and return an integer according to

+     the outcome. The return value is negative if x < y, zero if x == y

+     and strictly positive if x > y.

+ 

+     https://portingguide.readthedocs.io/en/latest/comparisons.html#the-cmp-function

+     """

+ 

+     return (x > y) - (x < y)

@@ -11,7 +11,7 @@ 

  from libtaskotron.ext.fedora import koji_utils

  from libtaskotron import file_utils

  

- from test_file_utils import mock_download

+ from .test_file_utils import mock_download

  

  

  class TestKojiClient():

@@ -11,7 +11,7 @@ 

  from libtaskotron.ext.fedora import yumrepoinfo

  from libtaskotron import exceptions as exc

  

- from test_yumrepoinfo import TEST_CONF

+ from .test_yumrepoinfo import TEST_CONF

  

  

  @pytest.mark.usefixtures('setup')

@@ -5,15 +5,14 @@ 

  

  import pytest

  import mock

- import StringIO

- import mock

+ from io import StringIO

  

  from libtaskotron.directives import yumrepoinfo_directive

  from libtaskotron.exceptions import TaskotronDirectiveError

  

  from libtaskotron.ext.fedora import yumrepoinfo

  

- from test_yumrepoinfo import TEST_CONF

+ from .test_yumrepoinfo import TEST_CONF

  

  

  class TestYumrepoinfoDirective(object):
@@ -81,7 +80,7 @@ 

          yumrepoinfo object instead of falling back to the default system arch"""

          ref_arch = 'i386'

          repoinfo = yumrepoinfo.YumRepoInfo(filelist=[], arch='x86_64')

-         repoinfo.parser.readfp(StringIO.StringIO(TEST_CONF))

+         repoinfo.parser.readfp(StringIO(TEST_CONF))

  

          stub_getrepoinfo = mock.MagicMock(return_value=repoinfo)

          monkeypatch.setattr(yumrepoinfo, 'get_yumrepoinfo', stub_getrepoinfo)

file modified
+19 -12
@@ -5,14 +5,21 @@ 

  

  '''Unit tests for libtaskotron/config.py'''

  

+ from __future__ import print_function

  import os

+ import sys

  import pytest

  import mock

- from StringIO import StringIO

+ from io import StringIO

+ 

  from libtaskotron import config

  from libtaskotron import exceptions as exc

  

  

+ PYVER = sys.version_info.major

+ builtin_open = '__builtin__.open' if PYVER < 3 else 'builtins.open'

+ 

+ 

  @pytest.mark.usefixtures('setup')

  class TestConfig(object):

  
@@ -39,7 +46,7 @@ 

          '''By default we should have a testing profile'''

          assert os.getenv(config.PROFILE_VAR) == config.ProfileName.TESTING

          conf = config.get_config()

-         print conf

+         print(conf)

          assert conf.profile == config.ProfileName.TESTING

          assert isinstance(conf, config.TestingConfig)

  
@@ -54,7 +61,7 @@ 

      def test_load_defaults(self):

          '''Test _load_defaults() function'''

          for attr, value in vars(config.ProfileName).items():

-             print attr, value

+             print(attr, value)

              if attr.startswith('_'):

                  continue

              conf = config._load_defaults(value)
@@ -67,13 +74,13 @@ 

  

      def test_load_file_empty(self):

          '''Test _load_file() function with empty file'''

-         contents = StringIO('')

+         contents = StringIO(u'')

          conf_object = config._load_file(contents)

          assert conf_object == {}

  

      def test_load_file_commented(self):

          '''Test _load_file() function with fully commented out file'''

-         contents = StringIO('''

+         contents = StringIO(u'''

  # first commented line

  # second: line

  # last line
@@ -83,7 +90,7 @@ 

  

      def test_load_file_options(self):

          '''Test _load_file() function with some options present'''

-         contents = StringIO('''# a header comment

+         contents = StringIO(u'''# a header comment

  option1: value1

  # option2: value2

  option3: 15
@@ -98,22 +105,22 @@ 

      def test_load_file_invalid_syntax(self):

          '''Test _load_file() function with invalid syntax'''

          with pytest.raises(exc.TaskotronConfigError):

-             contents = StringIO('a single string (not dict)')

+             contents = StringIO(u'a single string (not dict)')

              config._load_file(contents)

  

          with pytest.raises(exc.TaskotronConfigError):

-             contents = StringIO('tab:\t #this is invalid in YAML')

+             contents = StringIO(u'tab:\t #this is invalid in YAML')

              config._load_file(contents)

  

      def test_load_file_invalid_type(self):

          '''Test _load_file() function with invalid option type'''

          # tmpdir is string, with string it should pass

-         contents = StringIO('tmpdir: foo')

+         contents = StringIO(u'tmpdir: foo')

          config._load_file(contents)

  

          # but with anything else, it should fail

          with pytest.raises(exc.TaskotronConfigError):

-             contents = StringIO('tmpdir: False')

+             contents = StringIO(u'tmpdir: False')

              config._load_file(contents)

  

      def test_merge_config(self):
@@ -174,7 +181,7 @@ 

          file_data = '%'

          mocked_open = mock.mock_open(read_data=file_data)

  

-         with mock.patch('__builtin__.open', mocked_open):

+         with mock.patch(builtin_open, mocked_open):

              with pytest.raises(exc.TaskotronConfigError):

                  config.parse_yaml_from_file('mocked_filename')

  
@@ -182,7 +189,7 @@ 

          file_data = ':'

          mocked_open = mock.mock_open(read_data=file_data)

  

-         with mock.patch('__builtin__.open', mocked_open):

+         with mock.patch(builtin_open, mocked_open):

              with pytest.raises(exc.TaskotronConfigError):

                  config.parse_yaml_from_file('mocked_filename')

  

file modified
+1 -1
@@ -17,7 +17,7 @@ 

  from libtaskotron import file_utils

  from libtaskotron import arch_utils

  

- from test_file_utils import mock_download

+ from .test_file_utils import mock_download

  

  # http://stackoverflow.com/questions/3190706/nonlocal-keyword-in-python-2-x

  def create_multicall(first, second):

file modified
+11 -3
@@ -9,6 +9,7 @@ 

  

  from libtaskotron import python_utils

  import libtaskotron.exceptions as exc

+ from libtaskotron.python_utils import basestring

  

  

  class TestCollectionOf:
@@ -27,7 +28,11 @@ 

      def test_not_iterable(self):

          assert not python_utils.iterable('a')

          assert not python_utils.iterable(u'a')

-         assert not python_utils.iterable(unicode('foo'))

+         try:

+             assert not python_utils.iterable(unicode('foo'))

+         except NameError:

+             # Python 3 no such thing as unicode, str already tested

+             pass

          assert not python_utils.iterable(3)

          assert not python_utils.iterable(3.14)

          assert not python_utils.iterable(None)
@@ -40,8 +45,11 @@ 

  

          assert python_utils.iterable(['a', 'b'], str)

          assert python_utils.iterable(['a', 'b'], basestring)

-         assert not python_utils.iterable(['a', 'b'], unicode)

- 

+         try:

+             assert not python_utils.iterable(['a', 'b'], unicode)

+         except NameError:

+             # Python 3 no such thing as unicode, str already tested

+             pass

          assert python_utils.iterable([[], []], list)

  

          # empty classes

@@ -7,8 +7,12 @@ 

  from libtaskotron.check import CheckDetail, export_YAML, import_YAML

  import mock

  import os

+ import sys

  import argparse

  

+ PYVER = sys.version_info.major

+ builtin_open = '__builtin__.open' if PYVER < 3 else 'builtins.open'

+ 

  OUTPUT = ""

  

  FILE = """results:
@@ -36,7 +40,7 @@ 

          stub_file = mock.MagicMock()

          stub_file.write = save_output

  

-         with mock.patch('__builtin__.open', mock.MagicMock(return_value=stub_file), create=True):

+         with mock.patch(builtin_open, mock.MagicMock(return_value=stub_file), create=True):

              taskotron_result.main()

  

          assert OUTPUT == export_YAML(CheckDetail(**vars(test_args)))
@@ -56,7 +60,7 @@ 

  

          monkeypatch.setattr(os.path, 'isfile', mock.MagicMock(return_value=True))

  

-         with mock.patch('__builtin__.open', mock.MagicMock(return_value=stub_file), create=True):

+         with mock.patch(builtin_open, mock.MagicMock(return_value=stub_file), create=True):

              taskotron_result.main()

  

          assert OUTPUT == export_YAML(import_YAML(FILE)+[CheckDetail(**vars(test_args))])
@@ -73,7 +77,7 @@ 

          stub_file = mock.MagicMock()

          stub_file.write = save_output

  

-         with mock.patch('__builtin__.open', mock.MagicMock(return_value=stub_file), create=True):

+         with mock.patch(builtin_open, mock.MagicMock(return_value=stub_file), create=True):

              taskotron_result.main()

  

          assert OUTPUT == export_YAML(CheckDetail(**vars(test_args)))

file modified
+14 -10
@@ -6,15 +6,19 @@ 

  '''Unit tests for libtaskotron/yumrepoinfo.py'''

  

  import pytest

- import StringIO

- import ConfigParser

  import mock

+ from io import StringIO

+ 

+ try:

+     import configparser

+ except ImportError:

+     import ConfigParser as configparser

  

  from libtaskotron.ext.fedora import yumrepoinfo

  from libtaskotron import exceptions as exc

  

  

- TEST_CONF='''\

+ TEST_CONF=u'''\

  [DEFAULT]

  baseurl = http://download.fedoraproject.org/pub/fedora/linux

  baseurl_altarch = http://download.fedoraproject.org/pub/fedora-secondary
@@ -70,14 +74,14 @@ 

          monkeypatch.setattr(yumrepoinfo.YumRepoInfo, '_switch_to_mirror', mock.Mock())

          # create YumRepoInfo initialized with TEST_CONF

          self.repoinfo = yumrepoinfo.YumRepoInfo(filelist=[])

-         self.repoinfo.parser.readfp(StringIO.StringIO(TEST_CONF))

+         self.repoinfo.parser.readfp(StringIO(TEST_CONF))

  

      @pytest.fixture

      def disable_disk_loading(self, monkeypatch):

          '''Patch ConfigParser not to load from disk.'''

  

          # instead of reading from disk, just return the input parameter

-         monkeypatch.setattr(ConfigParser.RawConfigParser, 'read',

+         monkeypatch.setattr(configparser.RawConfigParser, 'read',

                              lambda self, cfg: cfg)

  

      @pytest.fixture
@@ -88,13 +92,13 @@ 

      def test_init_arch(self, disable_disk_loading):

          '''Test YumRepoInfo(arch=)'''

          repoinfo = yumrepoinfo.YumRepoInfo(arch='x86_64', filelist=[])

-         repoinfo.parser.readfp(StringIO.StringIO(TEST_CONF))

+         repoinfo.parser.readfp(StringIO(TEST_CONF))

          assert '/x86_64/' in repoinfo.get('rawhide', 'url')

  

      def test_init_basearch(self, disable_disk_loading):

          '''i686 should be converted to i386'''

          repoinfo = yumrepoinfo.YumRepoInfo(arch='i686', filelist=[])

-         repoinfo.parser.readfp(StringIO.StringIO(TEST_CONF))

+         repoinfo.parser.readfp(StringIO(TEST_CONF))

          assert '/i386/' in repoinfo.get('rawhide', 'url')

  

      def test_init_empty_filelist(self, monkeypatch):
@@ -102,7 +106,7 @@ 

          # make sure the disk is not read

          def _raise_alarm(x):

              assert False, 'This must not be called'

-         monkeypatch.setattr(ConfigParser.RawConfigParser, 'read', _raise_alarm)

+         monkeypatch.setattr(configparser.RawConfigParser, 'read', _raise_alarm)

  

          repoinfo = yumrepoinfo.YumRepoInfo(filelist=[])

          assert not repoinfo.repos()
@@ -168,14 +172,14 @@ 

  

      def test_top_parent_raise(self):

          '''top_parent() must detect an infinite parent cycle'''

-         cfg = '''\

+         cfg = u'''\

  [repo1]

  parent = repo2

  [repo2]

  parent = repo1

  '''

          repoinfo = yumrepoinfo.YumRepoInfo(filelist=[])

-         repoinfo.parser.readfp(StringIO.StringIO(cfg))

+         repoinfo.parser.readfp(StringIO(cfg))

  

          with pytest.raises(exc.TaskotronConfigError):

              repoinfo.top_parent('repo1')

file modified
+13
@@ -15,3 +15,16 @@ 

  python_functions=test should

  python_files=test_* functest_*

  addopts=--functional testing/ --cov-report=term-missing --cov libtaskotron

+ 

+ [tox]

+ envlist = py27,py36

+ 

+ [testenv]

+ deps = -rrequirements.txt

+ commands = python -m pytest {posargs}

+ # setup.py has from utils import...

+ setenv = PYTHONPATH = {toxinidir}

+ # needs hawkey, koji

+ sitepackages = True

+ # tests read HOME

+ passenv = HOME

I am able to run the tests with:

  • tox -v -e py36 -- -v

There is one test that fail on me:

  • test_run_playbook_simple fails on Python 2 and Python 3 consistently, I don't know what's wrong

Added a workaround for the xunitparser bug. Changed the PR description.

1 new commit added

  • Python 3: Workaround a bug in xunitparser
7 years ago

1 new commit added

  • Python 3: Add py36 tox testenv to tox.ini
7 years ago

Thanks!

I don't seem to be able to install progressbar for python3 virtualenv or tox. Does that work for you?

Collecting progressbar>=2.3 (from -r requirements.txt (line 14))
  Using cached https://files.pythonhosted.org/packages/0f/e1/f30b72ecabba259c7c38dd0eb944a173effced3fd7de2c9c2902bd6f649a/progressbar-2.3.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-kmxyd6o8/progressbar/setup.py", line 5, in <module>
        import progressbar
      File "/tmp/pip-install-kmxyd6o8/progressbar/progressbar/__init__.py", line 59, in <module>
        from progressbar.widgets import *
      File "/tmp/pip-install-kmxyd6o8/progressbar/progressbar/widgets.py", line 121, in <module>
        class FileTransferSpeed(Widget):
      File "/home/kparal/devel/taskotron/libtaskotron/env3/lib64/python3.6/abc.py", line 133, in __new__
        cls = super().__new__(mcls, name, bases, namespace, **kwargs)
    ValueError: 'format' in __slots__ conflicts with class variable

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-kmxyd6o8/progressbar/

If I install the package as a Fedora RPM, it works.

test_run_playbook_simple fails on Python 2 and Python 3 consistently, I don't know what's wrong

It works for me, so it's not a regression. We can look into it, but it's not essential for this PR.

Don't know why, but that happened to me as well. i suppose it's a bug in progressbar. RPM version is what I've used.

I made a few changes. Once copr works, this will get deployed to taskotron-dev and we'll see how it works.

Commit 9685f7e fixes this pull-request

Pull-Request has been merged by kparal

7 years ago

Thanks a lot, Miro. Merged.

np :) thanks for quick merging.

Metadata
Changes Summary 33
+1 -1
file changed
data/ansible/library/acquire_subject.py
+1 -1
file changed
data/ansible/library/taskotron_koji.py
+1 -0
file changed
data/ansible/module_utils/koji.py
+11 -10
file changed
docs/generate_directive_docs.py
+1 -0
file changed
dodo.py
+1 -1
file changed
libtaskotron/arch_utils.py
+1 -1
file changed
libtaskotron/buildbot_utils.py
+4 -2
file changed
libtaskotron/check.py
+2 -1
file changed
libtaskotron/config.py
+1 -0
file changed
libtaskotron/directives/bodhi_directive.py
+1 -1
file changed
libtaskotron/directives/distgit_directive.py
+1 -0
file changed
libtaskotron/directives/koji_directive.py
+4 -4
file changed
libtaskotron/directives/resultsdb_directive.py
+4 -0
file changed
libtaskotron/directives/xunit_directive.py
+2 -0
file changed
libtaskotron/directives/yumrepoinfo_directive.py
+3 -3
file changed
libtaskotron/executor.py
+1 -0
file changed
libtaskotron/ext/fedora/bodhi_utils.py
+1 -1
file changed
libtaskotron/ext/fedora/koji_utils.py
+4 -0
file changed
libtaskotron/ext/fedora/rpm_utils.py
+30 -5
file changed
libtaskotron/ext/fedora/yumrepoinfo.py
+3 -3
file changed
libtaskotron/file_utils.py
+1 -1
file changed
libtaskotron/image_utils.py
+3 -2
file changed
libtaskotron/os_utils.py
+18 -0
file changed
libtaskotron/python_utils.py
+1 -1
file changed
testing/functest_koji_utils.py
+1 -1
file changed
testing/functest_yumrepoinfo.py
+3 -4
file changed
testing/functest_yumrepoinfo_directive.py
+19 -12
file changed
testing/test_config.py
+1 -1
file changed
testing/test_koji_utils.py
+11 -3
file changed
testing/test_python_utils.py
+7 -3
file changed
testing/test_taskotron_result.py
+14 -10
file changed
testing/test_yumrepoinfo.py
+13 -0
file changed
tox.ini