#312 Needs extensive testing: Python 3 support
Merged 5 years ago by ngompa. Opened 5 years ago by churchyard.
churchyard/FedoraReview python3  into  devel

Other python3 compatibility fixes
Riccardo Schirone • 5 years ago  
Make urllib uses python2&3 compatible
Riccardo Schirone • 5 years ago  
file modified
+2 -2
@@ -58,8 +58,8 @@ 

  After downloading (above) use try-fedora-review:

  

      $ cd FedoraReview

-     $ ./update-version

-     $ ./try-fedora-review --help

+     $ python3 update-version

+     $ python3 try-fedora-review --help

  

  To run from any directory, install try-fedora-review according to

  instructions in that script. update-version only needs to run once.

file modified
+25 -31
@@ -23,36 +23,26 @@ 

  

  BuildArch:  noarch

  

- BuildRequires:  python-BeautifulSoup

- BuildRequires:  python-bugzilla

- BuildRequires:  python-packaging

- BuildRequires:  python-straight-plugin

- %if 0%{?rhel} && 0%{?rhel} < 7

- BuildRequires:  python-unittest2

- %endif

- BuildRequires:  python2-devel

- BuildRequires:  rpm-python

+ BuildRequires:  python3-beautifulsoup4

+ BuildRequires:  python3-bugzilla

+ BuildRequires:  python3-packaging

+ BuildRequires:  python3-straight-plugin

+ BuildRequires:  python3-devel

+ BuildRequires:  python3-rpm

  

- Requires:       packagedb-cli

  Requires:       fedora-packager

- Requires:       python-BeautifulSoup

- Requires:       python-bugzilla

- Requires:       python-kitchen

- Requires:       python-packaging

- Requires:       python-straight-plugin

- Requires:       packagedb-cli

- Requires:       rpm-python

+ Requires:       python3-beautifulsoup4

+ Requires:       python3-bugzilla

+ Requires:       python3-packaging

+ Requires:       python3-straight-plugin

+ Requires:       python3-rpm

  # licensecheck used to be in rpmdevtools, moved to devscripts later

  # this is compatible with both situations without ifdefs

  Requires:       %{_bindir}/licensecheck

- %if 0%{?fedora} > 21

  Requires:       dnf-plugins-core

- %else

- Requires:       yum-utils

- %endif

  

  # Let's be consistent with the name used on fedorahosted

- provides:       FedoraReview = %{version}-%{release}

+ Provides:       FedoraReview = %{version}-%{release}

  

  Provides:       %{name}-php-phpci = %{version}-%{release}

  Obsoletes:      %{name}-php-phpci < %{version}-%{release}
@@ -87,7 +77,7 @@ 

  %package tests

  Summary: Test and test data files for fedora-review

  Requires: %{name} = %{version}-%{release}

- Requires: python-nose

+ Requires: python3-nose

  

  %description tests

  Tests are packaged separately due to space concerns.
@@ -98,20 +88,24 @@ 

  

  

  %build

- %py2_build

+ %py3_build

  

  

  %install

- %py2_install

- pkg_dir="$RPM_BUILD_ROOT/%{python_sitelib}/FedoraReview"

+ %py3_install

+ pkg_dir="%{buildroot}/%{python3_sitelib}/FedoraReview"

  ln -s %{_datadir}/%{name}/scripts $pkg_dir/scripts

  ln -s %{_datadir}/%{name}/plugins $pkg_dir/plugins

  cd test

  bash < restore-links.sh

  rm restore-links.sh remember-links

  cd ..

- cp -ar test "$RPM_BUILD_ROOT%{_datadir}/%{name}"

- cp -a pep8.conf pylint.conf "$RPM_BUILD_ROOT%{_datadir}/%{name}"

+ cp -ar test "%{buildroot}%{_datadir}/%{name}"

+ cp -a pep8.conf pylint.conf "%{buildroot}%{_datadir}/%{name}"

+ 

+ # Fix shebangs in %%{_bindir}.

+ chmod -c 0755 %{buildroot}%{_bindir}/*

+ pathfix.py -pni "%{__python3} %{py3_shbang_opts}" %{buildroot}%{python3_sitelib} %{buildroot}%{_bindir}/*

  

  

  %check
@@ -122,15 +116,15 @@ 

  mock --quiet -r fedora-25-i386 --init

  mock --quiet -r fedora-26-i386 --init

  mock --quiet -r fedora-26-i386 --uniqueext=hugo --init

- %{__python2} -m unittest discover -f

+ %{__python3} -m unittest discover -f

  %endif

  

  

  %files

  %doc README

  %license COPYING AUTHORS

- %{python2_sitelib}/FedoraReview

- %{python2_sitelib}/fedora_review-%{version}-py%{python2_version}.egg-info

+ %{python3_sitelib}/FedoraReview

+ %{python3_sitelib}/fedora_review-%{version}-py%{python3_version}.egg-info

  %{_bindir}/fedora-review

  %{_bindir}/fedora-create-review

  %{_bindir}/koji-download-scratch

file removed
-14
@@ -1,14 +0,0 @@ 

- #!/bin/bash

- #

- # fedora-review post-commit

- #

- cd $( dirname $( readlink -fn $0 ))/..

- commit=$( git rev-parse HEAD )

- commit=${commit:0:7}

- host=$( uname -n )

- isodate=( $( git show -s --pretty=format:%ci HEAD ) )

- cd src/FedoraReview

- sed -e "s/@commit@/$commit/g" \

-     -e "s/@host@/$host/g" \

-     -e "s/@date@/${isodate[0]}/g" \

-     -e "s/@time@/${isodate[1]}/g" < version.tmpl > version

file removed
-56
@@ -1,56 +0,0 @@ 

- #!/bin/bash

- #

- # fedora-review git pre-commit hook: run pep8 and pylint

- 

- branch_name=$(git symbolic-ref -q HEAD)

- branch_name=${branch_name##refs/heads/}

- branch_name=${branch_name:-HEAD}

- 

- if [ "$branch_name" = "master" ];then

-     echo "You are on master branch. If you want to contribute patches "

-     echo "you should work on devel branch. Please read CONTRIBUTE file. "

-     echo "To ignore this warning run 'git commit --no-verify'."

-     exit 1

- fi

- 

- ALL_FILES=$( git diff --cached --name-status |

-               grep -v ^D | awk '$1 $2 { print $2}' | grep -e '.py$' )

- 

- if [ -z "$ALL_FILES" ]; then

-     exit 0

- fi

- 

- pep8 --config pep8.conf  $ALL_FILES || {

-     echo "pep8 failed. Fix your code!"

-     echo "*If* you know what you are doing, use 'git commit --no-verify'"

-     exit 1

- }

- 

- SRC_FILES=''

- TEST_FILES=''

- for file in $( echo $ALL_FILES ); do

-     if [[ $file == test/* ]]; then

-         TEST_FILES="$TEST_FILES ${file##test/}"

-     else

-         SRC_FILES="$SRC_FILES $file"

-     fi

- done

- 

- if [ "$TEST_FILES" ]; then

-     cd test

-     export PYTHONPATH=../src

-     pylint --rcfile=../pylint.conf -f text $TEST_FILES > pylint.log || {

-         echo "Pylint failed for test files, log in test/pylint.log"

-         echo "Fix test code or use --no-verify."

-         exit 3

-     }

-     cd $OLDPWD

- fi

- if [ "$SRC_FILES" ]; then

-     export PYTHONPATH=src

-     pylint --rcfile=pylint.conf -f text $SRC_FILES > pylint.log || {

-         echo "Pylint failed, log in pylint.log."

-         echo "Fix code or use --no-verify."

-         exit 3

-     }

- fi

file modified
+9 -8
@@ -7,7 +7,7 @@ 

  

  import re

  import os

- import urllib

+ from six.moves.urllib.request import urlopen

  

  import rpm

  
@@ -56,20 +56,21 @@ 

          version = None

          for url in self.URLS:

              try:

-                 stream = urllib.urlopen(url)

+                 stream = urlopen(url)

                  content = stream.read()

                  stream.close()

-             except IOError, err:

+             except IOError as err:

                  self.log.warning('Could not retrieve info from %s', url)

                  self.log.debug('Error: %s', err, exc_info=True)

                  continue

-             res = re.search('Package: %s\nVersion:.*' % name, content)

+             res = re.search(('Package: %s\nVersion:.*' % name).encode(),

+                             content)

              if res is not None:

                  self.log.debug("Found in: %s", url)

                  versionok.append(url)

                  if version is None:

-                     ver = res.group().split('\n')[1]

-                     version = ver.replace('Version:', '').strip()

+                     ver = res.group().split(b'\n')[1]

+                     version = ver.replace(b'Version:', b'').strip()

                  else:

                      self.log.warning(

                          " * Found two version of the package in %s",
@@ -159,8 +160,8 @@ 

  

      def run_on_applicable(self):

          """ Run the check """

-         cur_version = self.spec.expand_tag('Version')

-         up_version = self.get_upstream_r_package_version()

+         cur_version = self.spec.expand_tag('Version').decode('utf-8')

+         up_version = self.get_upstream_r_package_version().decode('utf-8')

          if up_version is None:

              self.set_passed(

                  self.PENDING,

file modified
+4 -4
@@ -16,7 +16,7 @@ 

          if self.is_user_enabled():

              return self.user_enabled_value()

          archs = self.checks.spec.expand_tag('BuildArchs')

-         if len(archs) == 1 and archs[0].lower() == 'noarch':

+         if len(archs) == 1 and archs[0].lower() == b'noarch':

              return False

          if self.checks.buildsrc.is_available:

              src = self.checks.buildsrc
@@ -125,7 +125,7 @@ 

                  # All other .h files should be in a -devel package.

                  if '-devel' not in pkg:

                      passed = False

-                     extra += "%s : %s\n" % (pkg, path)

+                     extra += "{} : {}\n".format(pkg, path)

          self.set_passed(passed, extra)

  

  
@@ -173,7 +173,7 @@ 

              if pkg.endswith('-devel'):

                  continue

              for path in self.rpms.find_all('*.so', pkg):

-                 bad_list.append("%s: %s" % (pkg, path))

+                 bad_list.append("{}: {}".format(pkg, path))

                  if self.bad_re.search(path):

                      in_libdir = True

                  else:
@@ -217,7 +217,7 @@ 

              extra = ""

              for pkg in self.spec.packages:

                  for path in self.rpms.find_all('*.la', pkg):

-                     extra += "%s : %s\n" % (pkg, path)

+                     extra += "{} : {}\n".format(pkg, path)

              self.set_passed(self.FAIL, extra)

  

  

file modified
+27 -28
@@ -23,7 +23,7 @@ 

  import os.path

  import re

  from glob import glob

- from io import BytesIO

+ from six import BytesIO

  from subprocess import Popen, PIPE, CalledProcessError

  

  import rpm
@@ -144,7 +144,7 @@ 

  

      def run(self):

          archs = self.checks.spec.expand_tag('BuildArchs')

-         if len(archs) == 1 and archs[0].lower() == 'noarch':

+         if len(archs) == 1 and archs[0].lower() == b'noarch':

              self.set_passed(self.NA)

              return

          self.set_passed(self.PENDING)
@@ -253,7 +253,7 @@ 

          try:

              cmd = 'find %s -perm -4000' % rpms_dir

              with open('/dev/null', 'w') as f:

-                 suids = check_output(cmd.split(), stderr=f).strip().split()

+                 suids = check_output(cmd.split(), stderr=f, universal_newlines=True).strip().split()

          except CalledProcessError:

              self.log.info('Cannot run find command: %s', cmd)

              suids = []
@@ -321,9 +321,9 @@ 

      def run(self):

          bad_tags = []

          for pkg_name in self.spec.packages:

-             if '%' in self.spec.expand_tag('Summary', pkg_name):

+             if '%' in self.spec.expand_tag('Summary', pkg_name).decode('utf-8'):

                  bad_tags.append(pkg_name + ' (summary)')

-             if '%' in self.spec.expand_tag('Description', pkg_name):

+             if '%' in self.spec.expand_tag('Description', pkg_name).decode('utf-8'):

                  bad_tags.append(pkg_name + ' (description)')

          if bad_tags:

              self.set_passed(self.PENDING,
@@ -597,7 +597,7 @@ 

      def _write_license(files_by_license, filename):

          ''' Dump files_by_license to filename. '''

          with open(filename, 'w') as f:

-             for license_ in sorted(files_by_license.iterkeys()):

+             for license_ in sorted(files_by_license.keys()):

                  f.write('\n' + license_ + '\n')

                  f.write('-' * len(license_) + '\n')

                  for path in sorted(files_by_license[license_]):
@@ -642,7 +642,7 @@ 

              license_ = license_.strip()

              if not license_is_valid(license_):

                  license_ = self.unknown_license

-             if license_ not in files_by_license.iterkeys():

+             if license_ not in files_by_license.keys():

                  files_by_license[license_] = []

              files_by_license[license_].append(file_)

          return files_by_license
@@ -654,7 +654,7 @@ 

              if os.path.exists(source_dir):

                  cmd = 'licensecheck -r ' + source_dir

                  try:

-                     out = check_output(cmd, shell=True)

+                     out = check_output(cmd, shell=True, universal_newlines=True)

                  except (OSError, CalledProcessError) as err:

                      self.set_passed(self.PENDING,

                                      "Cannot run licensecheck: " + str(err))
@@ -672,7 +672,7 @@ 

                  msg += ' Please check the source files for licenses manually.'

              else:

                  msg += ' Licenses found: "' \

-                        + '", "'.join(files_by_license.iterkeys()) + '".'

+                        + '", "'.join(files_by_license.keys()) + '".'

                  if self.unknown_license in files_by_license:

                      msg += ' %d files have unknown license.' % \

                                  len(files_by_license[self.unknown_license])
@@ -720,9 +720,8 @@ 

                                'COPYRIGHT', 'copyright']:

              pattern = '*' + potentialfile + '*'

              licenses.extend(self.rpms.find_all(pattern))

-         licenses = filter(lambda l: not self.rpms.find(l + '/*'),

-                           licenses)

-         licenses = map(lambda f: f.split('/')[-1], licenses)

+         licenses = [l.split('/')[-1] for l in licenses

+                     if not self.rpms.find(l + '/*')]

          if licenses == []:

              self.set_passed(self.PENDING)

              return
@@ -732,19 +731,19 @@ 

          for pkg in self.spec.packages:

              nvr = self.spec.get_package_nvr(pkg)

              rpm_path = Mock.get_package_rpm_path(nvr)

-             cmd = 'rpm -qp%s %s' % (self._license_flag, rpm_path)

-             doclist = check_output(cmd.split())

+             cmd = 'rpm -qp{} {}'.format(self._license_flag, rpm_path)

+             doclist = check_output(cmd.split(), universal_newlines=True)

              flagged_files.extend(doclist.split('\n'))

-         flagged_files = map(lambda f: f.split('/')[-1], flagged_files)

+         flagged_files = [f.split('/')[-1] for f in flagged_files]

  

          if self._license_flag == 'L':

              for pkg in self.spec.packages:

                  nvr = self.spec.get_package_nvr(pkg)

                  rpm_path = Mock.get_package_rpm_path(nvr)

                  cmd = 'rpm -qpL %s' % rpm_path

-                 qpL_list = check_output(cmd.split())

+                 qpL_list = check_output(cmd.split(), universal_newlines=True)

                  qpL_files.extend(qpL_list.split('\n'))

-             qpL_files = map(lambda f: f.split('/')[-1], qpL_files)

+             qpL_files = [f.split('/')[-1] for f in qpL_files]

  

          for _license in licenses:

              if self._license_flag == 'L' and _license not in qpL_files:
@@ -871,7 +870,7 @@ 

          self.type = 'MUST'

  

      def is_applicable(self):

-         license_ = self.spec.expand_tag('License').lower().split()

+         license_ = self.spec.expand_tag('License').decode('utf-8').lower().split()

          return 'and' in license_ or 'or' in license_

  

  
@@ -902,7 +901,7 @@ 

          if passed:

              self.set_passed(passed)

          else:

-             self.set_passed(passed, '%s\n%s' % (self.spec.name, output))

+             self.set_passed(passed, '{}\n{}'.format(self.spec.name, output))

  

  

  class CheckNaming(GenericCheckBase):
@@ -1112,7 +1111,7 @@ 

              items = []

              for d in owners_by_dir:

                  owners = ', '.join(owners_by_dir[d])

-                 items.append("{0}({1})".format(d, owners))

+                 items.append("{}({})".format(d, owners))

              return "Dirs in package are owned also by: " + \

                  ', '.join(items)

  
@@ -1211,10 +1210,10 @@ 

                  self.log.warn(

                      "Cannot extract local source: %s", s.filename)

                  return(False, None)

-             cmd = '/usr/bin/diff -U2 -r %s %s' % (upstream, local)

+             cmd = '/usr/bin/diff -U2 -r {} {}'.format(upstream, local)

              self.log.debug(' Diff cmd: %s', cmd)

              try:

-                 p = Popen(cmd.split(), stdout=PIPE, stderr=PIPE)

+                 p = Popen(cmd.split(), stdout=PIPE, stderr=PIPE, universal_newlines=True)

                  output = p.communicate()[0]

              except OSError:

                  self.log.error("Cannot run diff", exc_info=True)
@@ -1238,9 +1237,9 @@ 

              local = self.srpm.check_source_checksum(source.filename)

              upstream = source.check_source_checksum()

              text += source.url + ' :\n'

-             text += '  CHECKSUM({0}) this package     : {1}\n'.\

+             text += '  CHECKSUM({}) this package     : {}\n'.\

                      format(Settings.checksum.upper(), local)

-             text += '  CHECKSUM({0}) upstream package : {1}\n'.\

+             text += '  CHECKSUM({}) upstream package : {}\n'.\

                      format(Settings.checksum.upper(), upstream)

              if local != upstream:

                  all_sources_passed = False
@@ -1871,8 +1870,8 @@ 

      def run(self):

          using = []

          failed = False

-         systemd_post_re = re.compile(re.escape(rpm.expandMacro('%systemd_post .*.service')).replace('\.\*', '.*')[2:-4], re.M)

-         systemd_preun_re = re.compile(re.escape(rpm.expandMacro('%systemd_preun .*.service')).replace('\.\*', '.*')[2:-4], re.M)

+         systemd_post_re = re.compile(re.escape(rpm.expandMacro('%systemd_post .*.service')).replace(r'\.\*', '.*')[2:-4], re.M)

+         systemd_preun_re = re.compile(re.escape(rpm.expandMacro('%systemd_preun .*.service')).replace(r'\.\*', '.*')[2:-4], re.M)

          for pkg in self.spec.packages:

              if self.rpms.find('/usr/lib/systemd/system/*', pkg):

                  using.append(pkg)
@@ -1904,8 +1903,8 @@ 

      def run(self):

          using = []

          failed = False

-         systemd_user_post_re = re.compile(re.escape(rpm.expandMacro('%systemd_user_post .*.service')).replace('\.\*', '.*')[2:], re.M)

-         systemd_user_preun_re = re.compile(re.escape(rpm.expandMacro('%systemd_user_preun .*.service')).replace('\.\*', '.*')[2:], re.M)

+         systemd_user_post_re = re.compile(re.escape(rpm.expandMacro('%systemd_user_post .*.service')).replace(r'\.\*', '.*')[2:], re.M)

+         systemd_user_preun_re = re.compile(re.escape(rpm.expandMacro('%systemd_user_preun .*.service')).replace(r'\.\*', '.*')[2:], re.M)

          for pkg in self.spec.packages:

              if self.rpms.find('/usr/lib/systemd/user/*', pkg):

                  using.append(pkg)

file modified
+4 -3
@@ -50,7 +50,7 @@ 

  def _prepend_indent(text):

      ''' add the paragraph indentation '''

      lines = text.splitlines()

-     return '\n'.join(map(lambda x: "  " + x if x != "" else "", lines))

+     return '\n'.join(["  " + x if x != "" else "" for x in lines])

  

  

  class Registry(RegistryBase):
@@ -171,7 +171,8 @@ 

  

              try:

                  self.log.debug("running: %s", ' '.join(cmd))

-                 p = Popen(cmd, stdout=PIPE, stderr=PIPE)

+                 p = Popen(cmd, stdout=PIPE, stderr=PIPE,

+                           universal_newlines=True)

                  stdout, stderr = p.communicate()

              except IOError:

                  self.set_passed(self.PENDING,
@@ -185,7 +186,7 @@ 

                  return

  

              m4_lines = stdout.splitlines(False)

-             m4_lines = map(lambda x: x.strip('('), m4_lines)

+             m4_lines = [x.strip('(') for x in m4_lines]

              for m4_line in m4_lines:

                  line, m4 = m4_line.split(':')

  

file modified
+2 -9
@@ -34,13 +34,6 @@ 

  import sys

  import tempfile

  

- # pylint: disable=W0611

- try:

-     from subprocess import check_output

- except ImportError:

-     from FedoraReview.el_compat import check_output

- # pylint: enable=W0611

- 

  

  import FedoraReview.deps as deps

  from FedoraReview import CheckBase, Mock, ReviewDirs, Settings
@@ -72,7 +65,7 @@ 

          arg: filenames, list of filenames to run rpmlint on

          """

          rpmlint_cfg = tempfile.NamedTemporaryFile(delete=False)

-         rpmlint_cfg.write('addFilter("unknown-key")')

+         rpmlint_cfg.write(b'addFilter("unknown-key")')

          rpmlint_cfg.close()

  

          cmd = 'rpmlint -f ' + rpmlint_cfg.name + ' ' + ' '.join(filenames)
@@ -390,7 +383,7 @@ 

          text += 'Active plugins: ' + ', '.join(plugins) + '\n'

          plugins = self.checks.get_plugins(False)

          text += 'Disabled plugins: ' + ', '.join(plugins) + '\n'

-         flags = [f for f in self.checks.flags.iterkeys()

+         flags = [f for f in self.checks.flags.keys()

                   if not self.checks.flags[f]]

          flags = ', '.join(flags) if flags else 'None'

          text += 'Disabled flags: ' + flags + '\n'

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

  from FedoraReview import ReviewError             # pylint: disable=W0611

  from FedoraReview import RegistryBase, Settings

  

- from generic import in_list

+ from .generic import in_list

  

  

  class Registry(RegistryBase):
@@ -175,8 +175,8 @@ 

  

          def get_requires(rpm_name, requires):

              ''' Return printable requirements for a rpm. '''

-             requires = filter(lambda s: 'rpmlib' not in s, requires)

-             requires = filter(lambda s: 'GLIBC' not in s, requires)

+             requires = [s for s in requires

+                         if 'rpmlib' not in s and 'GLIBC' not in s]

              requires = sorted(list(set(requires)))

              hdr = rpm_name + ' (rpmlib, GLIBC filtered):'

              requires.insert(0, hdr)
@@ -254,7 +254,7 @@ 

          if len(self.spec.packages) == 1:

              self.set_passed(self.NA)

              return

-         if len(archs) == 1 and archs[0].lower() == 'noarch':

+         if len(archs) == 1 and archs[0].lower() == b'noarch':

              isa = ''

          else:

              isa = Mock.get_macro('%_isa', self.spec, self.flags)
@@ -294,10 +294,10 @@ 

          for tag in ('Packager', 'Vendor', 'PreReq', 'Copyright'):

              if not self.spec.find_re(r'^\s*' + tag + r'\s*:'):

                  continue

-             value = self.spec.expand_tag(tag)

+             value = self.spec.expand_tag(tag).decode('utf-8')

              if value:

                  passed = False

-                 output += 'Found : %s: %s\n' % (tag, value)

+                 output += 'Found : {}: {}\n'.format(tag, value)

          if not passed:

              self.set_passed(passed, output)

          else:
@@ -415,11 +415,11 @@ 

              return

          passed = 'pass'

          extra = ''

-         for pkg in files_by_pkg.iterkeys():

+         for pkg in files_by_pkg.keys():

              for fn in files_by_pkg[pkg]:

                  if '-devel' not in pkg:

                      passed = 'pending'

-                     extra += '%s : %s\n' % (pkg, fn)

+                     extra += '{} : {}\n'.format(pkg, fn)

          self.set_passed(passed, extra)

  

  
@@ -544,7 +544,7 @@ 

          url_spec_file = self.spec.filename

          cmd = ["diff", '-U2', url_spec_file, srpm_spec_file]

          try:

-             p = Popen(cmd, stdout=PIPE, stderr=PIPE)

+             p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)

              output = p.communicate()[0]

          except OSError:

              self.log.error("Cannot run diff", exc_info=True)
@@ -596,7 +596,7 @@ 

          build_ok = self.checks.checkdict['CheckBuild'].is_passed

  

          arch = self.spec.expand_tag('BuildArch')

-         noarch = arch and arch[0].lower() == 'noarch'

+         noarch = arch and arch[0].lower() == b'noarch'

          one_arch = self.spec.expand_tag('ExclusiveArch')

          if build_ok and (one_arch or noarch):

              self.set_passed(self.PASS)

file modified
+2 -2
@@ -127,7 +127,7 @@ 

          self.automatic = True

  

      def run_on_applicable(self):

-         arch = self.spec.expand_tag('arch')

+         arch = self.spec.expand_tag('arch').decode('utf-8')

          if _has_extension(self):

              self.set_passed('noarch' not in arch,

                              "Package with binary extension can't be built"
@@ -453,7 +453,7 @@ 

  

          err_message = []

          # construct the error message for all non-present macros

-         for key, value in re_dict.iteritems():

+         for key, value in re_dict.items():

              if value is False:

                  err_message.append(key.pattern.replace('\\s+', ' '))

  

file modified
+11 -11
@@ -139,7 +139,7 @@ 

      fi

      sort_hint=$1

      shift

-     title=${*//\/ }

