Skip to content

Commit ef1e5d2

Browse files
committed
More python 3 compatibility fixes
Our biggest problem for Python3 compatibility was the _CommandOutput class in rdopkg/utils/cmd.py, since it derives from str, which is Unicode in Python3. Solving this by making all strings unicode, and adjusting when needed. Also reimplemented functions from rpmUtils.miscutils which are python2-only, and fixed warnings about non-closed file handles. Change-Id: I2cf5321edaddf5d3e22764c7c9e4a8c5ff84e7c6
1 parent 374c200 commit ef1e5d2

File tree

7 files changed

+81
-18
lines changed

7 files changed

+81
-18
lines changed

rdopkg.spec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ BuildRequires: python2-devel
1515
BuildRequires: PyYAML
1616

1717
Requires: python-bunch
18+
Requires: python-future
1819
Requires: python-paramiko
1920
Requires: python-pymod2pkg >= 0.2.1
2021
Requires: python-requests

rdopkg/guess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def user():
174174
if not user:
175175
raise exception.CantGuess(what="user name",
176176
why='git config user.name not set')
177-
return user.decode('utf-8')
177+
return user
178178

179179

180180
def email():

rdopkg/utils/cmd.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from __future__ import unicode_literals
2+
from builtins import str
3+
14
import json
25
import re
36
import subprocess
@@ -53,6 +56,7 @@ def run(cmd, *params, **kwargs):
5356

5457
if input:
5558
stdin = subprocess.PIPE
59+
input = input.encode()
5660
else:
5761
stdin = None
5862

@@ -75,16 +79,16 @@ def run(cmd, *params, **kwargs):
7579
if print_stdout:
7680
log.info(out)
7781
else:
78-
out = ''
82+
out = b''
7983

8084
if err:
8185
err = err.rstrip()
8286
if print_stderr:
8387
log.info(err)
8488
else:
85-
err = ''
89+
err = b''
8690

87-
cout = _CommandOutput(out)
91+
cout = _CommandOutput(out.decode('utf-8'))
8892
cout.stderr = err
8993
cout.return_code = prc.returncode
9094
cout.cmd = cmd_str
@@ -262,8 +266,9 @@ def get_commit_bzs(self, from_revision, to_revision=None):
262266
log_cmd=False, fatal=False)
263267
if not log_out:
264268
return []
269+
265270
log = log_out.strip('\n\x1e').split("\x1e")
266-
log = [row.strip().split("\x1f") for row in log]
271+
log = [row.strip('\n\t ').split("\x1f") for row in log]
267272
log = [dict(zip(GIT_COMMIT_FIELDS, row)) for row in log]
268273
BZ_REGEX = r'rhbz#(\d+)'
269274
result = []

rdopkg/utils/specfile.py

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,64 @@
99
RPM_AVAILABLE = False
1010
try:
1111
import rpm
12-
import rpmUtils.miscutils
1312
RPM_AVAILABLE = True
1413
except ImportError:
1514
pass
1615

1716

