31982d5
From 1772e5fb09f73181bd2250744b6e0a8da1c5ac5d Mon Sep 17 00:00:00 2001
31982d5
From: lethliel <mstrigl@suse.com>
31982d5
Date: Thu, 13 Dec 2018 15:17:29 +0100
31982d5
Subject: [PATCH] [python3] python3 support for commandline module
31982d5
31982d5
* use cmp_to_key from functools for python 2.7 and higer
31982d5
* use self written cmp_to_key for python 2.6
31982d5
* a lot of bytestring handling and decoding
31982d5
---
31982d5
 osc/commandline.py | 105 +++++++++++++++++++++++++--------------------
31982d5
 1 file changed, 58 insertions(+), 47 deletions(-)
31982d5
31982d5
diff --git a/osc/commandline.py b/osc/commandline.py
31982d5
index e96a1170..67c2ad2a 100644
31982d5
--- a/osc/commandline.py
31982d5
+++ b/osc/commandline.py
31982d5
@@ -29,6 +29,11 @@
31982d5
 from .core import *
31982d5
 from .util import safewriter
31982d5
 
31982d5
+try:
31982d5
+    from functools import cmp_to_key
31982d5
+except ImportError:
31982d5
+    from .util.helper import cmp_to_key
31982d5
+
31982d5
 MAN_HEADER = r""".TH %(ucname)s "1" "%(date)s" "%(name)s %(version)s" "User Commands"
31982d5
 .SH NAME
31982d5
 %(name)s \- openSUSE build service command-line tool.
31982d5
@@ -435,7 +440,8 @@ def do_list(self, subcmd, opts, *args):
31982d5
                         break
31982d5
                     m = show_files_meta(apiurl, project, package)
31982d5
                     li = Linkinfo()
31982d5
-                    li.read(ET.fromstring(''.join(m)).find('linkinfo'))
31982d5
+                    root = ET.fromstring(m)
31982d5
+                    li.read(root.find('linkinfo'))
31982d5
                     if li.haserror():
31982d5
                         raise oscerr.LinkExpandError(project, package, li.error)
31982d5
                     project, package, rev = li.project, li.package, li.rev
31982d5
@@ -753,7 +759,7 @@ def do_token(self, subcmd, opts, *args):
31982d5
                 buf = f.read(16384)
31982d5
                 if not buf:
31982d5
                     break
31982d5
-                sys.stdout.write(buf)
31982d5
+                sys.stdout.write(decode_it(buf))
31982d5
 
31982d5
         elif opts.delete:
31982d5
             print("Delete token")
31982d5
@@ -773,7 +779,7 @@ def do_token(self, subcmd, opts, *args):
31982d5
                 raise oscerr.WrongArgs("Did you mean --" + args[0] + "?")
31982d5
             # just list token
31982d5
             for data in streamfile(url, http_GET):
31982d5
-                sys.stdout.write(data)
31982d5
+                sys.stdout.write(decode_it(data))
31982d5
 
31982d5
 
31982d5
     @cmdln.option('-a', '--attribute', metavar='ATTRIBUTE',
31982d5
@@ -938,22 +944,22 @@ def do_meta(self, subcmd, opts, *args):
31982d5
         # show
31982d5
         if not opts.edit and not opts.file and not opts.delete and not opts.create and not opts.set:
31982d5
             if cmd == 'prj':
31982d5
-                sys.stdout.write(''.join(show_project_meta(apiurl, project, rev=opts.revision, blame=opts.blame)))
31982d5
+                sys.stdout.write(decode_it(b''.join(show_project_meta(apiurl, project, rev=opts.revision, blame=opts.blame))))
31982d5
             elif cmd == 'pkg':
31982d5
-                sys.stdout.write(''.join(show_package_meta(apiurl, project, package, blame=opts.blame)))
31982d5
+                sys.stdout.write(decode_it(b''.join(show_package_meta(apiurl, project, package, blame=opts.blame))))
31982d5
             elif cmd == 'attribute':
31982d5
-                sys.stdout.write(''.join(show_attribute_meta(apiurl, project, package, subpackage,
31982d5
-                                         opts.attribute, opts.attribute_defaults, opts.attribute_project)))
31982d5
+                sys.stdout.write(decode_it(b''.join(show_attribute_meta(apiurl, project, package, subpackage,
31982d5
+                                         opts.attribute, opts.attribute_defaults, opts.attribute_project))))
31982d5
             elif cmd == 'prjconf':
31982d5
-                sys.stdout.write(''.join(show_project_conf(apiurl, project, rev=opts.revision, blame=opts.blame)))
31982d5
+                sys.stdout.write(decode_it(b''.join(show_project_conf(apiurl, project, rev=opts.revision, blame=opts.blame))))
31982d5
             elif cmd == 'user':
31982d5
                 r = get_user_meta(apiurl, user)
31982d5
                 if r:
31982d5
-                    sys.stdout.write(''.join(r))
31982d5
+                    sys.stdout.write(decode_it(r))
31982d5
             elif cmd == 'group':
31982d5
                 r = get_group_meta(apiurl, group)
31982d5
                 if r:
31982d5
-                    sys.stdout.write(''.join(r))
31982d5
+                    sys.stdout.write(decode_it(r))
31982d5
             elif cmd == 'pattern':
31982d5
                 if pattern:
31982d5
                     r = show_pattern_meta(apiurl, project, pattern)
31982d5
@@ -1390,9 +1396,9 @@ def _check_service(root):
31982d5
         if opts.diff or not opts.message:
31982d5
             try:
31982d5
                 rdiff = 'old: %s/%s\nnew: %s/%s rev %s\n' % (dst_project, dst_package, src_project, src_package, rev)
31982d5
-                rdiff += server_diff(apiurl,
31982d5
+                rdiff += decode_it(server_diff(apiurl,
31982d5
                                     dst_project, dst_package, None,
31982d5
-                                    src_project, src_package, rev, True)
31982d5
+                                    src_project, src_package, rev, True))
31982d5
             except:
31982d5
                 rdiff = ''
31982d5
 
31982d5
@@ -2483,7 +2489,7 @@ def do_request(self, subcmd, opts, *args):
31982d5
                             action.tgt_project, action.tgt_package)
31982d5
                         diff += submit_action_diff(apiurl, action)
31982d5
                         diff += '\n\n'
31982d5
-                run_pager(diff, tmp_suffix='')
31982d5
+                run_pager(decode_it(diff), tmp_suffix='')
31982d5
 
31982d5
         # checkout
31982d5
         elif cmd == 'checkout' or cmd == 'co':
31982d5
@@ -2983,7 +2989,7 @@ def do_copypac(self, subcmd, opts, *args):
31982d5
                      revision=rev,
31982d5
                      comment=comment,
31982d5
                      keep_link=opts.keep_link)
31982d5
-        print(r)
31982d5
+        print(decode_it(r))
31982d5
 
31982d5
 
31982d5
     @cmdln.option('-r', '--repo', metavar='REPO',
31982d5
@@ -3495,7 +3501,7 @@ def do_branch(self, subcmd, opts, *args):
31982d5
         devloc = None
31982d5
         if not exists and (srcprj != args[0] or srcpkg != args[1]):
31982d5
             try:
31982d5
-                root = ET.fromstring(''.join(show_attribute_meta(apiurl, args[0], None, None,
31982d5
+                root = ET.fromstring(b''.join(show_attribute_meta(apiurl, args[0], None, None,
31982d5
                     conf.config['maintained_update_project_attribute'], False, False)))
31982d5
                 # this might raise an AttributeError
31982d5
                 uproject = root.find('attribute').find('value').text
31982d5
@@ -3649,7 +3655,7 @@ def do_lock(self, subcmd, opts, project, package=None):
31982d5
             kind = 'pkg'
31982d5
             path_args = (project, package)
31982d5
         meta = meta_exists(kind, path_args, create_new=False, apiurl=apiurl)
31982d5
-        root = ET.fromstring(''.join(meta))
31982d5
+        root = ET.fromstring(b''.join(meta))
31982d5
         if root.find('lock') is not None:
31982d5
             print('Already locked', file=sys.stderr)
31982d5
             sys.exit(1)
31982d5
@@ -3854,9 +3860,9 @@ def do_diff(self, subcmd, opts, *args):
31982d5
                 for i in pac.get_diff(rev1):
31982d5
                     diff += ''.join(i)
31982d5
             else:
31982d5
-                diff += server_diff_noex(pac.apiurl, pac.prjname, pac.name, rev1,
31982d5
+                diff += decode_it(server_diff_noex(pac.apiurl, pac.prjname, pac.name, rev1,
31982d5
                                     pac.prjname, pac.name, rev2,
31982d5
-                                    not opts.plain, opts.missingok, opts.meta, not opts.unexpand)
31982d5
+                                    not opts.plain, opts.missingok, opts.meta, not opts.unexpand))
31982d5
         run_pager(diff)
31982d5
 
31982d5
 
31982d5
@@ -4135,12 +4141,12 @@ def _prdiff_output_diff(self, opts, rdiff):
31982d5
                                  stdin=subprocess.PIPE,
31982d5
                                  stdout=subprocess.PIPE,
31982d5
                                  close_fds=True)
31982d5
-            p.stdin.write(rdiff.encode())
31982d5
+            p.stdin.write(rdiff)
31982d5
             p.stdin.close()
31982d5
-            print("".join(x.decode() for x in p.stdout.readlines()))
31982d5
+            print("".join(decode_it(x) for x in p.stdout.readlines()))
31982d5
         elif opts.unified:
31982d5
             print()
31982d5
-            print(rdiff)
31982d5
+            print(decode_it(rdiff))
31982d5
             #run_pager(rdiff)
31982d5
 
31982d5
     def _prdiff_output_matching_requests(self, opts, requests,
31982d5
@@ -4285,7 +4291,7 @@ def do_repourls(self, subcmd, opts, *args):
31982d5
         else:
31982d5
             raise oscerr.WrongArgs('Wrong number of arguments')
31982d5
 
31982d5
-        root = ET.fromstring(''.join(show_configuration(apiurl)))
31982d5
+        root = ET.fromstring(b''.join(show_configuration(apiurl)))
31982d5
         elm = root.find('download_url')
31982d5
         if elm is None or not elm.text:
31982d5
             raise oscerr.APIError('download_url configuration element expected')
31982d5
@@ -4530,7 +4536,7 @@ def do_status(self, subcmd, opts, *args):
31982d5
                 # don't exclude packages with state ' ' because the packages
31982d5
                 # might have modified etc. files
31982d5
                 prj_excl = [st for st in excl_states if st != ' ']
31982d5
-                for st, pac in sorted(prj.get_status(*prj_excl), lambda x, y: cmp(x[1], y[1])):
31982d5
+                for st, pac in sorted(prj.get_status(*prj_excl), key=cmp_to_key(compare)):
31982d5
                     p = prj.get_pacobj(pac)
31982d5
                     if p is None:
31982d5
                         # state is != ' '
31982d5
@@ -4541,11 +4547,11 @@ def do_status(self, subcmd, opts, *args):
31982d5
                     elif st == ' ' and opts.verbose or st != ' ':
31982d5
                         lines.append(statfrmt(st, os.path.normpath(os.path.join(prj.dir, pac))))
31982d5
                     states = p.get_status(opts.show_excluded, *excl_states)
31982d5
-                    for st, filename in sorted(states, lambda x, y: cmp(x[1], y[1])):
31982d5
+                    for st, filename in sorted(states, key=cmp_to_key(compare)):
31982d5
                         lines.append(statfrmt(st, os.path.normpath(os.path.join(p.dir, filename))))
31982d5
             else:
31982d5
                 p = findpacs([arg])[0]
31982d5
-                for st, filename in sorted(p.get_status(opts.show_excluded, *excl_states), lambda x, y: cmp(x[1], y[1])):
31982d5
+                for st, filename in sorted(p.get_status(opts.show_excluded, *excl_states), key=cmp_to_key(compare)):
31982d5
                     lines.append(statfrmt(st, os.path.normpath(os.path.join(p.dir, filename))))
31982d5
         if lines:
31982d5
             print('\n'.join(lines))
31982d5
@@ -5227,7 +5233,7 @@ def do_results(self, subcmd, opts, *args):
31982d5
             del kwargs['showexcl']
31982d5
             for xml in get_package_results(**kwargs):
31982d5
                 if opts.xml:
31982d5
-                    print(xml, end='')
31982d5
+                    print(decode_it(xml), end='')
31982d5
                 else:
31982d5
                     # csv formatting
31982d5
                     results = [r for r, _ in result_xml_to_dicts(xml)]
31982d5
@@ -5290,7 +5296,7 @@ def do_prjresults(self, subcmd, opts, *args):
31982d5
                 kwargs['arch'] = opts.arch
31982d5
             kwargs['wait'] = opts.watch
31982d5
             for results in get_package_results(apiurl, project, **kwargs):
31982d5
-                print(results)
31982d5
+                print(decode_it(results))
31982d5
             return
31982d5
 
31982d5
         if opts.watch:
31982d5
@@ -5345,7 +5351,7 @@ def do_rpmlintlog(self, subcmd, opts, *args):
31982d5
         else:
31982d5
             raise oscerr.WrongArgs('please provide project package repository arch.')
31982d5
 
31982d5
-        print(get_rpmlint_log(apiurl, project, package, repository, arch))
31982d5
+        print(decode_it(get_rpmlint_log(apiurl, project, package, repository, arch)))
31982d5
 
31982d5
     @cmdln.alias('bl')
31982d5
     @cmdln.alias('blt')
31982d5
@@ -5791,7 +5797,7 @@ def do_buildinfo(self, subcmd, opts, *args):
31982d5
 
31982d5
         build_descr_data = None
31982d5
         if not build_descr is None:
31982d5
-            build_descr_data = open(build_descr, 'r').read()
31982d5
+            build_descr_data = open(build_descr, 'rb').read()
31982d5
         if opts.prefer_pkgs and build_descr_data is None:
31982d5
             raise oscerr.WrongArgs('error: a build description is needed if \'--prefer-pkgs\' is used')
31982d5
         elif opts.prefer_pkgs:
31982d5
@@ -5802,13 +5808,13 @@ def do_buildinfo(self, subcmd, opts, *args):
31982d5
             prefer_pkgs = get_prefer_pkgs(opts.prefer_pkgs, arch,
31982d5
                                           os.path.splitext(build_descr)[1],
31982d5
                                           cpiodata)
31982d5
-            cpiodata.add(os.path.basename(build_descr), build_descr_data)
31982d5
+            cpiodata.add(os.path.basename(build_descr.encode()), build_descr_data)
31982d5
             build_descr_data = cpiodata.get()
31982d5
 
31982d5
         if opts.multibuild_package:
31982d5
             package = package + ":" + opts.multibuild_package
31982d5
 
31982d5
-        print(''.join(get_buildinfo(apiurl,
31982d5
+        print(decode_it(get_buildinfo(apiurl,
31982d5
                                     project, package, repository, arch,
31982d5
                                     specfile=build_descr_data,
31982d5
                                     debug=opts.debug,
31982d5
@@ -5855,7 +5861,7 @@ def do_buildconfig(self, subcmd, opts, *args):
31982d5
         else:
31982d5
             raise oscerr.WrongArgs('Wrong number of arguments.')
31982d5
 
31982d5
-        print(''.join(get_buildconfig(apiurl, project, repository)))
31982d5
+        print(decode_it(get_buildconfig(apiurl, project, repository)))
31982d5
 
31982d5
 
31982d5
     def do_workerinfo(self, subcmd, opts, worker):
31982d5
@@ -6097,6 +6103,7 @@ def parse_repoarchdescr(self, args, noinit = False, alternative_project = None,
31982d5
                 recipe = recipe.strip()
31982d5
                 if recipe == 'arch':
31982d5
                     recipe = 'PKGBUILD'
31982d5
+                recipe = decode_it(recipe)
31982d5
                 pac = os.path.basename(os.getcwd())
31982d5
                 if is_package_dir(os.getcwd()):
31982d5
                     pac = store_read_package(os.getcwd())
31982d5
@@ -7287,7 +7294,7 @@ def do_getbinaries(self, subcmd, opts, *args):
31982d5
                                     package = pac,
31982d5
                                     target_filename = fname,
31982d5
                                     target_mtime = i.mtime,
31982d5
-                                    progress_meter = not opts.quiet)
31982d5
+                                    progress_meter = opts.quiet)
31982d5
 
31982d5
 
31982d5
     @cmdln.option('-b', '--bugowner', action='store_true',
31982d5
@@ -7373,7 +7380,7 @@ def do_my(self, subcmd, opts, *args):
31982d5
             what = {'project': ''}
31982d5
         elif type in args_sr:
31982d5
             requests = get_request_collection(apiurl, 'creator', req_who=user)
31982d5
-            for r in sorted(requests):
31982d5
+            for r in sorted(requests, key=lambda x: x.reqid):
31982d5
                 print(r.list_view(), '\n')
31982d5
             return
31982d5
         elif not type in args_pkg:
31982d5
@@ -7741,8 +7748,9 @@ def build_xpath(attr, what, substr = False):
31982d5
                 continue
31982d5
             # construct a sorted, flat list
31982d5
             # Sort by first column, follwed by second column if we have two columns, else sort by first.
31982d5
-            results.sort(lambda x, y: ( cmp(x[0], y[0]) or
31982d5
-                                       (len(x)>1 and len(y)>1 and cmp(x[1], y[1])) ))
31982d5
+            # results.sort(lambda x, y: ( cmp(x[0], y[0]) or
31982d5
+            #                           (len(x)>1 and len(y)>1 and cmp(x[1], y[1])) ))
31982d5
+            results.sort(key=cmp_to_key(compare))
31982d5
             new = []
31982d5
             for i in results:
31982d5
                 new.extend(i)
31982d5
@@ -7962,7 +7970,7 @@ def do_api(self, subcmd, opts, url):
31982d5
                          data=opts.data,
31982d5
                          file=opts.file,
31982d5
                          headers=opts.headers)
31982d5
-        out = r.read()
31982d5
+        out = decode_it(r.read())
31982d5
 
31982d5
         if opts.edit:
31982d5
             text = edit_text(out)
31982d5
@@ -7970,7 +7978,7 @@ def do_api(self, subcmd, opts, url):
31982d5
                          url,
31982d5
                          data=text,
31982d5
                          headers=opts.headers)
31982d5
-            out = r.read()
31982d5
+            out = decode_it(r.read())
31982d5
 
31982d5
         sys.stdout.write(out)
31982d5
 
31982d5
@@ -8184,7 +8192,7 @@ def setBugownerHelper(apiurl, project, package, bugowner):
31982d5
         else:
31982d5
             if pac:
31982d5
                 m = show_package_meta(apiurl, prj, pac)
31982d5
-                metaroot = ET.fromstring(''.join(m))
31982d5
+                metaroot = ET.fromstring(b''.join(m))
31982d5
                 if not opts.nodevelproject:
31982d5
                     while metaroot.findall('devel'):
31982d5
                         d = metaroot.find('devel')
31982d5
@@ -8193,18 +8201,18 @@ def setBugownerHelper(apiurl, project, package, bugowner):
31982d5
                         if opts.verbose:
31982d5
                             print("Following to the development space: %s/%s" % (prj, pac))
31982d5
                         m = show_package_meta(apiurl, prj, pac)
31982d5
-                        metaroot = ET.fromstring(''.join(m))
31982d5
+                        metaroot = ET.fromstring(b''.join(m))
31982d5
                     if not metaroot.findall('person') and not metaroot.findall('group'):
31982d5
                         if opts.verbose:
31982d5
                             print("No dedicated persons in package defined, showing the project persons.")
31982d5
                         pac = None
31982d5
                         m = show_project_meta(apiurl, prj)
31982d5
-                        metaroot = ET.fromstring(''.join(m))
31982d5
+                        metaroot = ET.fromstring(b''.join(m))
31982d5
             else:
31982d5
                 # fallback to project lookup for old servers
31982d5
                 if prj and not searchresult:
31982d5
                     m = show_project_meta(apiurl, prj)
31982d5
-                    metaroot = ET.fromstring(''.join(m))
31982d5
+                    metaroot = ET.fromstring(b''.join(m))
31982d5
 
31982d5
             # extract the maintainers
31982d5
             projects = []
31982d5
@@ -8365,10 +8373,13 @@ def do_cat(self, subcmd, opts, *args):
31982d5
         u = makeurl(apiurl, ['source', project, package, filename], query=query)
31982d5
         if subcmd == 'less':
31982d5
             f = http_GET(u)
31982d5
-            run_pager(''.join(f.readlines()))
31982d5
+            run_pager(b''.join(f.readlines()))
31982d5
         else:
31982d5
             for data in streamfile(u):
31982d5
-                sys.stdout.write(data)
31982d5
+                if isinstance(data, str):
31982d5
+                    sys.stdout.write(data)
31982d5
+                else:
31982d5
+                    sys.stdout.write(decode_it(data))
31982d5
 
31982d5
 
31982d5
     # helper function to download a file from a specific revision
31982d5
@@ -8617,7 +8628,7 @@ def do_pull(self, subcmd, opts, *args):
31982d5
         u = makeurl(p.apiurl, ['source', p.prjname, p.name], query=query)
31982d5
         f = http_GET(u)
31982d5
         meta = f.readlines()
31982d5
-        root_new = ET.fromstring(''.join(meta))
31982d5
+        root_new = ET.fromstring(b''.join(meta))
31982d5
         linkinfo_new = root_new.find('linkinfo')
31982d5
         if linkinfo_new == None:
31982d5
             raise oscerr.APIError('link is not a really a link?')
31982d5
@@ -8790,7 +8801,7 @@ def do_signkey(self, subcmd, opts, *args):
31982d5
             buf = f.read(16384)
31982d5
             if not buf:
31982d5
                 break
31982d5
-            sys.stdout.write(buf)
31982d5
+            sys.stdout.write(decode_it(buf))
31982d5
 
31982d5
     @cmdln.option('-m', '--message',
31982d5
                   help='add MESSAGE to changes (do not open an editor)')
31982d5
@@ -8830,7 +8841,7 @@ def do_vc(self, subcmd, opts, *args):
31982d5
             import glob, re
31982d5
             try:
31982d5
                 fn_changelog = glob.glob('*.changes')[0]
31982d5
-                fp = file(fn_changelog)
31982d5
+                fp = open(fn_changelog)
31982d5
                 titleline = fp.readline()
31982d5
                 fp.close()
31982d5
                 if re.match('^\*\W+(.+\W+\d{1,2}\W+20\d{2})\W+(.+)\W+<(.+)>\W+(.+)$', titleline):