+     title=${*//\\/ }

      file="$sort_hint;${title/;/:};$i"

      cat > .attachments/"$file"

      cd $startdir
@@ -174,7 +174,7 @@ 

  def _settings_generator():

      ''' Bash code defining FR_SETTINGS, reflecting Settings. '''

      body = 'declare -A FR_SETTINGS \n'

-     for key in Settings.__dict__.iterkeys():

+     for key in Settings.__dict__.keys():

          if key.startswith('_'):

              continue

          value = Settings.__dict__[key]
@@ -182,14 +182,14 @@ 

              value = ''

          if isinstance(value, str):

              value = value.replace('"', r'\"')

-         body += 'FR_SETTINGS[%s]="%s"\n' % (key, value)

+         body += 'FR_SETTINGS[{}]="{}"\n'.format(key, value)

      return body

  

  

  def _source_generator(spec):

      ''' Bash code defining the %sourceX items. '''

      body = ''

-     for tag, path in spec.sources_by_tag.iteritems():

+     for tag, path in spec.sources_by_tag.items():

          body += 'export ' + tag + '="' + path + '"\n'

      return body

  
@@ -197,7 +197,7 @@ 

  def _patch_generator(spec):

      ''' Bash code defining the %patchX items. '''

      body = ''

-     for tag, path in spec.patches_by_tag.iteritems():

+     for tag, path in spec.patches_by_tag.items():

          body += 'export ' + tag + '="' + path + '"\n'

      return body

  
@@ -207,7 +207,7 @@ 

      body = 'declare -A FR_FILES\n'

      for pkg in spec.packages:

          item = _quote('\n'.join(spec.get_files(pkg)))

-         body += """FR_FILES[%s]='%s'\n""" % (pkg, item)

+         body += """FR_FILES[{}]='{}'\n""".format(pkg, item)

      return body

  

  
@@ -220,15 +220,15 @@ 

          section = spec.get_section('%description', pkg)

          if section:

              item = _quote('\n'.join(section))

-             body += """FR_DESCRIPTION[%s]='%s'\n""" % (pkg, item)

+             body += """FR_DESCRIPTION[{}]='{}'\n""".format(pkg, item)

      return body

  

  

  def _flags_generator(flags):

      ''' Bash code defining FR_FLAGS,reflecting checks.flags. '''

      body = 'declare -A FR_FLAGS\n'

-     for flag in flags.itervalues():

-         body += """FR_FLAGS[%s]='%s'\n""" % (flag.name, str(flag))

+     for flag in flags.values():

+         body += """FR_FLAGS[{}]='{}'\n""".format(flag.name, str(flag))

      return body

  

  
@@ -248,7 +248,7 @@ 

  

  def _write_tag(spec, env, tag):

      ''' Substitute a spec tag into env. '''

-     value = spec.expand_tag(tag.upper())

+     value = spec.expand_tag(tag.upper()).decode('utf-8')

      if value:

          env = env.replace('@' + tag + '@', value)

      else:
@@ -432,7 +432,7 @@ 

          Actually invoke the external script, returning

          (retcode, stdout, stderr)

          '''

-         p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)

+         p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)

          try:

              stdout, stderr = p.communicate()

          except OSError:

file modified
+9 -9
@@ -20,14 +20,14 @@ 

  Tools for helping Fedora package reviewers

  '''

  

- from check_base   import AbstractCheck, GenericCheck, CheckBase

- from mock         import Mock

- from review_error import ReviewError

- from review_dirs  import ReviewDirs

- from registry     import AbstractRegistry, RegistryBase

- from rpm_file     import RpmFile

- from settings     import Settings

- from version      import __version__, BUILD_ID, BUILD_DATE, BUILD_FULL

- from xdg_dirs     import XdgDirs

+ from .check_base   import AbstractCheck, GenericCheck, CheckBase

+ from .mock         import Mock

+ from .review_error import ReviewError

+ from .review_dirs  import ReviewDirs

+ from .registry     import AbstractRegistry, RegistryBase

+ from .rpm_file     import RpmFile

+ from .settings     import Settings

+ from .version      import __version__, BUILD_ID, BUILD_DATE, BUILD_FULL

+ from .xdg_dirs     import XdgDirs

  

  # vim: set expandtab ts=4 sw=4:

@@ -24,13 +24,13 @@ 

  

  from abc import ABCMeta, abstractmethod

  from glob import glob

- from urlparse import urlparse

+ from six.moves.urllib.parse import urlparse

  

- from helpers_mixin import HelpersMixin

- from review_error import ReviewError

- from settings import Settings

- from srpm_file import SRPMFile

- from review_dirs import ReviewDirs

+ from .helpers_mixin import HelpersMixin

+ from .review_error import ReviewError

+ from .settings import Settings

+ from .srpm_file import SRPMFile

+ from .review_dirs import ReviewDirs

  

  

  class AbstractBug(HelpersMixin):

@@ -18,9 +18,9 @@ 

  '''

  import os.path

  

- from url_bug import UrlBug

- from settings import Settings

- from abstract_bug import AbstractBug

+ from .url_bug import UrlBug

+ from .settings import Settings

+ from .abstract_bug import AbstractBug

  

  

  class BugzillaBug(UrlBug):

@@ -21,12 +21,12 @@ 

  ''' Basic definitions: AbstractCheck + descendants, TestResult.  '''

  

  import re

- import StringIO

+ from six.moves import StringIO

  

  from abc import ABCMeta, abstractmethod

  from textwrap import TextWrapper

  

- from helpers_mixin import HelpersMixin

+ from .helpers_mixin import HelpersMixin

  

  

  class _Attachment(object):
@@ -53,6 +53,24 @@ 

          s += self.text

          return s

  

+     def __eq__(self, other):

+         return self.__cmp__(other) == 0

+ 

+     def __ne__(self, other):

+         return self.__cmp__(other) != 0

+ 

+     def __lt__(self, other):

+         return self.__cmp__(other) < 0

+ 

+     def __le__(self, other):

+         return self.__cmp__(other) <= 0

+ 

+     def __gt__(self, other):

+         return self.__cmp__(other) > 0

+ 

+     def __ge__(self, other):

+         return self.__cmp__(other) >= 0

+ 

      def __cmp__(self, other):

          if not hasattr(other, 'order_hint'):

              return NotImplemented
@@ -288,7 +306,7 @@ 

  

      def get_text(self):

          ''' Return printable representation of test. '''

-         strbuf = StringIO.StringIO()

+         strbuf = StringIO()

          main_lines = self.wrapper.wrap(self._leader + self.text)

          strbuf.write('\n'.join(main_lines))

          if self.output_extra and self.output_extra != "":

file modified
+18 -18
@@ -27,13 +27,13 @@ 

  from operator import attrgetter

  from straight.plugin import load                  # pylint: disable=F0401

  

- from datasrc import RpmDataSource, BuildFilesSource, SourcesDataSource

- from settings import Settings

- from srpm_file import SRPMFile

- from spec_file import SpecFile

- from review_error import ReviewError

- from xdg_dirs import XdgDirs

- from reports import write_xml_report, write_template

+ from .datasrc import RpmDataSource, BuildFilesSource, SourcesDataSource

+ from .settings import Settings

+ from .srpm_file import SRPMFile

+ from .spec_file import SpecFile

+ from .review_error import ReviewError

+ from .xdg_dirs import XdgDirs

+ from .reports import write_xml_report, write_template

  

  

  _BATCH_EXCLUDED = 'CheckBuild,CheckPackageInstalls,CheckRpmlintInstalled,' \
@@ -66,7 +66,7 @@ 

                               first.name, first.defined_in, second.name,

                               second.defined_in)

  

-         if key in self.iterkeys():

+         if key in self.keys():

              log_duplicate(value, self[key])

          dict.__setitem__(self, key, value)

          value.checkdict = self
@@ -76,7 +76,7 @@ 

              raise TypeError("update: at most 1 arguments, got %d" %

                              len(args))

          other = dict(*args, **kwargs)

-         for key in other.iterkeys():

+         for key in other.keys():

              self[key] = other[key]

  

      def add(self, check):
@@ -115,10 +115,10 @@ 

  

          value = self[key]

          for victim in value.deprecates:

-             if victim in self.iterkeys():

+             if victim in self.keys():

                  log_kill(self[victim], value)

                  del self[victim]

-         for killer in self.itervalues():

+         for killer in self.values():

              if key in killer.deprecates:

                  log_kill(value, killer)

                  return
@@ -235,7 +235,7 @@ 

      def get_plugins(self, state='true_or_false'):

          ''' Return list of groups (i. e., plugins) being active/passive. '''

          plugins = []

-         for p in self.groups.iterkeys():

+         for p in self.groups.keys():

              if state != 'true_or_false':

                  r = self.groups[p]

                  if r.is_user_enabled():
@@ -287,7 +287,7 @@ 

          with open('.testlog.txt', 'w') as f:

              for r in results:

                  f.write('\n' + 24 * ' ' +

-                         "('%s', '%s')," % (r.state, r.name))

+                         "('{}', '{}'),".format(r.state, r.name))

  

      def _ready_to_run(self, name):

          """
@@ -317,7 +317,7 @@ 

  

      def deprecate(self):

          ''' Mark all deprecated tests as run. '''

-         allkeys = list(self.checkdict.iterkeys())

+         allkeys = list(self.checkdict.keys())

          for c in allkeys:

              if c not in self.checkdict:

                  continue
@@ -326,15 +326,15 @@ 

  

      def _get_ready_to_run(self):

          ''' Return checks ready to run, deprecating checks first. '''

-         names = list(self.checkdict.iterkeys())

-         tests_to_run = filter(self._ready_to_run, names)

+         names = self.checkdict.keys()

+         tests_to_run = (n for n in names if self._ready_to_run(n))

          return sorted(tests_to_run,

                        key=lambda t: len(self.checkdict[t].deprecates),

                        reverse=True)

  

      def is_external_plugin_installed(self, group_name):

          ''' Return True if external plugin install for given group. '''

-         for reg_group, registry in self.groups.iteritems():

+         for reg_group, registry in self.groups.items():

              basename = reg_group.split('.')[0]

              if basename == group_name and registry.external_plugin:

                  return True
@@ -389,7 +389,7 @@ 

              with open('.testlog.txt', 'w') as f:

                  for r in results:

                      f.write('\n' + 24 * ' ' +

-                             "('%s', '%s')," % (r.state, r.name))

+                             "('{}', '{}'),".format(r.state, r.name))

  

  

  # vim: set expandtab ts=4 sw=4:

file modified
+6 -6
@@ -20,24 +20,24 @@ 

  

  from __future__ import print_function

  

- import urllib

+ from six.moves.urllib.request import urlopen

  import json

  import sys

  import re

  import os

  import platform

  

- from url_bug import UrlBug

- from review_error import ReviewError

- from review_dirs import ReviewDirs

- from settings import Settings

+ from .url_bug import UrlBug

+ from .review_error import ReviewError

+ from .review_dirs import ReviewDirs

+ from .settings import Settings

  

  COPR_API_URL_TEMPLATE = 'https://copr.fedoraproject.org/api/coprs/build/{}/'

  

  

  def get_build_data(build_id):

      """ Fetch build data from COPR and return them as json """

-     build_data_file = urllib.urlopen(

+     build_data_file = urlopen(

          COPR_API_URL_TEMPLATE.format(build_id))

      return json.load(build_data_file)

  

@@ -30,17 +30,21 @@ 

      - warn user

  """

  

+ from __future__ import print_function

  import argparse

- import ConfigParser

  import getpass

  import logging

  import os

+ import rpm

  import stat

  import subprocess

  from subprocess import Popen, check_output

  import sys

- from xmlrpclib import Fault

- import rpm

+ 

+ import six.moves.configparser

+ from six.moves import input

+ from six.moves.xmlrpc_client import Fault

+ 

  from bugzilla.rhbugzilla import RHBugzilla

  

  SETTINGS_FILE = os.path.join(os.environ['HOME'],
@@ -109,7 +113,7 @@ 

      koji command and add a comment with this link on the review

      request.

      """

-     print 'Adding comment about the koji build'

+     print('Adding comment about the koji build')

      url = None

      for line in output_build.split('\n'):

          if 'Task info' in line:
@@ -143,7 +147,7 @@ 

          :arg configfile, name of the configuration file loaded.

          :arg sec, section of the configuration retrieved.

          """

-         parser = ConfigParser.ConfigParser()

+         parser = six.moves.configparser.ConfigParser()

          configfile = os.path.join(os.environ['HOME'], configfile)

          is_new = create_conf(configfile)

          parser.read(configfile)
@@ -170,7 +174,7 @@ 

          else:

              opts = set()

  

-         for name in self._dict.iterkeys():

+         for name in self._dict.keys():

              value = None

              if name in opts:

                  value = parser.get(section, name)
@@ -198,7 +202,7 @@ 

  

      def create_review_request(self, rename_request):

          """ Create the review request on the bugzilla. """

-         print 'Creating review'

+         print('Creating review')

          review_type = 'Review Request'

          if rename_request:

              review_type = 'Rename Request'
@@ -206,7 +210,7 @@ 

              'product': 'Fedora',

              'component': 'Package Review',

              'version': 'rawhide',

-             'short_desc': '%s: %s - %s' % (review_type,

+             'short_desc': '{}: {} - {}'.format(review_type,

                                             self.info['name'],

                                             self.info['summary']),

              'comment': BUG_COMMENT % (self.info['specurl'],
@@ -225,22 +229,22 @@ 

          try:

              bug = self.bzclient.createbug(**data)

              bug.refresh()

-         except Fault, ex:

-             print ex

+         except Fault as ex:

+             print(ex)

              self.login_bz()

              return self.create_review_request(rename_request)

          return bug

  

      def do_scratch_build(self, target='rawhide'):

          """ Starts a scratch build on koji. """

-         print 'Starting scratch build'

+         print('Starting scratch build')

          cmd = ['koji', 'build', '--scratch', target, self.srpmfile]

          self.log.debug(cmd)

          try:

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

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

              output = proc.communicate()[0]

-         except OSError, err:

-             print "OSError : %s" % str(err)

+         except OSError as err:

+             print("OSError : %s" % str(err))

          return (output, proc.returncode)

  

      def fill_urls(self):
@@ -248,7 +252,7 @@ 

          info in the settings.

          """

          complement_url = self.settings.upload_target.split('public_html/')[1]

-         url = 'https://%s.fedorapeople.org/%s/' % (

+         url = 'https://{}.fedorapeople.org/{}/'.format(

              self.username, complement_url)

          self.info['specurl'] = url + os.path.basename(self.specfile)

          self.info['srpmurl'] = url + os.path.basename(self.srpmfile)
@@ -266,25 +270,25 @@ 

          """

          bugbz = self.bzclient.query(

              #  'bug_status': ['CLOSED'],

-             {'short_desc': "Request: {0} -".format(self.info['name']),

+             {'short_desc': "Request: {} -".format(self.info['name']),

               'short_desc_type': 'allwordssubstr',

               'query_format': 'advanced',

               'component': 'Package Review'})

  

          if bugbz:

-             print 'Reviews for a package of the same name have been found:'

+             print('Reviews for a package of the same name have been found:')

          for bug in bugbz:

-             print ' ', bug, '-', bug.resolution

-             print "\t", bug.url

+             print(' ', bug, '-', bug.resolution)

+             print("\t", bug.url)

  

          if bugbz:

-             usr_inp = raw_input('Do you want to proceed anyway? [Y/N]')

+             usr_inp = input('Do you want to proceed anyway? [Y/N]')

              if usr_inp.lower() == ''  or usr_inp.lower().startswith('n'):

                  raise FedoraCreateReviewError()

  

      def login_bz(self):

          """ Login into the bugzilla. """

-         username = raw_input('Bugzilla username: ')

+         username = input('Bugzilla username: ')

          self.bzclient.login(user=username,

                              password=getpass.getpass())

  
@@ -296,7 +300,7 @@ 

              bzurl = 'https://bugzilla.redhat.com'

          else:

              bzurl = 'https://partner-bugzilla.redhat.com'

-             print "Using test bugzilla at: " + bzurl

+             print("Using test bugzilla at: " + bzurl)

  

          self.username = args.username

          if not self.username:
@@ -305,7 +309,7 @@ 

                  self.username = read_fas_user()

              except:

                  self.log.debug('Could not determine FAS username')

-                 self.username = raw_input('FAS username: ')

+                 self.username = input('FAS username: ')

  

          self.bzclient = RHBugzilla(url="%s/xmlrpc.cgi" % bzurl)

          self.srpmfile = os.path.expanduser(args.srpmfile)
@@ -329,32 +333,32 @@ 

          bug = self.create_review_request(args.rename_request)

          if not args.no_build:

              add_comment_build(output_build, bug)

-         print 'Review created at: %s/show_bug.cgi?id=%s' % (bzurl,

-                                                             bug.id)

-         print bug

+         print('Review created at: {}/show_bug.cgi?id={}'.format(bzurl,

+                                                             bug.id))

+         print(bug)

  

      def retrieve_description(self):

          """ Retrieve the description tag from a spec file. """

-         description = self.spec.packages[0].header[1005]

+         description = self.spec.packages[0].header[1005].decode('utf-8')

          self.log.debug('Description: %s', description)

          return description

  

      def retrieve_name(self):

          """ Retrieve the name tag from a spec file. """

-         name = self.spec.packages[0].header[1000]

+         name = self.spec.packages[0].header[1000].decode('utf-8')

          self.log.debug('Name: %s', name)

          return name

  

      def retrieve_summary(self):

          """ Retrieve the summary tag from a spec file. """

-         summary = self.spec.packages[0].header[1004]

+         summary = self.spec.packages[0].header[1004].decode('utf-8')

          self.log.debug('Summary: %s', summary)

          return summary

  

      def upload_files(self):

          """ Upload the spec file and the src.rpm files into

          fedorapeople.org, ensuring readable mode."""

-         print 'Uploading files into fedorapeople'

+         print('Uploading files into fedorapeople')

          self.log.debug('Target: %s', self.settings.upload_target)

          for path in [self.specfile, self.srpmfile]:

              mode = os.stat(path)[0]
@@ -364,10 +368,10 @@ 

                 self.username + "@" + self.settings.upload_target]

          self.log.debug(cmd)

          try:

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

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

              output = proc.communicate()[0]

-         except OSError, err:

-             print "OSError : %s" % str(err)

+         except OSError as err:

+             print("OSError : %s" % str(err))

          return (output, proc.returncode)

  

  
@@ -403,7 +407,7 @@ 

      try:

          ReviewRequest().main()

      except Exception as err:                 # pylint: disable=broad-except

-         print err

+         print(err)

  

  

  # vim: set expandtab ts=4 sw=4:

file modified
+13 -13
@@ -26,10 +26,10 @@ 

  from fnmatch import fnmatch

  from glob import glob

  

- from review_dirs import ReviewDirs

- from rpm_file import RpmFile

- from settings import Settings

- from source import Source

+ from .review_dirs import ReviewDirs

+ from .rpm_file import RpmFile

+ from .settings import Settings

+ from .source import Source

  

  

  class AbstractDataSource(object):
@@ -222,20 +222,20 @@ 

          if container:

              return self.rpms_by_pkg[container].filelist

          all_ = []

-         for pkg in self.rpms_by_pkg.iterkeys():

+         for pkg in self.rpms_by_pkg.keys():

              all_.extend(self.rpms_by_pkg[pkg].filelist)

          return all_

  

      def get(self, key=None):

          ''' Return RpmFile object for a package name key. '''

          self.init()

-         if key and key in self.rpms_by_pkg.iterkeys():

+         if key and key in self.rpms_by_pkg.keys():

              return self.rpms_by_pkg[key]

          return None

  

      def get_keys(self):

          self.init()

-         return self.rpms_by_pkg.iterkeys()

+         return self.rpms_by_pkg.keys()

  

  

  class SourcesDataSource(AbstractDataSource):
@@ -244,9 +244,9 @@ 

      def __init__(self, spec):

          AbstractDataSource.__init__(self)

          self.sources_by_tag = {}

-         for tag, url in spec.sources_by_tag.iteritems():

+         for tag, url in spec.sources_by_tag.items():

              self.sources_by_tag[tag] = Source(tag, url)

-         self.containers = [s.tag for s in self.sources_by_tag.itervalues()]

+         self.containers = [s.tag for s in self.sources_by_tag.values()]

          self.files_by_tag = {}

  

      def init(self):
@@ -255,7 +255,7 @@ 

      def _load_files(self, tag):

          """ Ensure that file list for tag is in files_by_tag. """

  

-         if tag in self.files_by_tag.iterkeys():

+         if tag in self.files_by_tag.keys():

              return

          source = self.sources_by_tag[tag]

          if not source.extract_dir:
@@ -277,7 +277,7 @@ 

              self._load_files(container)

              return self.files_by_tag[container]

          all_ = []

-         for key in self.files_by_tag.iterkeys():

+         for key in self.files_by_tag.keys():

              self._load_files(key)

              all_.extend(self.files_by_tag[key])

          return all_
@@ -287,12 +287,12 @@ 

          if not key:

              key = 'Source0'

              self.log.warning('Retrieving default source as Source0')

-         if key not in self.sources_by_tag.iterkeys():

+         if key not in self.sources_by_tag.keys():

              return None

          return self.sources_by_tag[key]

  

      def get_keys(self):

-         return self.sources_by_tag.iterkeys()

+         return self.sources_by_tag.keys()

  

      def get_files_sources(self):

          ''' Compatibility, to be removed. '''

file modified
+17 -16
@@ -23,7 +23,7 @@ 

  except ImportError:

      from FedoraReview.el_compat import check_output

  

- from settings import Settings

+ from .settings import Settings

  

  

  def init():
@@ -58,14 +58,14 @@ 

             ' '.join(list(set(pkgs)))]

      Settings.get_logger().debug("Running: %s", ' '.join(cmd))

      try:

-         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE)

+         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run %s", " ".join(cmd))

          return []

      deps = []

      while True:

          try:

-             line = dnf.stdout.next().strip()

+             line = next(dnf.stdout).strip()

          except StopIteration:

              return list(set(deps))

          name = line.rsplit('.', 2)[0]
@@ -85,14 +85,14 @@ 

             + ' '.join(list(set(pkgs)))]

      Settings.get_logger().debug("Running: %s", ' '.join(cmd))

      try:

-         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE)

+         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run %s", " ".join(cmd))

          return []

      provides = []

      while True:

          try:

-             line = dnf.stdout.next().strip()

+             line = next(dnf.stdout).strip()

          except StopIteration:

              return list(set(provides))

          provides.append(line)
@@ -121,7 +121,7 @@ 

      Settings.get_logger().debug("Running: %s", ' '.join(cmd))

  

      try:

-         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE)

+         dnf = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run %s", " ".join(cmd))

          return []
@@ -129,7 +129,7 @@ 

      pkgs = []

      while True:

          try:

-             line = dnf.stdout.next().strip()

+             line = next(dnf.stdout).strip()

          except StopIteration:

              return list(set(pkgs))

  
@@ -146,14 +146,14 @@ 

  

      cmd = ['rpm', '-ql', '--dump', '-p', pkg_filename]

      try:

-         rpm = subprocess.Popen(cmd, stdout=subprocess.PIPE)

+         rpm = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run %s", " ".join(cmd))

          return []

      dirs = []

      while True:

          try:

-             line = rpm.stdout.next().strip()

+             line = next(rpm.stdout).strip()

          except StopIteration:

              return dirs

          try:
@@ -162,7 +162,7 @@ 

              # E. g., when given '(contains no files)'

              continue

          mode = int(mode, 8)

-         if mode & 040000:

+         if mode & 0o40000:

              dirs.append(path)

  

  
@@ -180,7 +180,8 @@ 

                                '--enable-network', 'shell',

                                'rpm --qf %{NAME}\n -qf ' + path],

                               stdout=subprocess.PIPE,

-                              stderr=subprocess.PIPE)

+                              stderr=subprocess.PIPE,

+                              universal_newlines=True)

          path_owners = p.communicate()[0].split()

          if p.returncode != 0:

              continue
@@ -197,7 +198,7 @@ 

                 'shell', 'dnf repoquery -C --quiet --file ' + path]

          Settings.get_logger().debug("Running: %s", ' '.join(cmd))

          try:

-             lines = check_output(cmd).split()

+             lines = check_output(cmd, universal_newlines=True).split()

              lines = [l.strip() for l in lines]

              if not lines or not lines[0]:

                  continue
@@ -222,7 +223,7 @@ 

  

      Settings.get_logger().debug("Running: %s", ' '.join(cmd))

      try:

-         paths = check_output(cmd)

+         paths = check_output(cmd, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run dnf repoquery")

          return []
@@ -235,7 +236,7 @@ 

      cmd = ['rpm', '-ql', '--dump', '--nosignature', '-p', pkg_filename]

      Settings.get_logger().debug("Running: %s", ' '.join(cmd))

      try:

-         rpm = subprocess.Popen(cmd, stdout=subprocess.PIPE)

+         rpm = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)

      except OSError:

          Settings.get_logger().warning("Cannot run %s", " ".join(cmd))

          return []
@@ -243,7 +244,7 @@ 

      dirs = []

      while True:

          try:

-             line = rpm.stdout.next().strip()

+             line = next(rpm.stdout).strip()

          except StopIteration:

              return dirs, files

          try:
@@ -252,7 +253,7 @@ 

              # E. g., when given '(contains no files)'

              continue

          mode = int(mode, 8)

-         if mode & 040000:

+         if mode & 0o40000:

              dirs.append(path)

          else:

              files.append(path)

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

  

  ''' Download a scrath build from koji. '''

  

+ from __future__ import print_function

  import optparse

  import os

  import sys
@@ -18,16 +19,16 @@ 

      ''' Perform download of a single task. '''

  

      if opts.arches:

-         print 'Downloading %s rpms from task %i: %s' \

-             % (', '.join(opts.arches), task['id'], koji.taskLabel(task))

+         print('Downloading %s rpms from task %i: %s'

+               % (', '.join(opts.arches), task['id'], koji.taskLabel(task)))

      else:

-         print 'Downloading rpms from task %i: %s' \

-             % (task['id'], koji.taskLabel(task))

+         print('Downloading rpms from task %i: %s'

+               % (task['id'], koji.taskLabel(task)))

      base_path = koji.pathinfo.taskrelpath(task['id'])

      output = session.listTaskOutput(task['id'])

      prog_meter = urlgrabber.progress.TextMeter()

      if output == []:

-         print "This build is empty, no files to download"

+         print("This build is empty, no files to download")

          sys.exit(1)

      for filename in output:

          if opts.nologs and filename.endswith('log'):
@@ -62,8 +63,8 @@ 

              parser.error('Task %i did not complete successfully' % task['id'])

  

          if task['method'] == 'build':

-             print 'Getting rpms from children of task %i: %s' \

-                 % (task['id'], koji.taskLabel(task))

+             print('Getting rpms from children of task %i: %s'

+                   % (task['id'], koji.taskLabel(task)))

              task_opts = {'parent': task_id,

                           'method': 'buildArch',

                           'state': [koji.TASK_STATES['CLOSED']],

@@ -23,19 +23,19 @@ 

  import logging

  import os.path

  import re

- import urllib

+ from six.moves.urllib.request import FancyURLopener

  from subprocess import Popen, PIPE

  import hashlib

  

- from settings import Settings

- from review_error import ReviewError

+ from .settings import Settings

+ from .review_error import ReviewError

  

  

  class DownloadError(ReviewError):

      ''' Error in urlretrieve(). '''

      def __init__(self, code, url):

          ReviewError.__init__(

-             self, "Error %s downloading %s" % (code, url))

+             self, "Error {} downloading {}".format(code, url))

  

  

  class HelpersMixin(object):
@@ -51,11 +51,11 @@ 

          ''' Run a command using using subprocess, return output. '''

          self.log.debug(header + ': ' + cmd)

          cmd = cmd.split(' ')

-         proc = Popen(cmd, stdout=PIPE, stderr=PIPE)

+         proc = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)

          output, error = '', 'undefined'

          try:

              output, error = proc.communicate()

-         except OSError, e:

+         except OSError as e:

              self.log.debug("OS error, stderr: %s", error, exc_info=True)

              self.log.error("OS error running %s %s", ' '.join(cmd), str(e))

          return output
@@ -70,7 +70,7 @@ 

          '''

          ck = hashlib.new(Settings.checksum)

          with open(path, 'rb') as f:

-             for chunk in iter(lambda: f.read(8192), ''):

+             for chunk in iter(lambda: f.read(8192), b''):

                  ck.update(chunk)

          return ck.hexdigest()

  
@@ -82,12 +82,12 @@ 

              import socket

              socket.setdefaulttimeout(30)

  

-             istream = urllib.FancyURLopener().open(url)

+             istream = FancyURLopener().open(url)

              if istream.getcode() and istream.getcode() != 200:

                  raise DownloadError(istream.getcode(), url)

-             with open(path, 'w') as ostream:

+             with open(path, 'wb') as ostream:

                  octets = istream.read(32767)

-                 while octets != '':

+                 while octets:

                      ostream.write(octets)

                      octets = istream.read(32767)

          except IOError as err:
@@ -116,7 +116,7 @@ 

          """

          cmd = 'rpmdev-extract -qC ' + extract_dir + ' ' + archive

          cmd += ' &>/dev/null'

-         p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)

+         p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True)

          stdout, stderr = p.communicate()

          if p.returncode != 0:

              log = Settings.get_logger()
@@ -135,11 +135,9 @@ 

  

          problems = re.compile(r'(\d+)\serrors\,\s(\d+)\swarnings')

          lines = out.split('\n')[:-1]

-         err_lines = filter(lambda l: l.lower().find('error') != -1,

-                            lines)

+         err_lines = [l for l in lines if l.lower().find('error') != -1]

          if not err_lines:

-             Settings.get_logger().debug('Cannot parse rpmlint output: %s',

-                                         out)

+             Settings.get_logger().debug('Cannot parse rpmlint output: %s', out)

              return False, 'Cannot parse rpmlint output:'

  

          res = problems.search(err_lines[-1])

file modified
+17 -17
@@ -34,10 +34,10 @@ 

  except ImportError:

      from FedoraReview.el_compat import check_output

  

- from helpers_mixin import HelpersMixin

- from review_dirs import ReviewDirs

- from settings import Settings

- from review_error import ReviewError

+ from .helpers_mixin import HelpersMixin

+ from .review_dirs import ReviewDirs

+ from .settings import Settings

+ from .review_error import ReviewError

  

  

  _RPMLINT_SCRIPT = " mock  @config@ --chroot " \
@@ -47,7 +47,7 @@ 

  def _run_script(script):

      """ Run a script,  return (ok, output). """

      try:

-         p = Popen(script, stdout=PIPE, stderr=STDOUT, shell=True)

+         p = Popen(script, stdout=PIPE, stderr=STDOUT, shell=True, universal_newlines=True)

          output, error = p.communicate()

      except OSError as e:

          return False, e.strerror + ' stderr: ' + error
@@ -96,7 +96,7 @@ 

      if not paths:

          return '', macros

      arches = [p.rsplit('.', 2)[1] for p in paths]

-     if set(arches) == set(['noarch']):

+     if set(arches) == {'noarch'}:

          buildarch = 'noarch'

      else:

          buildarch = [a for a in arches if a != 'noarch'][0]
@@ -143,7 +143,7 @@ 

          macros = _add_disttag_macros({}, tag)

          buildarch, macros = _add_buildarch_macros(macros, paths)

          try:

-             _arch = check_output('rpm --eval %_arch'.split()).strip()

+             _arch = check_output('rpm --eval %_arch'.split(), universal_newlines=True).strip()

          except CalledProcessError:

              raise ReviewError("Can't evaluate 'rpm --eval %_arch")

          if buildarch == 'x86_64' and _arch != 'x86_64':
@@ -217,7 +217,7 @@ 

          header = header if header else ""

          self.log.debug(header + ' command: ' + ', '.join(cmd))

          try:

-             p = Popen(cmd, stdout=PIPE, stderr=STDOUT)

+             p = Popen(cmd, stdout=PIPE, stderr=STDOUT, universal_newlines=True)

              output, error = p.communicate()

              logging.debug(log_text(output, error), exc_info=True)

          except OSError:
@@ -235,7 +235,7 @@ 

          cmd = self._mock_cmd()

          cmd.extend(['-q', '--chroot', '--', 'rpm --eval %_topdir'])

          try:

-             self._topdir = check_output(cmd).strip()

+             self._topdir = check_output(cmd, universal_newlines=True).strip()

              self.log.debug("_topdir: %s", str(self._topdir))

          except (CalledProcessError, OSError):

              self.log.info("Cannot evaluate %topdir in mock, using"
@@ -260,7 +260,7 @@ 

          ''' Run rpm --eval <arg> inside mock, return output. '''

          cmd = self._mock_cmd()

          cmd.extend(['--quiet', '--chroot', '--', 'rpm --eval "' + arg + '"'])

-         return check_output(cmd).decode('utf-8').strip()

+         return check_output(cmd, universal_newlines=True).strip()

  

  # Last (cached?) output from rpmlint, list of lines.

      rpmlint_output = property(_get_rpmlint_output)
@@ -296,10 +296,10 @@ 

          on missing or multiple matches. Argument should have

          have name, version and release attributes.

          '''

-         pattern = '%s-%s*' % (nvr.name, nvr.version)

+         pattern = '{}-{}*'.format(nvr.name, nvr.version)

          paths = self._get_rpm_paths(pattern)

-         paths = filter(lambda p: p.endswith('.rpm') and

-                        not p.endswith('.src.rpm'), paths)

+         paths = [p for p in paths if p.endswith('.rpm') and

+                  not p.endswith('.src.rpm')]

          if not paths:

              raise ReviewError('No built package found for ' + nvr.name)

          elif len(paths) > 1:
@@ -315,7 +315,7 @@ 

  

          def get_package_srpm_path(spec):

              ''' Return path to srpm given a spec. '''

-             pattern = '*%s-%s*' % (spec.name, spec.version)

+             pattern = '*{}-{}*'.format(spec.name, spec.version)

              paths = self._get_rpm_paths(pattern)

              paths = [p for p in paths if p.endswith('.src.rpm')]

              if not paths:
@@ -335,7 +335,7 @@ 

  

      def get_package_debuginfo_paths(self, nvr):

          ''' Return paths to debuginfo rpms for given nvr.  '''

-         pattern = '%s-*debuginfo*-%s-*' % (nvr.name, nvr.version)

+         pattern = '{}-*debuginfo*-{}-*'.format(nvr.name, nvr.version)

          return self._get_rpm_paths(pattern)

  

      def get_builddir(self, subdir=None):
@@ -455,7 +455,7 @@ 

              return None

          else:

              self.log.debug('Build failed rc = %s', rc)

-             error = ReviewError('mock build failed, see %s/build.log',

+             error = ReviewError('mock build failed, see %s/build.log' %

                                  self.resultdir)

              error.show_logs = False

              raise error
@@ -484,7 +484,7 @@ 

          cmd.append('--init')

          self._run_cmd(cmd, '--init')

          cmd = self._mock_cmd()

-         rpms = filter(is_not_installed, list(set(packages)))

+         rpms = [p for p in set(packages) if is_not_installed(p)]

          if not rpms:

              return None

          self._clear_rpm_db()

file modified
+6 -5
@@ -19,12 +19,13 @@ 

  

  import os

  import os.path

- 

  from glob import glob

- from urlparse import urlparse

- from review_dirs import ReviewDirs

- from settings import Settings

- from abstract_bug import AbstractBug

+ 

+ from six.moves.urllib.parse import urlparse

+ 

+ from .review_dirs import ReviewDirs

+ from .settings import Settings

+ from .abstract_bug import AbstractBug

  

  

  class NameBug(AbstractBug):

file modified
+6 -4
@@ -21,9 +21,9 @@ 

  import inspect

  

  

- from review_error import ReviewError

- from settings import Settings

- from version import __version__, BUILD_ID

+ from .review_error import ReviewError

+ from .settings import Settings

+ from .version import __version__, BUILD_ID

  

  

  class _Flag(object):
@@ -43,9 +43,11 @@ 

          self.defined_in = defined_in

          self.value = False

  

-     def __nonzero__(self):

+     def __bool__(self):

          return bool(self.value)

  

+     __nonzero__ = __bool__

+ 

      def __str__(self):

          return self.value if self.value else ''

  

file modified
+14 -11
@@ -26,9 +26,9 @@ 

  

  from glob import glob

  

- from review_dirs import ReviewDirs

- from settings import Settings

- from version import __version__, BUILD_FULL

+ from .review_dirs import ReviewDirs

+ from .settings import Settings

+ from .version import __version__, BUILD_FULL

  

  # pylint: disable=W0611

  try:
@@ -72,7 +72,7 @@ 

      if len(spec) != 1:

          return '?', '?'

      path = spec[0].strip()

-     cs = check_output(['sha224sum', path]).split()[0]

+     cs = check_output(['sha224sum', path], universal_newlines=True).split()[0]

      path = path.rsplit('/', 1)[1]

      return path, cs

  
@@ -97,10 +97,10 @@ 

  

          return '3' + str(result.check.sort_key)

  

-     groups = list(set([hdr(test.group) for test in results]))

+     groups = list({hdr(test.group) for test in results})

      res = None

      for group in sorted(groups):

-         res = filter(lambda t: hdr(t.group) == group, results)

+         res = [r for r in results if hdr(r.group) == group]

          if not res:

              continue

          res = sorted(res, key=result_key)
@@ -133,15 +133,15 @@ 

          results = [r for r in results if r not in issues]

  

      output.write("\n\n===== MUST items =====\n")

-     musts = filter(lambda r: r.type == 'MUST', results)

+     musts = [r for r in results if r.type == 'MUST']

      _write_section(musts, output)

  

      output.write("\n===== SHOULD items =====\n")

-     shoulds = filter(lambda r: r.type == 'SHOULD', results)

+     shoulds = [r for r in results if r.type == 'SHOULD']

      _write_section(shoulds, output)

  

      output.write("\n===== EXTRA items =====\n")

-     extras = filter(lambda r: r.type == 'EXTRA', results)

+     extras = [r for r in results if r.type == 'EXTRA']

      _write_section(extras, output)

  

      for a in sorted(attachments):
@@ -182,7 +182,10 @@ 

  

          def txt2utf(txt):

              ''' Convert txt to utf-8. '''

-             return unicode(txt, encoding='utf-8', errors='replace')

+             if isinstance(txt, bytes):

+                 return txt.decode('utf-8', errors='replace')

+ 

+             return txt

  

          path = root.find('metadata/file').attrib['given-path']

          results = root.find('results')
@@ -203,5 +206,5 @@ 

              root = add_xml_result(root, result)

      dom = xml.dom.minidom.parseString(ET.tostring(root))

      prettyxml = dom.toprettyxml(indent='    ', encoding='utf-8')

-     with open('report.xml', 'w') as f:

+     with open('report.xml', 'wb') as f:

          f.write(prettyxml)

@@ -28,8 +28,8 @@ 

  import shutil

  import tempfile

  

- from review_error import ReviewError

- from settings     import Settings

+ from .review_error import ReviewError

+ from .settings     import Settings

  

  SRPM              = 'srpm'

  SRPM_UNPACKED     = 'srpm-unpacked'

@@ -22,23 +22,24 @@ 

  Tools for helping Fedora package reviewers

  '''

  

+ from __future__ import print_function

  import os.path

  import sys

  import time

- import ansi

- 

- from bugzilla_bug import BugzillaBug

- from check_base import SimpleTestResult

- from checks import Checks, ChecksLister

- from mock import Mock

- from name_bug import NameBug

- from review_dirs import ReviewDirs

- from review_error import ReviewError, SpecParseReviewError

- from settings import Settings

- from url_bug import UrlBug

- from copr_bug import CoprBug

- from version import __version__, BUILD_FULL

- from reports import write_xml_report

+ 

+ from . import ansi

+ from .bugzilla_bug import BugzillaBug

+ from .check_base import SimpleTestResult

+ from .checks import Checks, ChecksLister

+ from .mock import Mock

+ from .name_bug import NameBug

+ from .review_dirs import ReviewDirs

+ from .review_error import ReviewError, SpecParseReviewError

+ from .settings import Settings

+ from .url_bug import UrlBug

+ from .copr_bug import CoprBug

+ from .version import __version__, BUILD_FULL

+ from .reports import write_xml_report

  

  

  _EXIT_MESSAGE = """\
@@ -116,23 +117,23 @@ 

              self.checks.run_checks(output=output,

                                     writedown=not Settings.no_report)

          if not Settings.no_report:

-             print apply_color("Review template in: " + self.outfile,

-                               ansi.green)

-             print apply_color(_EXIT_MESSAGE, ansi.red)

+             print(apply_color("Review template in: " + self.outfile,

+                               ansi.green))

+             print(apply_color(_EXIT_MESSAGE, ansi.red))

  

      @staticmethod

      def _list_flags():

          ''' List all flags in simple, user-friendly format. '''

          checks_lister = ChecksLister()

-         for flag in checks_lister.flags.itervalues():

-             print flag.name + ': ' + flag.doc

+         for flag in checks_lister.flags.values():

+             print(flag.name + ': ' + flag.doc)

  

      @staticmethod

      def _list_plugins():

          ''' --display-plugins implementation. '''

          checks_lister = ChecksLister()

          plugins = checks_lister.get_plugins()

-         print ', '.join(plugins)

+         print(', '.join(plugins))

  

      @staticmethod

      def _list_checks():
@@ -141,58 +142,57 @@ 

          def list_data_by_file(files, checks_list):

              ''' print filename + flags and checks defined in it. '''

              for f in sorted(files):

-                 print 'File:  ' + f

-                 flags_by_src = filter(lambda c: c.defined_in == f,

-                                       checks_lister.flags.itervalues())

+                 print('File:  ' + f)

+                 flags_by_src = [c for c in checks_lister.flags.values()

+                                 if c.defined_in == f]

                  for flag in flags_by_src:

-                     print 'Flag: ' + flag.name

-                 files_per_src = filter(lambda c: c.defined_in == f,

-                                        checks_list)

-                 groups = list(set([c.group for c in files_per_src]))

+                     print('Flag: ' + flag.name)

+                 files_per_src = [c for c in checks_list

+                                  if c.defined_in == f]

+                 groups = list({c.group for c in files_per_src})

                  for group in sorted(groups):

  

                      def check_match(c):

                          ''' check in correct group and file? '''

                          return c.group == group and c.defined_in == f

  

-                     checks = filter(check_match, checks_list)

+                     checks = [c for c in checks_list if check_match(c)]

                      if checks == []:

                          continue

-                     print 'Group: ' + group

+                     print('Group: ' + group)

                      for c in sorted(checks):

-                         print '    %s: %s' % (c.name, c.text)

-                 print

+                         print('    {}: {}'.format(c.name, c.text))

+                 print()

  

          checks_lister = ChecksLister()

-         checks_list = list(checks_lister.get_checks().itervalues())

-         files = list(set([c.defined_in for c in checks_list]))

+         checks_list = list(checks_lister.get_checks().values())

+         files = list({c.defined_in for c in checks_list})

          list_data_by_file(files, checks_list)

-         deps_list = filter(lambda c: c.needs != [] and

-                            c.needs != ['CheckBuildCompleted'],

-                            checks_list)

+         deps_list = [c for c in checks_list

+                      if c.needs != [] and c.needs != ['CheckBuildCompleted']]

          for dep in deps_list:

-             print'Dependencies: ' + dep.name + ': ' + \

-                 os.path.basename(dep.defined_in)

+             print('Dependencies: ' + dep.name + ': ' +

+                   os.path.basename(dep.defined_in))

              for needed in dep.needs:

-                 print '     ' + needed

-         deprecators = filter(lambda c: c.deprecates != [], checks_list)

+                 print('     ' + needed)

+         deprecators = [c for c in checks_list if c.deprecates != []]

          for dep in deprecators:

-             print 'Deprecations: ' + dep.name + ': ' + \

-                 os.path.basename(dep.defined_in)

+             print('Deprecations: ' + dep.name + ': ' +

+                   os.path.basename(dep.defined_in))

              for victim in dep.deprecates:

-                 print '    ' + victim

+                 print('    ' + victim)

  

      @staticmethod

      def _print_version():

          ''' Handle --version option. '''

          # pylint: disable=superfluous-parens

-         print('fedora-review version ' + __version__ + ' ' + BUILD_FULL)

+         print(('fedora-review version ' + __version__ + ' ' + BUILD_FULL))

          print('external plugins:')

          checks_lister = ChecksLister()

-         for registry in checks_lister.groups.itervalues():

+         for registry in checks_lister.groups.values():

              if registry.external_plugin:

-                 print "{r.group} version {r.version} {r.build_id}".format(

-                     r=registry)

+                 print("{r.group} version {r.version} {r.build_id}".format(

+                     r=registry))

  

      def _do_run(self, outfile=None):

          ''' Initiate, download url:s, run checks a write report. '''

file modified
+13 -11
@@ -22,8 +22,8 @@ 

  import os

  import rpm

  

- from mock import Mock

- from settings import Settings

+ from .mock import Mock

+ from .settings import Settings

  

  

  class RpmFile(object):
@@ -52,9 +52,9 @@ 

          eq = rpm.RPMSENSE_EQUAL

          for ix in range(0, len(names) - 1):

              if not versions[ix]:

-                 dp.append(names[ix])

+                 dp.append(names[ix].decode('utf-8'))

                  continue

-             s = names[ix] + ' '

+             s = names[ix].decode('utf-8') + ' '

              if sense[ix] and eq:

                  s += '= '

              elif sense[ix] and lt:
@@ -64,7 +64,7 @@ 

              else:

                  s += 'What? : ' + bin(sense[ix])

                  self.log.warning("Bad RPMSENSE: %s", bin(sense[ix]))

-             s += versions[ix]

+             s += versions[ix].decode('utf-8')

              dp.append(s)

          return dp

  
@@ -86,9 +86,11 @@ 

      def header_to_str(self, tag):

          ''' Convert header in a string, to cope with API changes in F18'''

          if isinstance(self.header[tag], (dict, list)):

-             return ' '.join(self.header[tag])

- 

-         return self.header[tag]

+             return b' '.join(self.header[tag]).decode('utf-8')

+         elif self.header[tag]:

+             return self.header[tag].decode('utf-8')

+         else:

+             return None

  

      def _scriptlet(self, prog_tag, script_tag):

          ''' Return inline -p script, script or None. '''
@@ -141,19 +143,19 @@ 

      def filelist(self):

          ''' List of files in this rpm (expanded). '''

          self.init()

-         return self.header[rpm.RPMTAG_FILENAMES]

+         return [x.decode('utf-8') for x in self.header[rpm.RPMTAG_FILENAMES]]

  

      @property

      def requires(self):

          ''' List of requires, also auto-generated for rpm. '''

          self.init()

-         return self.header[rpm.RPMTAG_REQUIRES]

+         return [x.decode('utf-8') for x in self.header[rpm.RPMTAG_REQUIRES]]

  

      @property

      def provides(self):

          ''' List of provides, also auto-generated for rpm. '''

          self.init()

-         return self.header[rpm.RPMTAG_PROVIDES]

+         return [x.decode('utf-8') for x in self.header[rpm.RPMTAG_PROVIDES]]

  

      @property

      def format_requires(self):

file modified
+11 -8
@@ -19,6 +19,7 @@ 

  ''' Tools for helping Fedora package reviewers '''

  

  

+ from __future__ import print_function

  import argparse

  import grp

  import logging
@@ -30,9 +31,10 @@ 

  import sys

  

  from packaging import version

- import ansi

- from review_error import ReviewError

- from xdg_dirs import XdgDirs

+ 

+ from . import ansi

+ from .review_error import ReviewError

+ from .xdg_dirs import XdgDirs

  

  PARSER_SECTION = 'review'

  
@@ -58,7 +60,8 @@ 

  def _check_mock_ver():

      """ Returns mock version """

      try:

-         mock_ver = subprocess.check_output(['mock', '--version'])

+         mock_ver = subprocess.check_output(['mock', '--version'],

+                                            universal_newlines=True)

      except subprocess.CalledProcessError:

          mock_ver = '0'

      return mock_ver
@@ -250,7 +253,7 @@ 

          This instanciate the Settings object and load into the _dict

          attributes the default configuration which each available option.

          '''

-         for key, value in self.defaults.iteritems():

+         for key, value in self.defaults.items():

              setattr(self, key, value)

          self._dict = self.defaults

          self.log = None
@@ -305,7 +308,7 @@ 

          self.do_logger_setup()

          for opt in ['--assign', '--login', '--user', '-a', '-i', '-l']:

              if opt in sys.argv:

-                 print self.BZ_OPTS_MESSAGE

+                 print(self.BZ_OPTS_MESSAGE)

                  self.init_done = True

                  raise self.SettingsError()

          parser = argparse.ArgumentParser(
@@ -336,7 +339,7 @@ 

      def add_args(self, args):

          """ Load all command line options in args. """

          var_dict = vars(args)

-         for key, value in var_dict.iteritems():

+         for key, value in var_dict.items():

              setattr(self, key, value)

  

      @property
@@ -349,7 +352,7 @@ 

          if not self.log:

              return

          self.log.debug("Active settings after processing options")

-         for k, v in vars(self).iteritems():

+         for k, v in vars(self).items():

              if k in ['_dict', 'mock_config_options', 'log']:

                  continue

              try:

file modified
+5 -5
@@ -23,12 +23,12 @@ 

  import os.path

  import shutil

  

- from urlparse import urlparse

+ from six.moves.urllib.parse import urlparse

  

- from helpers_mixin import HelpersMixin, DownloadError

- from review_dirs import ReviewDirs

- from review_error import ReviewError

- from settings import Settings

+ from .helpers_mixin import HelpersMixin, DownloadError

+ from .review_dirs import ReviewDirs

+ from .review_error import ReviewError

+ from .settings import Settings

  

  

  class Source(HelpersMixin):

file modified
+25 -20
@@ -21,12 +21,13 @@ 

  

  import re

  import sys

- import urllib

+ from six.moves.urllib.parse import unquote

  

  import rpm

- from review_error import ReviewError, SpecParseReviewError

- from settings import Settings

- from mock import Mock

+ 

+ from .review_error import ReviewError, SpecParseReviewError

+ from .settings import Settings

+ from .mock import Mock

  

  

  def _lines_in_string(s, raw):
@@ -85,12 +86,12 @@ 

          parse_spec()

          sys.stdout = stdout

          self._packages = None

-         self.name_vers_rel = [self.expand_tag(rpm.RPMTAG_NAME),

-                               self.expand_tag(rpm.RPMTAG_VERSION),

+         self.name_vers_rel = [self.expand_tag(rpm.RPMTAG_NAME).decode('utf-8'),

+                               self.expand_tag(rpm.RPMTAG_VERSION).decode('utf-8'),

                                '*']

          update_macros()

          parse_spec()

-         self.name_vers_rel[2] = self.expand_tag(rpm.RPMTAG_RELEASE)

+         self.name_vers_rel[2] = self.expand_tag(rpm.RPMTAG_RELEASE).decode('utf-8')

  

      name = property(lambda self: self.name_vers_rel[0])

      version = property(lambda self: self.name_vers_rel[1])
@@ -109,13 +110,13 @@ 

                                   nvr.name, nvr.version, nvr.release)

                  return None

  

-         pkgs = [p.header[rpm.RPMTAG_NAME] for p in self.spec.packages]

+         pkgs = [p.header[rpm.RPMTAG_NAME].decode('utf-8') for p in self.spec.packages]

          pkgs = [p for p in pkgs if not self.get_files(p) is None]

          return [p for p in pkgs if check_pkg_path(p)]

  

      # pylint: disable=W1401

      def _get_lines(self, filename):

-         ''' Read line from specfile, fold \ continuation lines. '''

+         r''' Read line from specfile, fold \ continuation lines. '''

          with open(filename, "r") as f:

              lines = f.readlines()

          last = None
@@ -149,7 +150,7 @@ 

          if not pkg_name:

              return self.spec.packages[0]

          for p in self.spec.packages:

-             if p.header[rpm.RPMTAG_NAME] == pkg_name:

+             if p.header[rpm.RPMTAG_NAME].decode('utf-8') == pkg_name:

                  return p

          raise KeyError(pkg_name + ': no such package')

  
@@ -165,7 +166,7 @@ 

              tag = srctype + str(num)

              try:

                  result[tag] = \

-                     self.spec.sourceHeader.format(urllib.unquote(url))

+                     self.spec.sourceHeader.format(unquote(url))

              except Exception:

                  raise SpecParseReviewError("Cannot parse %s url %s"

                                             % (tag, url))
@@ -186,9 +187,9 @@ 

              elif token == '-f':

                  tokens.pop(0)

              else:

-                 return self.base_package + '-' + token

+                 return self.base_package.decode() + '-' + token

  

-         return self.base_package

+         return self.base_package.decode()

  

      def _parse_files(self, pkg_name):

          ''' Parse and return the %files section for pkg_name.
@@ -264,12 +265,14 @@ 

      @property

      def build_requires(self):

          ''' Return the list of build requirements. '''

-         return self.spec.sourceHeader[rpm.RPMTAG_REQUIRES]

+         return [x.decode('utf-8')

+                 for x in self.spec.sourceHeader[rpm.RPMTAG_REQUIRES]]

  

      def get_requires(self, pkg_name=None):

          ''' Return list of requirements i. e., Requires: '''

          package = self._get_pkg_by_name(pkg_name)

-         return package.header[rpm.RPMTAG_REQUIRES]

+         return [x.decode('utf-8')

+                 for x in package.header[rpm.RPMTAG_REQUIRES]]

  

      def get_package_nvr(self, pkg_name=None):

          ''' Return object with name, version, release for a package. '''
@@ -281,9 +284,9 @@ 

  

          package = self._get_pkg_by_name(pkg_name)

          nvr = NVR()

-         nvr.version = package.header[rpm.RPMTAG_VERSION]

-         nvr.release = package.header[rpm.RPMTAG_RELEASE]

-         nvr.name = package.header[rpm.RPMTAG_NAME]

+         nvr.version = package.header[rpm.RPMTAG_VERSION].decode('utf-8')

+         nvr.release = package.header[rpm.RPMTAG_RELEASE].decode('utf-8')

+         nvr.name = package.header[rpm.RPMTAG_NAME].decode('utf-8')

          return nvr

  

      def get_files(self, pkg_name=None):
@@ -292,12 +295,14 @@ 

          '''

          try:

              files = self._get_pkg_by_name(pkg_name).fileList

-             return \

-                 [l for l in [f.strip() for f in files.split('\n')] if l]

          except AttributeError:

              # No fileList attribute...

              # https://bugzilla.redhat.com/show_bug.cgi?id=857653

              return self._parse_files(pkg_name)

+         if files is None:

+             return None

+         return [l for l in [f.decode('utf-8').strip()

+                             for f in files.split(b'\n')] if l]

  

      def get_section(self, section, raw=False):

          '''

@@ -26,9 +26,9 @@ 

  from glob import glob

  from subprocess import call

  

- from helpers_mixin import HelpersMixin

- from review_dirs import ReviewDirs

- from settings import Settings

+ from .helpers_mixin import HelpersMixin

+ from .review_dirs import ReviewDirs

+ from .settings import Settings

  

  

  class SRPMFile(HelpersMixin):

file modified
+6 -6
@@ -18,11 +18,11 @@ 

  No xmlrpc involved, for better or worse.

  '''

  import os.path

- import urllib

+ from six.moves.urllib.request import urlretrieve

  

- from BeautifulSoup import BeautifulSoup

+ from bs4 import BeautifulSoup

  

- from abstract_bug import AbstractBug

+ from .abstract_bug import AbstractBug

  

  

  class UrlBug(AbstractBug):
@@ -45,13 +45,13 @@ 

          if self.bug_url.startswith('file://'):

              tmpfile = self.bug_url.replace('file://', '')

          else:

-             tmpfile = urllib.urlretrieve(self.bug_url)[0]

-         soup = BeautifulSoup(open(tmpfile))

+             tmpfile = urlretrieve(self.bug_url)[0]

+         soup = BeautifulSoup(open(tmpfile), features="lxml")

          links = soup.findAll('a')

          hrefs = [l.get('href') for l in links if l.get('href')]

          found = []

          for href in reversed(hrefs):

-             href = href.encode('ascii', 'ignore')

+             href = href.encode('ascii', 'ignore').decode('ascii')

              if '?' in href:

                  href = href[0: href.find('?')]

              if not href.startswith('http://') and \

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

  except ImportError:

      from FedoraReview.el_compat import check_output

  

- from review_error import ReviewError

+ from FedoraReview.review_error import ReviewError

  

  __version__ = 'Unknown'

  BUILD_FULL = 'Unknown (no version file nor git info)'
@@ -30,10 +30,9 @@ 

  def _setup():

      ''' Setup  the 'version' file from version.tmpl. '''

      try:

-         octets = check_output(['git', 'log', '--pretty=format:%h %ci', '-1'])

+         line = check_output(['git', 'log', '--pretty=format:%h %ci', '-1'], universal_newlines=True)

      except:

          raise VersionError("No version file and git not available.")

-     line = octets.decode('utf-8')

      words = line.split()

      commit = words.pop(0)

      date = words.pop(0)

file modified
+2 -2
@@ -47,9 +47,9 @@ 

  if os.path.exists(srcdir):

      sys.path.insert(0, srcdir)

  

- import create_review

+ from FedoraReview import create_review

  

  try:

      create_review.ReviewRequest().main()

  except Exception as err:

-     print err

+     print(err)

file modified
+4 -3
@@ -20,6 +20,7 @@ 

  Base class for FedoraReview tests

  '''

  

+ from __future__ import print_function

  import os

  import os.path

  import shutil
@@ -27,7 +28,7 @@ 

  import sys

  import unittest2 as unittest

  

- from urllib import urlopen

+ from six.moves.urllib.request import urlopen

  

  import srcpath                                   # pylint: disable=W0611

  from FedoraReview import Mock, ReviewDirs, Settings
@@ -68,7 +69,7 @@ 

  

      def tearDown(self):

          if 'REVIEW_TEST_GIT_STATUS' in os.environ:

-             print

+             print()

              subprocess.call('git status -uno | grep  "modified:"',

                              shell=True)

          os.chdir(self.startdir)
@@ -144,7 +145,7 @@ 

          self.assertEqual(rc, 0)

          sys.stdout = stdout

          checkdict = helper.checks.get_checks()

-         for check in checkdict.itervalues():

+         for check in checkdict.values():

              self.assertTrue(check.is_run)

              if check.is_passed or check.is_pending or check.is_failed:

                  self.assertIn(check.group, spec.groups_ok,

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

          self.bug.download_files()

          self.checks = Checks(self.bug.spec_file, self.bug.srpm_file)

          self.checks.run_checks(writedown=False)

-         for check in self.checks.checkdict.itervalues():

+         for check in self.checks.checkdict.values():

              #if not os.path.exists('test-R/rpms-unpacked'):

              #    os.mkdir('test-R/rpms-unpacked')

              if check.is_passed or check.is_pending or check.is_failed:

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

  

  from fr_testcase import FEDORA

  

- DEPLIST_OK = set(["bash",

+ DEPLIST_OK = {"bash",

                    "python",

                    "fedora-packager",

                    "python",
@@ -40,16 +40,16 @@ 

                    "python-straight-plugin",

                    "packagedb-cli",

                    "rpm-python",

-                   "devscripts-minimal"])

+                   "devscripts-minimal"}

  

  

- DIRLIST_OK = set(["/usr/share/doc/ruby-racc-1.4.5",

+ DIRLIST_OK = {"/usr/share/doc/ruby-racc-1.4.5",

                    "/usr/share/doc/ruby-racc-1.4.5/doc.en",

                    "/usr/share/doc/ruby-racc-1.4.5/doc.ja",

-                   "/usr/share/ruby/vendor_ruby/racc"])

+                   "/usr/share/ruby/vendor_ruby/racc"}

  DIRLIST_PKG = 'ruby-racc/ruby-racc/results/ruby-racc-1.4.5-9.fc17.noarch.rpm'

  

- OWNERS_OK = set(['rpm', 'yum', 'fedora-repos'])

+ OWNERS_OK = {'rpm', 'yum', 'fedora-repos'}

  

  

  class TestDeps(unittest.TestCase):
@@ -67,7 +67,7 @@ 

      def test_resolve(self):

          ''' Test resolving symbols -> packages. '''

          pkgs = deps.resolve(['config(rpm)', 'perl'])

-         self.assertEqual(set(['rpm', 'perl']), set(pkgs))

+         self.assertEqual({'rpm', 'perl'}, set(pkgs))

  

      @unittest.skipIf(not FEDORA, 'Fedora-only test')

      def test_list_dirs(self):

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

          self.assertEqual(len(glob('dist/*')), 4)

          lint = check_output(

                      'rpmlint -f test/rpmlint.conf dist/*spec dist/*rpm',

-                     shell=True)

+                     shell=True, universal_newlines=True)

          self.assertIn('0 error', lint)

          self.assertIn('0 warning', lint)

  

file modified
+8 -8
@@ -394,7 +394,7 @@ 

          self.assertTrue(check.is_passed)

          paths = check.checks.sources.find_all_re('.*[.]py')

          files = [os.path.basename(p) for p in paths]

-         self.assertEqual(set(files), set(['setup.py', '__init__.py']))

+         self.assertEqual(set(files), {'setup.py', '__init__.py'})

          files = check.checks.sources.get_filelist()

          self.assertEqual(len(files), 10)

  
@@ -452,7 +452,7 @@ 

                               '--no-build'])

          wdir = Mock.get_builddir('BUILD')

          len1 = len(glob.glob(os.path.join(wdir, "*")))

