From 3a0ecf00f99263deed38b7497a33596d951ef4e0 Mon Sep 17 00:00:00 2001
From: Lubomír Sedlář <lsedlar@redhat.com>
Date: Oct 16 2017 09:01:54 +0000
Subject: Port to Python 3


Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>

---

diff --git a/compose_utils/changelog.py b/compose_utils/changelog.py
index 3ce9f8d..39e9bf2 100644
--- a/compose_utils/changelog.py
+++ b/compose_utils/changelog.py
@@ -41,7 +41,7 @@ def to_utf8(text):
     encodings = ["ascii", "utf8", "latin1", "latin2"]
     for encoding in encodings:
         try:
-            return text.decode(encoding).encode("utf-8")
+            return text.decode(encoding)
         except UnicodeDecodeError:
             pass
     return text.decode("ascii", "ignore")
@@ -61,7 +61,7 @@ class SimpleRpmWrapperWithChangelog(kobo.pkgset.SimpleRpmWrapper):
         ts = kwargs.pop("ts", None)
         header = kobo.rpmlib.get_rpm_header(file_path, ts=ts)
 
-        self.summary = kobo.rpmlib.get_header_field(header, "summary")
+        self.summary = kobo.rpmlib.get_header_field(header, "summary").decode('utf-8')
 
         if self.sourcerpm:
             key = self.sourcerpm
@@ -105,10 +105,10 @@ def get_changelog_diff_from_headers(old, new, max_records=-1):
     if new_changelog and old_changelog:
         result = []
         old_time = old_changelog[0].time
-        old_nvr = LooseVersion(old_changelog[0].name.rsplit(None, 1)[-1])
+        old_nvr = LooseVersion(to_utf8(old_changelog[0].name).rsplit(None, 1)[-1])
         while new_changelog:
             entry = new_changelog.pop(0)
-            new_nvr = LooseVersion(entry.name.rsplit(None, 1)[-1])
+            new_nvr = LooseVersion(to_utf8(entry.name).rsplit(None, 1)[-1])
             if entry.time < old_time or (entry.time == old_time and new_nvr <= old_nvr):
                 # We want to take all entries from new changelog that are newer
                 # than old changelog, or from the same day as latest old entry
@@ -163,7 +163,7 @@ class ComposeChangelog(object):
         for variant in rm:
             for arch in rm[variant]:
                 for srpm_nevra in rm[variant][arch]:
-                    for rpm_nevra, data in rm[variant][arch][srpm_nevra].iteritems():
+                    for rpm_nevra, data in rm[variant][arch][srpm_nevra].items():
                         if data['category'] != 'source':
                             continue
                         result.setdefault(
@@ -205,7 +205,7 @@ class ComposeChangelog(object):
         for variant in rm:
             for arch in rm[variant]:
                 for srpm_nevra in rm[variant][arch]:
-                    for rpm_nevra, data in rm[variant][arch][srpm_nevra].iteritems():
+                    for rpm_nevra, data in rm[variant][arch][srpm_nevra].items():
                         if data["category"] in ("debug", "source"):
                             continue
                         result.setdefault(
@@ -366,7 +366,7 @@ class ComposeChangelog(object):
 
             data["changelog"] = []
             for i in get_changelog_diff_from_headers(old_package, new_package, max_logs):
-                data["changelog"].append(to_utf8(str(i)))
+                data["changelog"].append("* %s %s\n%s" % (i.ctime, to_utf8(i.name), to_utf8(i.text)))
 
             # TODO: comps, system release
             # if rpm.versionCompare(old_package, new_package.header) == -1:
@@ -532,7 +532,7 @@ class ComposeChangelog(object):
             result.append("")
         result.append("")
 
-        return "\n".join([to_utf8(i) for i in result])
+        return "\n".join(result)
 
     def write(self, data, path=None, name=None, verbose=False):
         if name:
@@ -558,4 +558,5 @@ class ComposeChangelog(object):
         # verbose
         verbose_log = os.path.join(path, "%s.verbose" % name)
         with open(verbose_log, "w") as f:
-            f.write(self.get_verbose_log(data, shorten=verbose))
+            clog = self.get_verbose_log(data, shorten=verbose)
+            f.write(clog.encode('utf-8'))
diff --git a/compose_utils/copy_compose.py b/compose_utils/copy_compose.py
index 89fba44..3cbec98 100644
--- a/compose_utils/copy_compose.py
+++ b/compose_utils/copy_compose.py
@@ -37,7 +37,7 @@ def copy_compose(compose, dest, arches=None, variants=None, dry_run=False, rsync
 
     compose_path = compose.compose_path.rstrip('/')
     paths = _reduce(compose, paths)
-    for parent, children in paths.iteritems():
+    for parent, children in paths.items():
         sources = sorted([os.path.join(parent, child) for child in children])
         destination = os.path.join(dest, parent.replace(compose_path, '').lstrip('/'))
         _run_rsync(sources, destination, dry_run=dry_run, opts=rsync_opts)
@@ -69,10 +69,10 @@ def _collect_variant(compose, variant, arch=None):
         paths = getattr(variant.paths, path_type)
         if arch and path_type.startswith('source'):
             if arch == 'src':
-                sources = sources | set(paths.itervalues())
+                sources = sources | set(paths.values())
             continue
         if not arch:
-            sources = sources | set(paths.itervalues())
+            sources = sources | set(paths.values())
         elif arch in paths:
             sources.add(paths[arch])
 
@@ -85,7 +85,7 @@ def _collect_variant(compose, variant, arch=None):
         if arch:
             images = variant_images[arch]
         else:
-            for vararch_images in variant_images.itervalues():
+            for vararch_images in variant_images.values():
                 images.extend(vararch_images)
     except (KeyError, RuntimeError):
         # Ignore missing images metadata or no images in the variant/arch
@@ -126,7 +126,7 @@ def _reduce(compose, paths):
 
                 # If any other path starts with the removed directory, we can
                 # remove it too.
-                for other in mapping.keys():
+                for other in list(mapping.keys()):
                     if (other.rstrip('/') + '/').startswith(dir + '/'):
                         mapping.pop(other)
 
diff --git a/compose_utils/legacy.py b/compose_utils/legacy.py
index da93fca..5ce6473 100644
--- a/compose_utils/legacy.py
+++ b/compose_utils/legacy.py
@@ -1,11 +1,11 @@
 # -*- coding: utf-8 -*-
 
-import ConfigParser
+from six.moves import configparser
 
 
 def write_legacy_composeinfo(ci, file):
     """Write a legacy INI-style composeinfo data into `file`."""
-    conf = ConfigParser.SafeConfigParser(dict_type=SortedDict)
+    conf = configparser.SafeConfigParser(dict_type=SortedDict)
     _serialize_compose(conf, ci.compose)
     _serialize_product(conf, ci.release, ci.compose)
     if ci.release.is_layered:
@@ -106,7 +106,7 @@ def _serialize_variant(conf, variant):
         _serialize_paths(conf, path_section, variant.paths, arch)
 
     children = set()
-    for child in variant.variants.itervalues():
+    for child in variant.variants.values():
         _serialize_variant(conf, child)
         children.add(child.uid)
 
diff --git a/compose_utils/list.py b/compose_utils/list.py
index 0422dfa..f570eb1 100644
--- a/compose_utils/list.py
+++ b/compose_utils/list.py
@@ -88,9 +88,9 @@ def check_single_line(composes):
     Returns a list with the sorted composes.
     """
     if len(composes) == 1:
-        versions = composes[composes.keys()[0]]
+        versions = composes[list(composes.keys())[0]]
         if len(versions) == 1:
-            return sorted(versions[versions.keys()[0]], key=compose_sort)
+            return sorted(versions[list(versions.keys())[0]], key=compose_sort)
     raise BadUsage(
         'Expected to find composes for only one release.\n'
         'Consider adding some filters.'
diff --git a/compose_utils/package_moves.py b/compose_utils/package_moves.py
index 869ae5b..b830344 100644
--- a/compose_utils/package_moves.py
+++ b/compose_utils/package_moves.py
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 
 
+from __future__ import print_function
+
 __all__ = (
     "ComposePackageMoves",
 )
@@ -53,15 +55,15 @@ class ComposePackageMoves(object):
         rpms = compose.rpms.rpms
 
         result = {}
-        for variant, arches in rpms.iteritems():
+        for variant, arches in rpms.items():
             result[variant] = {}
-            for arch, srpms in arches.iteritems():
+            for arch, srpms in arches.items():
                 if arch == "src":
                     # Ignore src arch in rpm manifest
                     continue
                 result[variant][arch] = {}
-                for srpm_nevra, rpms in srpms.iteritems():
-                    for rpm_nevra, data in rpms.iteritems():
+                for srpm_nevra, rpms in srpms.items():
+                    for rpm_nevra, data in rpms.items():
                         # Parse filename
                         nvra_dict = parse_nvra(os.path.basename(data["path"]))
                         rpm_name = nvra_dict["name"]
@@ -79,7 +81,8 @@ class ComposePackageMoves(object):
                         }
                         if key in result[variant][arch]:
                             # Compose should have only latest version of each rpm -> print warning
-                            print "Warning: There are multiple packages with name %s (%s)" % (rpm_name, rpm_arch)
+                            print("Warning: There are multiple packages with name %s (%s)"
+                                  % (rpm_name, rpm_arch))
                             result[variant][arch][key].append(details)
                         else:
                             result[variant][arch][key] = [details]
@@ -111,7 +114,7 @@ class ComposePackageMoves(object):
         result["new_items"] = {}
         result["moved_items"] = []
 
-        for variant, parent_variant in new_variants_map.iteritems():
+        for variant, parent_variant in new_variants_map.items():
 
             if not parent_variant:
                 # Ignore variants which doesn't have parent
@@ -222,7 +225,7 @@ class ComposePackageMoves(object):
         log = []
 
         tmp = {}  # {'variant': {'arch': {items}, ..}, ..}
-        for _, val in data.iteritems():
+        for _, val in data.items():
             variant = val["variant"]
             arch = val["arch"]
             items = val["items"]
diff --git a/setup.py b/setup.py
index 79c4be3..1ba12dc 100644
--- a/setup.py
+++ b/setup.py
@@ -25,6 +25,7 @@ setup(
     install_requires=[
         'productmd>=1.0',
         'kobo>=0.4.2',
+        'six',
     ],
     data_files=[
         ('share/man/man1', [
@@ -41,5 +42,6 @@ setup(
         'nose',
         'mock',
         'freezegun',
+        'unittest2',
     ],
 )
diff --git a/tests/fixtures/move-report.json b/tests/fixtures/move-report.json
index 5125f41..003b71c 100644
--- a/tests/fixtures/move-report.json
+++ b/tests/fixtures/move-report.json
@@ -117,4 +117,4 @@
       "variant": "Server"
     }
   }
-}
\ No newline at end of file
+}
diff --git a/tests/test_changelog.py b/tests/test_changelog.py
index 2e566ef..3dca9b7 100644
--- a/tests/test_changelog.py
+++ b/tests/test_changelog.py
@@ -3,7 +3,10 @@
 import json
 import locale
 import mock
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 
 from kobo.rpmlib import ChangelogEntry
 
@@ -25,7 +28,7 @@ DUMMY_FIREFOX = {
     'old_rpms': ['Dummy-firefox'],
     'common_rpms': ['Dummy-firefox'],
     'rpms': ['Dummy-firefox'],
-    'changelog': ['* Tue Mar 15 2016 Lubomír Sedlář <lubomir.sedlar@gmail.com> - 1:0.1.0-1\n- new version'],
+    'changelog': [u'* Tue Mar 15 2016 Lubomír Sedlář <lubomir.sedlar@gmail.com> - 1:0.1.0-1\n- new version'],
     'added_rpms': [],
     'dropped_rpms': [],
     'nvr': 'Dummy-firefox-1:0.1.0-1',
@@ -57,7 +60,7 @@ DUMMY_CLOUD_INIT = {
     'old_rpms': ['cloud-init'],
     'common_rpms': ['cloud-init'],
     'rpms': ['cloud-init'],
-    'changelog': ['* Tue Sep 05 2017 Lubomír Sedlář <lsedlar@redhat.com> - 0.7.9-9.module_f8c7dcdc\n- First release'],
+    'changelog': [u'* Tue Sep 05 2017 Lubomír Sedlář <lsedlar@redhat.com> - 0.7.9-9.module_f8c7dcdc\n- First release'],
     'added_rpms': [],
     'dropped_rpms': [],
     'nvr': 'cloud-init-0.7.9-9.module_f8c7dcdc',
@@ -224,26 +227,26 @@ class TestFormat(unittest.TestCase):
 
 class TestCompareChangelogs(unittest.TestCase):
     def test_select_new(self):
-        c1 = ChangelogEntry('John Doe <jdoe@example.com> 1.0-1', 1000000, 'change 1')
-        c2 = ChangelogEntry('John Doe <jdoe@example.com> 1.1-1', 2000000, 'change 2')
+        c1 = ChangelogEntry(b'John Doe <jdoe@example.com> 1.0-1', 1000000, 'change 1')
+        c2 = ChangelogEntry(b'John Doe <jdoe@example.com> 1.1-1', 2000000, 'change 2')
         old = mock.Mock(changelogs=[c1])
         new = mock.Mock(changelogs=[c2, c1])
         clog = get_changelog_diff_from_headers(old, new)
         self.assertEqual(clog, [c2])
 
     def test_select_with_same_date(self):
-        c1 = ChangelogEntry('John Doe <jdoe@example.com> 1.0-1', 1000000, 'change 1')
-        c2 = ChangelogEntry('John Doe <jdoe@example.com> 1.1-1', 1000000, 'change 2')
+        c1 = ChangelogEntry(b'John Doe <jdoe@example.com> 1.0-1', 1000000, 'change 1')
+        c2 = ChangelogEntry(b'John Doe <jdoe@example.com> 1.1-1', 1000000, 'change 2')
         old = mock.Mock(changelogs=[c1])
         new = mock.Mock(changelogs=[c2, c1])
         clog = get_changelog_diff_from_headers(old, new)
         self.assertEqual(clog, [c2])
 
     def test_no_subset(self):
-        c1 = ChangelogEntry('John Doe <jdoe@example.com> 0:2.0-1', 1000000, 'change 1')
-        c2 = ChangelogEntry('John Doe <jdoe@example.com> 1:1.1-1', 1000000, 'change 2')
-        c3 = ChangelogEntry('John Doe <jdoe@example.com> 1:1.2-1', 1000000, 'change 3')
-        c4 = ChangelogEntry('John Doe <jdoe@example.com> 1:1.3-1', 1000000, 'change 4')
+        c1 = ChangelogEntry(b'John Doe <jdoe@example.com> 0:2.0-1', 1000000, 'change 1')
+        c2 = ChangelogEntry(b'John Doe <jdoe@example.com> 1:1.1-1', 1000000, 'change 2')
+        c3 = ChangelogEntry(b'John Doe <jdoe@example.com> 1:1.2-1', 1000000, 'change 3')
+        c4 = ChangelogEntry(b'John Doe <jdoe@example.com> 1:1.3-1', 1000000, 'change 4')
         old = mock.Mock(changelogs=[c3, c1])
         new = mock.Mock(changelogs=[c4, c2, c1])
         clog = get_changelog_diff_from_headers(old, new)
diff --git a/tests/test_copy_compose.py b/tests/test_copy_compose.py
index e35611b..6231751 100644
--- a/tests/test_copy_compose.py
+++ b/tests/test_copy_compose.py
@@ -1,9 +1,12 @@
 # -*- encoding: utf-8 -*-
 
-import unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import mock
 import os
-from StringIO import StringIO
+from six import StringIO
 import tempfile
 import shutil
 
diff --git a/tests/test_create_next_dir.py b/tests/test_create_next_dir.py
index 1ac7056..18c382f 100644
--- a/tests/test_create_next_dir.py
+++ b/tests/test_create_next_dir.py
@@ -8,7 +8,7 @@ import tempfile
 import os
 
 from freezegun import freeze_time
-from StringIO import StringIO
+from six import StringIO
 
 from compose_utils import create_next_dir
 
diff --git a/tests/test_legacy_composeinfo.py b/tests/test_legacy_composeinfo.py
index e8bc113..23fd09d 100644
--- a/tests/test_legacy_composeinfo.py
+++ b/tests/test_legacy_composeinfo.py
@@ -2,7 +2,7 @@
 
 import unittest
 import os
-import StringIO
+from six import StringIO
 import sys
 
 import productmd.compose
@@ -33,14 +33,14 @@ class LegacyComposeInfoTest(unittest.TestCase):
         self.compose = productmd.compose.Compose(BASE_PATH)
 
     def test_write_legacy_file(self):
-        output = StringIO.StringIO()
+        output = StringIO()
         write_legacy_composeinfo(self.compose.info, output)
         with open(os.path.join(BASE_PATH, 'compose', get_expected())) as f:
             expected = f.read().split()
             self.assertEqual(output.getvalue().split(), expected)
 
     def test_write_legacy_file_no_paths(self):
-        output = StringIO.StringIO()
+        output = StringIO()
         # Keep only Server variant and remove all paths for server
         server = self.compose.info.variants['Server']
         server.variants = {}
diff --git a/tests/test_list.py b/tests/test_list.py
index 25cdcb7..d40fafd 100644
--- a/tests/test_list.py
+++ b/tests/test_list.py
@@ -6,7 +6,7 @@ import tempfile
 import shutil
 import os
 import json
-from StringIO import StringIO
+from six import StringIO
 from freezegun import freeze_time
 
 from compose_utils import list
diff --git a/tests/test_symlink.py b/tests/test_symlink.py
index a6c2174..f7a8db2 100644
--- a/tests/test_symlink.py
+++ b/tests/test_symlink.py
@@ -5,7 +5,7 @@ import shutil
 import tempfile
 import unittest
 import mock
-from StringIO import StringIO
+from six import StringIO
 
 from compose_utils import symlink
 