17+
def split_filename(filename):
18+
"""
19+
Received a standard style rpm fullname and returns
20+
name, version, release, epoch, arch
21+
Example: foo-1.0-1.i386.rpm returns foo, 1.0, 1, i386
22+
1:bar-9-123a.ia64.rpm returns bar, 9, 123a, 1, ia64
23+
24+
This function replaces rpmUtils.miscutils.splitFilename, see
25+
https://bugzilla.redhat.com/1452801
26+
"""
27+
28+
# Remove .rpm suffix
29+
if filename.endswith('.rpm'):
30+
filename = filename.split('.rpm')[0]
31+
32+
# is there an epoch?
33+
components = filename.split(':')
34+
if len(components) > 1:
35+
epoch = components[0]
36+
else:
37+
epoch = ''
38+
39+
# Arch is the last item after .
40+
arch = filename.rsplit('.')[-1]
41+
remaining = filename.rsplit('.%s' % arch)[0]
42+
release = remaining.rsplit('-')[-1]
43+
version = remaining.rsplit('-')[-2]
44+
name = '-'.join(remaining.rsplit('-')[:-2])
45+
46+
return name, version, release, epoch, arch
47+
48+
49+
def string_to_version(verstring):
50+
"""
51+
Return a tuple of (epoch, version, release) from a version string
52+
53+
This function replaces rpmUtils.miscutils.stringToVersion, see
54+
https://bugzilla.redhat.com/1364504
55+
"""
56+
# is there an epoch?
57+
components = verstring.split(':')
58+
if len(components) > 1:
59+
epoch = components[0]
60+
else:
61+
epoch = 0
62+
63+
remaining = components[:2][0].split('-')
64+
version = remaining[0]
65+
release = remaining[1]
66+
67+
return (epoch, version, release)
68+
69+
1870
def spec_fn(spec_dir='.'):
1971
specs = [f for f in os.listdir(spec_dir)
2072
if os.path.isfile(f) and f.endswith('.spec')]
@@ -32,7 +84,8 @@ def get_patches_from_files(patches_dir='.'):
3284
return []
3385
patches = []
3486
for pfn in patches_fns:
35-
txt = codecs.open(pfn, 'r', encoding='utf-8').read()
87+
with codecs.open(pfn, 'r', encoding='utf-8') as fp:
88+
txt = fp.read()
3689
hash = None
3790
m = re.search(r'^From ([a-z0-9]+)', txt, flags=re.M)
3891
if m:
@@ -84,8 +137,8 @@ def has_macros(s):
84137
def nvrcmp(nvr1, nvr2):
85138
if not RPM_AVAILABLE:
86139
raise exception.RpmModuleNotAvailable()
87-
t1 = rpmUtils.miscutils.stringToVersion(nvr1)
88-
t2 = rpmUtils.miscutils.stringToVersion(nvr2)
140+
t1 = string_to_version(nvr1)
141+
t2 = string_to_version(nvr2)
89142
return rpm.labelCompare(t1, t2)
90143

91144

@@ -98,9 +151,7 @@ def vcmp(v1, v2):
98151

99152

100153
def nvr2version(nvr):
101-
if not RPM_AVAILABLE:
102-
raise exception.RpmModuleNotAvailable()
103-
_, v, _, _, _ = rpmUtils.miscutils.splitFilename(nvr)
154+
_, v, _, _, _ = split_filename(nvr)
104155
return v
105156

106157

@@ -130,7 +181,8 @@ def fn(self):
130181
@property
131182
def txt(self):
132183
if not self._txt:
133-
self._txt = codecs.open(self.fn, 'r', encoding='utf-8').read()
184+
with codecs.open(self.fn, 'r', encoding='utf-8') as fp:
185+
self._txt = fp.read()
134186
return self._txt
135187

136188
@property
@@ -548,7 +600,7 @@ def get_last_changelog_entry(self, strip=False):
548600
entry = entries[0]
549601
lines = entry.split("\n")
550602
if strip:
551-
lines = map(lambda x: x.lstrip(" -*\t"), lines)
603+
lines = list(map(lambda x: x.lstrip(" -*\t"), lines))
552604
return lines[0], lines[1:]
553605

554606
def get_requires(self, versions_as_string=False, remove_epoch=True):

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
blessings
22
bunch
3+
future
34
paramiko
45
PyYAML
56
requests

tests/test_common.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ def assert_distgit(dg_path, img_dg):
106106
exp_tree = cfind(img_path)
107107
assert current_tree == exp_tree
108108
current_txt = dg_path.join('foo.spec').read()
109-
exp_txt = open(os.path.join(img_path, 'foo.spec')).read()
109+
with open(os.path.join(img_path, 'foo.spec')) as fp:
110+
exp_txt = fp.read()
110111
assert current_txt == exp_txt
111112

112113

tests/test_update_patches.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,18 @@ def test_wipe(tmpdir):
178178
spec = specfile.Spec()
179179
spec.wipe_patches()
180180
spec.save()
181-
spec_after = open('foo.spec', 'r').read()
182-
spec_exp = open(common.spec_path('empty'), 'r').read()
181+
with open('foo.spec', 'r') as fp:
182+
spec_after = fp.read()
183+
with open(common.spec_path('empty'), 'r') as fp:
184+
spec_exp = fp.read()
183185
assert spec_after == spec_exp
184186
# second wipe must be a no-op
185187
with tmpdir.as_cwd():
186188
spec = specfile.Spec()
187189
spec.wipe_patches()
188190
spec.save()
189-
spec_after = open('foo.spec', 'r').read()
191+
with open('foo.spec', 'r') as fp:
192+
spec_after = fp.read()
190193
assert spec_after == spec_exp
191194

192195

0 commit comments

Comments
 (0)