-         s = "cd {0}; ln -sf foo bar || :".format(wdir)

+         s = "cd {}; ln -sf foo bar || :".format(wdir)

          check_output(s, shell=True)

          Mock.builddir_cleanup()

          len2 = len(glob.glob(os.path.join(wdir, "*")))
@@ -530,11 +530,11 @@ 

          self.assertEqual(spec.version, '1.0')

          dist = Mock.get_macro('%dist', None, {})

          self.assertEqual(spec.release, '1' + dist)

-         self.assertEqual(spec.expand_tag('Release'), '1' + dist)

-         self.assertEqual(spec.expand_tag('License'), 'GPLv2+')

-         self.assertEqual(spec.expand_tag('Group'), 'Development/Languages')

+         self.assertEqual(spec.expand_tag('Release').decode('utf-8'), '1' + dist)

+         self.assertEqual(spec.expand_tag('License').decode('utf-8'), 'GPLv2+')

+         self.assertEqual(spec.expand_tag('Group').decode('utf-8'), 'Development/Languages')

          # Test rpm value not there

-         self.assertEqual(spec.expand_tag('PreReq'), None)

+         self.assertEqual(spec.expand_tag('PreReq').decode('utf-8'), None)

          # Test get sections

          expected = ['rm -rf $RPM_BUILD_ROOT']

          self.assertEqual(spec.get_section('%clean'), expected)
@@ -543,10 +543,10 @@ 

                     '/usr/bin/python setup.py build']

  

          build = spec.get_section('%build')

-         build = map(fix_usr_link, build)

+         build = [fix_usr_link(b) for b in build]

          self.assertIn(''.join(build), ''.join(expected))

          install = spec.get_section('%install')

-         install = map(fix_usr_link, install)

+         install = [fix_usr_link(x) for x in install]

          expected = ['LANG=C', 'export LANG', 'unset DISPLAY',

                      'rm -rf $RPM_BUILD_ROOT',

                      '/usr/bin/python setup.py install -O1 --skip-build'

file modified
+5 -14
@@ -12,6 +12,7 @@ 

  #

  # (C) 2011 - Alec Leamas

  

+ from __future__ import print_function

  import os

  import os.path

  import sys
@@ -32,20 +33,10 @@ 

  cmd = ["git", "--git-dir", os.path.join(main_dir, '.git'), "rev-parse", "--abbrev-ref", "HEAD"]

  cur_branch = check_output(cmd).strip()

  if cur_branch == "master":

-     print "\033[91mYou are running fedora-review from 'master' branch. This " \

-           "is probably not what you want to do. Master branch is equal to " \

-           "latest stable release. For development/bugreporting use " \

-           "'devel' branch. See CONTRIBUTE file for more details\033[0m"

- 

- # let's setup a proper git commit hooks so people don't commit ugly code

- # accidentally

- devnull = open('/dev/null', 'w')

- subprocess.call(['ln', '-s', '../../git-hooks/pre-commit',

-                  os.path.join(main_dir, '.git/hooks/pre-commit')],

-                  stderr=devnull)

- subprocess.call(['ln', '-s', '../../git-hooks/post-commit',

-                  os.path.join(main_dir, '.git/hooks/post-commit')],

-                  stderr=devnull)

+     print("\033[91mYou are running fedora-review from 'master' branch. This "

+           "is probably not what you want to do. Master branch is equal to "

+           "latest stable release. For development/bugreporting use "

+           "'devel' branch. See CONTRIBUTE file for more details\033[0m")

  

  review = ReviewHelper()

  rc = review.run()

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

  #    $ cd .git/hooks

  #    $ ln -s ../../update-version post-commit

  

+ from __future__ import print_function

  import os.path

  import os

  import sys
@@ -13,7 +14,7 @@ 

  here = os.path.dirname(os.path.realpath(__file__))

  os.chdir(os.path.join(here, 'src', 'FedoraReview'))

  if not os.access(os.getcwd(), os.W_OK):

-     print "I cannot write into " + os.getcwd() + ", giving up"

+     print("I cannot write into " + os.getcwd() + ", giving up")

      sys.exit(1)

  if os.path.exists('version'):

      os.remove('version')

How to test

(option 1) Copr

Almost up to date copr maintained by @eclipseo is at https://copr.fedorainfracloud.org/coprs/eclipseo/fedora-review/

$ sudo dnf copr enable eclipseo/fedora-review
$ sudo dnf install fedora-review

(option 2) From git

Get the code from this PR, if you don't have any, just clone my fork at the python3 branch:

$ git clone https://pagure.io/forks/churchyard/FedoraReview.git --branch python3 --single-branch
$ cd FedoraReview

If you already have it, make sure to git fetch and git reset --hard origin/python3.

Install the required packages:

$ sudo dnf install fedora-packager python3-beautifulsoup4 python3-bugzilla python3-packaging python3-straight-plugin python3-rpm dnf-plugins-core

Run Fedora review with python3 explicitly as you would normally run it:

$ python3 try-fedora-review -b 1234567 -m fedora-rawhide-x86_64

Report bugs as comments here

If there is a problem with this howto, say so.

If the program crashes, please say so and attach or copy the log here and the exact command to reproduce.

If some check used to work but doesn't work anymore, please say so and provide an example command to run to see the difference.

Report success as well

If everything works fine for you, we'd appreciate a note as well with a link to the review request for reference.


Original first comment of this PR follows:

I get currently stuck on chcks._ChecksLoader.Data.flags not getting populated.

Let me know if you need any help.

I got stuck. If you can get me unstuck, it would help :)

I'm working a bit on this... Things I have done:
- make urllib uses python2&3 compatible
- remove koji-download-scratch scripts because they were deprecated and they used urlgrabber which does not have python3 lib
- replace raw_input with input and other small python3 fixes
- fix string/bytes mess

Still TODO:
- packagedb-cli py does not work on py3
- fedora-cert py does not work on py3

  • packagedb-cli is not needed any more
  • fedora-cert is obsoleted by fedora-packager (py3) on rawhide

@churchyard how do you implement the CheckNoNameConflict check?

WRT fedora-cert/fedora-packager, is the new version going to be shipped in F29 as well?

how do you implement the CheckNoNameConflict check

no idea.

WRT fedora-cert/fedora-packager, is the new version going to be shipped in F29 as well?

I don't think so. This should target rawhide anyway.

packagedb-cli py does not work on py3

It actually does, it's just a matter of changing the python version

@churchyard

how do you implement the CheckNoNameConflict check
no idea.

Then why you say packagedb-cli is not needed anymore? If there are no other ways to get the functionalities offered by packagedb-cli, that means it's still needed.

@pingou Do you have any bugzilla link for this? Anyone I can ask about this?

Because AFAIK packagedb-cli connects to packagedb to get the info and we don't have that anymore.

Because AFAIK packagedb-cli connects to packagedb to get the info and we don't have that anymore.

Correct :)

Anyone I can ask about this?

Me :)

Because AFAIK packagedb-cli connects to packagedb to get the info and we don't have that anymore

It actually does, it's just a matter of changing the python version

ok I'm not sure I'm following you... So, packagedb-cli could work with py3, but that's not necessary because packagedb is not used anymore. Right?

What is used instead of packagedb? I could only find pkgdb2, but no packages are available in F29. Maybe in rawhide?

ok I'm not sure I'm following you... So, packagedb-cli could work with py3, but that's not necessary because packagedb is not used anymore. Right?

Correct

What is used instead of packagedb?

Pagure at https://src.fedoraproject.org whose API is documented at: https://src.fedoraproject.org/api/0/

Pagure at https://src.fedoraproject.org whose API is documented at: https://src.fedoraproject.org/api/0/

Perfect! I will have a look at it, thanks.

fedora-cert is obsoleted by fedora-packager (py3) on rawhide

@churchyard I cannot find any python3 file in the fedora-packager package on Rawhide. On the other hand, read_user_cert in fedora-cert seems to be obsoleted, since you don't need anymore a fedora cert. So I'm planning to replace that functionality with a read of fedora.upn (which is currently done inside read_user_cert too) + klist to check if the user has a kerberos ticket for FEDORAPROJECT.ORG

So, given https://pagure.io/FedoraReview/pull-request/318 and https://pagure.io/FedoraReview/pull-request/317 have been merged, the port to py3 should be feasible now with a bit of work! @churchyard I hope you don't mind if I open a new PR with the new changes I've done to make it work.

I can probably incorporate the few changes from that branch, yet I doubt it unblock me from where I'm blocked (see first comment here).

(I'm on vacation and I'll get to this next week.)

Hi, sorry I forgot to reply to the initial question. I'm not working on this right now as I have other things on my plate, however IIRC I have fixed the problem mentioned in the first comment and I have also removed python modules that are not supported anymore or that do not work with python 3. So I believe now it's just a matter of py2/3 compatibility (e.g. bytes/string, etc.)

Not yet unfortunately. It is on my TODO list and it is getting higher. This week sounds doable, but as always, something more urgent can happen.

rebased onto af2936016401bd789389722838ed19c6c003a731

5 years ago

1 new commit added

  • Make urllib uses python2&3 compatible
5 years ago

15 new commits added

  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

1 new commit added

  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
5 years ago

16 new commits added

  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

16 new commits added

  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

Good. So chcks._ChecksLoader.Data.flags is not getting populated on Python 2 and Python 3 consistently now \o/ :D

16 new commits added

  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

1 new commit added

  • Avoid unnecessary list construction
5 years ago

17 new commits added

  • Avoid unnecessary list construction
  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

Loaded plugins by load('plugins') on devel branch (with python2):

  • plugins.R
  • plugins.php
  • plugins.perl
  • plugins.java
  • plugins.ccpp
  • plugins.ruby
  • plugins.ocaml
  • plugins.fonts
  • plugins.python
  • plugins.generic
  • plugins.haskell
  • plugins.shell_api
  • plugins.generic_build
  • plugins.sugar_activity
  • plugins.generic_should
  • plugins.generic_autotools

Loaded plugins by load('plugins') on python3 branch (with both python2 and python3):

  • plugins.R
  • plugins.php
  • plugins.perl
  • plugins.java
  • plugins.ccpp
  • plugins.ruby
  • plugins.ocaml
  • plugins.fonts
  • plugins.python
  • plugins.haskell
  • plugins.shell_api
  • plugins.generic_build
  • plugins.sugar_activity
  • plugins.generic_autotools

Missing: plugins.generic_should and plugins.generic.- the latter is repsonsible for populating the flags.

17 new commits added

  • Avoid unnecessary list construction
  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

Got it, the files were not importable, but there was no exception, because the plugin loader ate it.
Errors should never pass silently!

3 new commits added

  • flake8 E124 closing bracket does not match visual indentation
  • flake8 E251 unexpected spaces around keyword / parameter equals
  • flake8 E402 module level import not at top of file
5 years ago

17 new commits added

  • Avoid unnecessary list construction
  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

Anyway I've successfully run a review.

Now I need to figure out how to run the tests as well.

Also, there is soo much non PEP8 stuff and FedoraReview keeps readding a pre commit hook for pylint and pep8. We need to get rid of it and eventually fix the style (maybe utilize black?).

Yeah, I need to kill those things. I hate them.

Is there a documented way to run the tests? IV'e tried pytest, but it's FFFFFFFFFFFFFFFFFFFFF on devel and here alike.

@churchyard Unfortunately, I'm not sure, as it doesn't work for me either. There's the script in the test directory. I think it was last tested on Fedora 25, which I haven't tried to see if it works still yet...

1 new commit added

  • TypeError: cannot use a string pattern on a bytes-like object
5 years ago

18 new commits added

  • TypeError: cannot use a string pattern on a bytes-like object
  • Avoid unnecessary list construction
  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

@churchyard Unfortunately, it looks like some of the tests depend on it fetching fedora-review releases, which needs this done first: https://pagure.io/fedora-infrastructure/issue/7613

@churchyard Unfortunately, it looks like some of the tests depend on it fetching fedora-review releases, which needs this done first: https://pagure.io/fedora-infrastructure/issue/7613

@ngompa you got the releases here [1] , IIRC just latest release was not tagged

[1]
https://pagure.io/FedoraReview/releases

As for the Python 3 compatibility: I'm not 100% happy with how the bytes/text separation is handled (it's mostly patched in a exception driven way, putting encodes/decoded everywhere where it blew up). Most likely we decode something only to encode it back in a different function.

It would be great if we diagram the data flow and agree whether we want to work with sequence of bytes or text and only do encoding/decoding at boundary level. RPM metadata is generally bytes.

Excellent read: https://portingguide.readthedocs.io/en/latest/strings.html

I however won't have time to put effort into this (and the code structure is kinda crazy frankly).

rebased onto 9d32bcb41921b9eb0169540e329fdf8001c76af9

5 years ago

1 new commit added

  • Don't decode text, that's not possible
5 years ago

Fedora 29: No match for argument: python3-straight-plugin :(

$ rpm -qi python3-straight-plugin
Name        : python3-straight-plugin
Version     : 1.5.0
Release     : 5.fc29
Architecture: noarch
Install Date: Wed Mar  6 12:51:06 2019
Group       : Unspecified
Size        : 23307
License     : BSD
Signature   : RSA/SHA256, Fri Jul 20 02:31:40 2018, Key ID a20aa56b429476b4
Source RPM  : python-straight-plugin-1.5.0-5.fc29.src.rpm
Build Date  : Fri Jul 20 02:31:28 2018
Build Host  : buildvm-ppc64le-07.ppc.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : https://github.com/ironfroggy/straight.plugin/
Bug URL     : https://bugz.fedoraproject.org/python-straight-plugin
Summary     : Python plugin loader
Description :
straight.plugin is a Python plugin loader inspired by twisted.plugin with two
important distinctions:

 - Fewer dependencies
 - Python 3 compatible

The system is used to allow multiple Python packages to provide plugins within
a namespace package, where other packages will locate and utilize. The plugins
themselves are modules in a namespace package where the namespace identifies
the plugins in it for some particular purpose or intent.
$ sudo dnf reinstall python3-straight-plugin
Last metadata expiration check: 1:45:43 ago on Fri Mar  8 12:29:29 2019.
Dependencies resolved.
================================================================================
 Package                      Arch        Version             Repository   Size
================================================================================
Reinstalling:
 python3-straight-plugin      noarch      1.5.0-5.fc29        fedora       17 k

Transaction Summary
================================================================================

Total download size: 17 k
Installed size: 23 k
Is this ok [y/N]: 

Got issue with bumping the version for a local build:

$ env PYTHONPATH=src ./update-version
Traceback (most recent call last):
File "./update-version", line 22, in <module>
import version
File "/home/bob/Downloads/FedoraReview/src/FedoraReview/version.py", line 17, in <module>
from .review_error import ReviewError
ValueError: Attempted relative import in non-package

I don't think ".review_error" should be relative as it is called
directly.

I don't know what "called directly" means in this context but the problem is that version.py is clearly used from multiple places in multiple ways. Let em check what can be done about that.

1 new commit added

  • Use absolute import in version.py to fix update-version
5 years ago

I've pushed an immediate fix, but update-version is not ported at all. Will work on that.

I'd like to test this; don't you have a copr build for easier testing?

1 new commit added

  • Use print function in update-version
5 years ago

No I don't. I've considered this more flexible as I push fixes as we speak. There is no complicated setup. You clone and run. You get missing deps once.

If that is indeed a blocker for you, I can certainly do a copr build.

Fedora 29: No match for argument: python3-straight-plugin :(

Sorry, I have misconfigured repos.

I'd like to test this; don't you have a copr build for easier testing?

If that is indeed a blocker for you, I can certainly do a copr build.

F28/F29 only as Rawhide is borked on COPR for now:

https://copr.fedorainfracloud.org/coprs/eclipseo/fedora-review/

Get an error in an error message:

ERROR: 'mock build failed, see %s/build.log'

%s is not replaced with correct dir here.

See src/FedoraReview/mock.py:458

1 new commit added

  • Update spec for Python 3
5 years ago

1 new commit added

  • Fix bad string modulo
5 years ago

Thanks. I'll commit the spec here. several notes:

please remove from the spec:

  • Requires: packagedb-cli
  • Requires: packagedb-cli
  • Requires: python3-kitchen

Anyway, fixed the %s thing.

Typo in the SPEC:

chmod -c 0755 %{buidlroot}%{_bindir}/*

should be

chmod -c 0755 %{buildroot}%{_bindir}/*

1 new commit added

  • Spec typo
5 years ago

Also you mix $RPM_BUILD_ROOT with %{buildroot}, should be the same for all.

1 new commit added

  • Spec: Use %{buildroot} everywhere
5 years ago

I have done one review using this code and works for me.

Thank you @msuchy. For reference, what kind of project it was? E.g. I've tested this with Python projects, but not much with other kinds.

pathfix.py -pni "%{__python3} %{py3_shbang_opts}" %{buildroot}%{python3_sitearch} %{buildroot}%{_bindir}/*

Are you sure it should not be %{buildroot}%{python3_sitelib} here? I've got a build failure because that path is not present:

+ pathfix.py -pni '/usr/bin/python3 -s' /builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/lib64/python3.7/site-packages /builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/fedora-create-review /builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/fedora-review /builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/koji-download-scratch
/builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/lib64/python3.7/site-packages: cannot open: FileNotFoundError(2, 'No such file or directory')
/builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/fedora-create-review: updating
/builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/fedora-review: updating
/builddir/build/BUILDROOT/fedora-review-0.7.0-0.2.beta.fc29.x86_64/usr/bin/koji-download-scratch: updating

no I'm not, I've blindly copy pasted it form an archfull package, silly me

1 new commit added

  • Spec: This is noarch
5 years ago

For reference, what kind of project it was?

Python as well.

I used it once on a RPMFusion package, cinelerra-gg:

Generated by fedora-review 0.7.0 (b89c61c) last change: 2019-03-08
Command line :/usr/bin/fedora-review -x CheckIfDepsDeprecated,CheckOwnDirs --mock-config /home/bob/packaging/mock-rpmfusion.cfg -n cinelerra-gg
Buildroot used: f30-candidate-x86_64
Active plugins: C/C++, Shell-api, Generic
Disabled plugins: Ruby, PHP, R, Perl, Ocaml, fonts, Haskell, SugarActivity, Java, Python
Disabled flags: EPEL6, EPEL7, DISTTAG, BATCH, EXARCH

Worked fine. I will use it for my daily reviews to see if all plugins work as expected.

Worked fine on Perl package.

I have tried it on a Haskell project and it worked fine there.

On a Rust crate (this review request: bzr#1679583), I got the following backtrace:

03-09 19:39 root         DEBUG    Build command: "mock" "-r" "fedora-rawhide-x86_64" "--no-bootstrap-chroot" "--no-cleanup-after" "--no-clean" "--resultdir=/home/dan/fedora-scm/FedoraReview/1679583-rust-lmdb-sys/results" --rebuild /home/dan/fedora-scm/FedoraReview/1679583-rust-lmdb-sys/srpm/rust-lmdb-sys-0.8.0-1.fc30.src.rpm 2>&1 | tee build.log | egrep "Results and/or logs|ERROR"
03-09 19:46 root         DEBUG    _topdir: /builddir/build
03-09 19:46 root         INFO     Build completed
03-09 19:46 root         DEBUG    Exception down the road...
Traceback (most recent call last):
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 299, in get_files
    for f in files.split(b'\n')] if l]
AttributeError: 'NoneType' object has no attribute 'split'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/review_helper.py", line 239, in run
    self._do_run(outfile)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/review_helper.py", line 229, in _do_run
    self._do_report(outfile)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/review_helper.py", line 99, in _do_report
    self._run_checks(self.bug.spec_file, self.bug.srpm_file, outfile)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/review_helper.py", line 118, in _run_checks
    writedown=not Settings.no_report)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/checks.py", line 378, in run_checks
    run_check(name)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/checks.py", line 352, in run_check
    check.run()
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/plugins/generic_build.py", line 200, in run
    listfiles()
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/plugins/generic_build.py", line 173, in listfiles
    for pkg in self.spec.packages:
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 262, in packages
    self._packages = self._get_packages()
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 114, in _get_packages
    pkgs = [p for p in pkgs if not self.get_files(p) is None]
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 114, in <listcomp>
    pkgs = [p for p in pkgs if not self.get_files(p) is None]
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 303, in get_files
    return self._parse_files(pkg_name)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 204, in _parse_files
    name = self._parse_files_pkg_name(line)
  File "/home/dan/fedora-scm/FedoraReview/src/FedoraReview/spec_file.py", line 190, in _parse_files_pkg_name
    return self.base_package + '-' + token
TypeError: can't concat str to bytes
03-09 19:46 root         ERROR    Exception down the road...(logs in /home/dan/.cache/fedora-review.log)
03-09 19:46 root         DEBUG    Report completed:  474.021 seconds

Happens with Golang packages as well or any package which doesn't have a %files section for the main package but only for the subpackages.

1 new commit added

  • Fix packages with no main %files section
5 years ago

I've fixed the immediate problem. The rest of the check takes a while, so not sure if it will finish.

That don't seem to solve tho original problem at https://pagure.io/fork/churchyard/FedoraReview/blob/db1602666f376f5372c9e55a43fb227735057892/f/src/FedoraReview/spec_file.py#_301 where files can be None, thus the function should return None.

so the AttributeError try there is for a different AttributeError, oh my

1 new commit added

  • fixup! Fix packages with no main %files section
5 years ago

OK. What about now?

Note: I'll be pushing fixup commits and won't rebase, so people can pull easier. Will autosquash before merging this.

It is working for me on Golang.

bzr#1679583: The CheckIfDepsDeprecated runs forever, checking provides of a lot of packages (including stuff like f29-backgrounds-kde), not sure if that problem is relevant to this port or something else.

Not because of the port, CheckIfDepsDeprecated has always be heavy because is checks Provides for each RR and BR. Not sure how f29-backgrounds-kde got mixed into this for a Rust package, I'll have to look into this.

There seems to be an issue with processing the new Rust split packages:

dnf repoquery -C --whatprovides "(crate(pkg-config/default)"

returns a gigantic list of packages, and we check each provides for each package returned so it takes forever.

dnf repoquery -C --whatprovides "(crate(pkg-config)" doesn't have this problem.

so not a regression? good (at least good for this PR)

Ha I think it's because the script doesn't handle rich deps.

I've merged @eclipseo's fix into devel branch.

@churchyard, if you want to pick that up, just click the rebase button in this PR. :wink:

rebased onto 106e2980c38c7bac7c3f19e8b91e77d97adb310c

5 years ago

Rebased and updated the instructions here so rebases are possible.

24 new commits added

  • Fix packages with no main %files section
  • Fix bad string modulo
  • Update spec for Python 3
  • Use print function in update-version
  • Use absolute import in version.py to fix update-version
  • Don't decode text, that's not possible
  • TypeError: cannot use a string pattern on a bytes-like object
  • Avoid unnecessary list construction
  • Use compregensions instead of map/reduce/filter + various bytes/str fixes
  • Other python3 compatibility fixes
  • Use six.moves.input() instead of raw_input()
  • Replace a filter call with list comprehension
  • Make urllib uses python2&3 compatible
  • Octal Literals
  • Donwload files as binary
  • Work with strings, not bytes
  • urlretrieve six.moves
  • String output from subprocess
  • Relative imports
  • Use BeautifulSoup 4
  • Replace iter(keys|values|items) with the non-iter ones
  • New except syntax
  • Six moves
  • Use the print function
5 years ago

Now bzr#1679583 gives me:

subprocess.CalledProcessError: Command '['dnf', 'repoquery', '-C', '-l', 'filesystem']' returned non-zero exit status 1.

Trying if I can reproduce with devel branch.

Not a regression: https://pagure.io/FedoraReview/issue/331

Not a problem with your patch. It happens to me sometimes, I just do

sudo rm -rf /var/cache/dnf/*
sudo dnf makecache

What's missing here is fedora-create-review, too...

I copied src/fedora-create-review to try-fedora-create-review, and applied this patch to get the search paths right (basically doing what try-fedora-review does), plus fix a few Python2-isms:

--- src/fedora-create-review    2019-03-10 19:57:02.019498145 -0400
+++ try-fedora-create-review    2019-03-10 20:00:20.607535614 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/python -tt
+#!/usr/bin/python3 -tt
 #    -*- coding: utf-8 -*-

 #    This program is free software; you can redistribute it and/or modify
@@ -35,21 +35,14 @@
 import sys


-# Load from site lib
-from distutils.sysconfig import get_python_lib
-sitedir = os.path.join(get_python_lib(), 'FedoraReview')
-if os.path.exists(sitedir):
-    sys.path.insert(0, sitedir)
-
-# Load from development lib
-here = os.path.dirname(os.path.realpath(__file__))
-srcdir = os.path.join(here, 'FedoraReview')
-if os.path.exists(srcdir):
-    sys.path.insert(0, srcdir)
+main_dir = os.path.dirname(os.path.realpath(__file__))

-import create_review
+pkg_dir = os.path.join(main_dir, 'src')
+sys.path.insert(0, pkg_dir)
+
+from FedoraReview import create_review

 try:
     create_review.ReviewRequest().main()
 except Exception as err:
-    print err
+    print(err)

The resulting Review Request is here. As you can see, it messes up the title a bit, as well as the description posted in the summary.

I'd open a PR to fix it https://pagure.io/fork/qulogic/FedoraReview/tree/python3 but Pagure is taking too long to open the PR dialog.

2 new commits added

  • Decode rpm information used to create review requests.
  • Fix fedora-create-review on Python 3.
5 years ago

This COPR is still kept up to date if you want to try the patch:

https://copr.fedorainfracloud.org/coprs/eclipseo/fedora-review

@churchyard I've got an actual bug from the Py3 conversion.

I was reviewing a R package. The fedora-review.log says:

03-11 16:20 root         DEBUG    Running check: RCheckLatestVersionIsPackaged
03-11 16:20 root         DEBUG    Found in: https://cran.r-project.org/src/contrib/PACKAGES
03-11 16:20 root         DEBUG    Exception down the road...
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 239, in run
    self._do_run(outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 229, in _do_run
    self._do_report(outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 99, in _do_report
    self._run_checks(self.bug.spec_file, self.bug.srpm_file, outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 118, in _run_checks
    writedown=not Settings.no_report)
  File "/usr/lib/python3.7/site-packages/FedoraReview/checks.py", line 378, in run_checks
    run_check(name)
  File "/usr/lib/python3.7/site-packages/FedoraReview/checks.py", line 352, in run_check
    check.run()
  File "/usr/lib/python3.7/site-packages/FedoraReview/check_base.py", line 263, in run
    self.run_on_applicable()
  File "/usr/lib/python3.7/site-packages/FedoraReview/plugins/R.py", line 164, in run_on_applicable
    up_version = self.get_upstream_r_package_version()
  File "/usr/lib/python3.7/site-packages/FedoraReview/plugins/R.py", line 72, in get_upstream_r_package_version
    ver = res.group().split('\n')[1]
TypeError: a bytes-like object is required, not 'str'

1 new commit added

  • Split bytes by bytes
5 years ago

Please verify it's fixed now.

Yes but not exactly, the problem is propagated to the line below:

03-11 17:19 root         DEBUG    Exception down the road...
Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 239, in run
    self._do_run(outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 229, in _do_run
    self._do_report(outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 99, in _do_report
    self._run_checks(self.bug.spec_file, self.bug.srpm_file, outfile)
  File "/usr/lib/python3.7/site-packages/FedoraReview/review_helper.py", line 118, in _run_checks
    writedown=not Settings.no_report)
  File "/usr/lib/python3.7/site-packages/FedoraReview/checks.py", line 378, in run_checks
    run_check(name)
  File "/usr/lib/python3.7/site-packages/FedoraReview/checks.py", line 352, in run_check
    check.run()
  File "/usr/lib/python3.7/site-packages/FedoraReview/check_base.py", line 263, in run
    self.run_on_applicable()
  File "/usr/lib/python3.7/site-packages/FedoraReview/plugins/R.py", line 164, in run_on_applicable
    up_version = self.get_upstream_r_package_version()
  File "/usr/lib/python3.7/site-packages/FedoraReview/plugins/R.py", line 73, in get_upstream_r_package_version
    version = ver.replace('Version:', '').strip()
TypeError: a bytes-like object is required, not 'str'

Also:
R.py:164 should be

    up_version = self.get_upstream_r_package_version().decode('utf-8')

Otherwise it will fail too.

@eclipseo Thanks. Iv'e added you to my fork, you should be able to push there. Feel free to do so.

1 new commit added

  • Convert get_upstream_r_package_version to use bytes
5 years ago

rebased onto f2c8b0297bb5555ccb92de8f38323c1bc4af8682

5 years ago

dnf repoquery -C --whatprovides "(crate(pkg-config/default)"

Can you check what is populating this? It seems that something does "str.split()" where it should not.

rebased onto ca8eb49b8776be61b8988b1c0eb01faf27dcf8e0

5 years ago

rebased onto de182e88903219bdd2d5f75ba65d10d044bf4add

5 years ago

I've tested fedora-create-review and it's not working as expected, there's b'text' everywhere:

See https://bugzilla.redhat.com/show_bug.cgi?id=1688361

Review Request: b'golang-github-rogpeppe-fastuuid' - b'Fast generation of 192-bit UUIDs'

Description:
b'\nPackage fastuuid provides fast UUID generation of 192 bit universally unique\nidentifiers. It does not provide formatting or parsing of the identifiers\n(it is assumed that a simple hexadecimal or base64 representation is\nsufficient, for which adequate functionality exists elsewhere).'

Disregards the previous comment, I didn't update to the latest version.

rebased onto 4ce9578

5 years ago

So how are we looking on this? It seems like people are mostly positive about the recent changeset?

I'd like to test more, I've yet to test the Ruby plugin in action.

@eclipseo I have a ruby package for you :wink: I meant to submit this package a while ago, actually, but never got around to doing it.

https://bugzilla.redhat.com/show_bug.cgi?id=1689542

1 new commit added

  • Apply pyupgrade tool
5 years ago

1 new commit added

  • Send the commit hooks to a farm upstate
5 years ago

For the record, I've just ditched the commit hooks because I consider them horrible.

I also looked at using black and I like the result (because later you can actually use flake8 and similar to get other code smells). But let's merge this first before we go that way, because I'm afraid of conflicts.

I've applied pyupgrade because the diff wasn't so enormous. In case of conflicts, the commit message contains the command, so we can rerun it on devel branch if needed.

@decathorpe:

Issues:
=======
- Package contains Requires: ruby(release).

...

Ruby:
[ ]: Platform dependent files must all go under %{gem_extdir_mri}, platform
     independent under %{gem_dir}.
[x]: Gem package must not define a non-gem subpackage
[x]: Macro %{gem_extdir} is deprecated.
[x]: Gem package is named rubygem-%{gem_name}
[x]: Package contains BuildRequires: rubygems-devel.
[x]: Gem package must define %{gem_name} macro.
[x]: Pure Ruby package must be built as noarch
[x]: Package does not contain Requires: ruby(abi).

...

Ruby:
[!]: Test suite of the library should be run.
[x]: Gem package should exclude cached Gem.
[x]: Gem should use %gem_install macro.
[x]: gems should not require rubygems package
[x]: Specfile should use macros from rubygem-devel package.


(That is consistent with the devel branch.)

So are we in agreement that this is in good shape to merge now? @churchyard @decathorpe @eclipseo

For me that seems good. I don't know what other package I might need to test, maybe Java one's, which have a specific plugin. Other languages don't have specific plugins and should work fine.

Let's merge this, release it as beta, put it in rawhide and deal with breakage as regression?

Got this even from git:

- This seems like a Java package, please install fedora-review-plugin-java
  to get additional checks

That seems kinda weird thing to get from git version, but... IDK.

Also:

Java:
[x]: Bundled jar/class files should be removed before build

Running on devel branch now.

Behavior consistent, no regression.

That sounds like an OK to merge?

1 new commit added

  • Update README
5 years ago

Pull-Request has been merged by ngompa

5 years ago

@churchyard Do you want to send a PR to blacken the codebase before I release 0.7.0?

A release doesn't need to wait, but I'll work on it ~Tueasday.

Then I'll cut a release now. :100:

Hmm, after fixing the test run execution, I get the following error:

======================================================================
ERROR: Run all automated review checks
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/fedora-review-release-gbkSj/fedora-review-0.7.0/test/test_R_checks.py", line 104, in test_all_checks
    self.checks.run_checks(writedown=False)
  File "/tmp/fedora-review-release-gbkSj/fedora-review-0.7.0/src/FedoraReview/checks.py", line 378, in run_checks
    run_check(name)
  File "/tmp/fedora-review-release-gbkSj/fedora-review-0.7.0/src/FedoraReview/checks.py", line 352, in run_check
    check.run()
  File "/tmp/fedora-review-release-gbkSj/fedora-review-0.7.0/src/FedoraReview/check_base.py", line 263, in run
    self.run_on_applicable()
  File "/tmp/fedora-review-release-gbkSj/fedora-review-0.7.0/src/FedoraReview/plugins/R.py", line 164, in run_on_applicable
    up_version = self.get_upstream_r_package_version().decode('utf-8')
AttributeError: 'NoneType' object has no attribute 'decode'

@churchyard Could you take a look at this?

I was able to run them by doing the following (after checking out current devel):

$ sudo dnf install python3-pylint python3-pycodestyle python3-mock python3-virtualenv python3-beautifulsoup4 python3-bugzilla python3-packaging python3-straight-plugin python3-rpm make
$ ./make_release

Metadata Update from @ngompa:
- Request assigned

5 years ago
Metadata
Changes Summary 44
+2 -2
file changed
README
+25 -31
file changed
fedora-review.spec
-14
file removed
git-hooks/post-commit
-56
file removed
git-hooks/pre-commit
+9 -8
file changed
plugins/R.py
+4 -4
file changed
plugins/ccpp.py
+27 -28
file changed
plugins/generic.py
+4 -3
file changed
plugins/generic_autotools.py
+2 -9
file changed
plugins/generic_build.py
+10 -10
file changed
plugins/generic_should.py
+2 -2
file changed
plugins/ruby.py
+11 -11
file changed
plugins/shell_api.py
+9 -9
file changed
src/FedoraReview/__init__.py
+6 -6
file changed
src/FedoraReview/abstract_bug.py
+3 -3
file changed
src/FedoraReview/bugzilla_bug.py
+21 -3
file changed
src/FedoraReview/check_base.py
+18 -18
file changed
src/FedoraReview/checks.py
+6 -6
file changed
src/FedoraReview/copr_bug.py
+38 -34
file changed
src/FedoraReview/create_review.py
+13 -13
file changed
src/FedoraReview/datasrc.py
+17 -16
file changed
src/FedoraReview/deps.py
+8 -7
file changed
src/FedoraReview/download_scratch.py
+13 -15
file changed
src/FedoraReview/helpers_mixin.py
+17 -17
file changed
src/FedoraReview/mock.py
+6 -5
file changed
src/FedoraReview/name_bug.py
+6 -4
file changed
src/FedoraReview/registry.py
+14 -11
file changed
src/FedoraReview/reports.py
+2 -2
file changed
src/FedoraReview/review_dirs.py
+47 -47
file changed
src/FedoraReview/review_helper.py
+13 -11
file changed
src/FedoraReview/rpm_file.py
+11 -8
file changed
src/FedoraReview/settings.py
+5 -5
file changed
src/FedoraReview/source.py
+25 -20
file changed
src/FedoraReview/spec_file.py
+3 -3
file changed
src/FedoraReview/srpm_file.py
+6 -6
file changed
src/FedoraReview/url_bug.py
+2 -3
file changed
src/FedoraReview/version.py
+2 -2
file changed
src/fedora-create-review
+4 -3
file changed
test/fr_testcase.py
+1 -1
file changed
test/test_R_checks.py
+6 -6
file changed
test/test_deps.py
+1 -1
file changed
test/test_dist.py
+8 -8
file changed
test/test_misc.py
+5 -14
file changed
try-fedora-review
+2 -1
file changed
update-version