diff --git a/.gitignore b/.gitignore index 43dba70291d972b73713248ee568984c69a92c04..ede3e9604039690172a9457681aff533bfde2d33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *~ -mio +*.bak +/mio2 +/mio3 diff --git a/build b/build index aa51638a8c069816593778254549f9c8b62c7a95..10925a9c96c5f6cc1617d4f7b67520b092b842c9 100755 --- a/build +++ b/build @@ -4,4 +4,8 @@ TARGET=$(basename $(pwd)) set -e cd src find ${TARGET} -name '*.py' | sort | \ - xargs apa -o ../${TARGET} ${TARGET}.py + xargs apa --interpreter /usr/bin/python3 \ + -o ../${TARGET}3 ${TARGET}.py +find ${TARGET} -name '*.py' | sort | \ + xargs apa --interpreter /usr/bin/python2 \ + -o ../${TARGET}2 ${TARGET}.py diff --git a/src/mio.py b/src/mio.py index d6d07782017e33db821d31ffc9fa8f28f6330f16..53e2a0f27c29dfb9b3f33a8ae45fc02fa6a825e2 100755 --- a/src/mio.py +++ b/src/mio.py @@ -17,11 +17,6 @@ from mio.exception import * from mio.log import log, MUTE, SILENT, NORMAL, VERBOSE import locale -# Fix for older python version that does not have True and False defined -if not hasattr(__builtins__, "True"): - __builtins__["True"] = 1 - __builtins__["False"] = 0 - def parse_with_path(path, filename, repository): f = mio.filecache.loadfile(path, filename) tree = mio.parser.parse(f.filename, url=f.key) @@ -41,8 +36,7 @@ def parse_with_path(path, filename, repository): repository.add(tree._group_, join=join) def parse(filename, repository): - path = list(options.path) - for p in path: + for p in options.path: try: parse_with_path(p, filename, repository) return @@ -185,8 +179,7 @@ if __name__ == '__main__': help="increase verbosity") options = optParser.parse_args(sys.argv[1:]) - options.path = map(tuple, options.path) - + options.path = [ tuple(p,) for p in options.path ] mio.log.set_verbosity(NORMAL + options.verbose - options.quiet) find_and_parse = FindAndParse() @@ -259,9 +252,7 @@ if __name__ == '__main__': pass if not error: - keys = files.keys() - keys.sort() - for k in keys: + for k in sorted(files.keys()): print(k) pass else: @@ -296,9 +287,7 @@ if __name__ == '__main__': pass if not error: - keys = rpms.keys() - keys.sort() - for k in keys: + for k in sorted(rpms.keys()): print(k) pass else: diff --git a/src/mio/exception.py b/src/mio/exception.py index 989c1eca39b059c96709404d7d03d8ffe0cdb74b..61467bc29524914e1158cea513e00c6cee587126 100755 --- a/src/mio/exception.py +++ b/src/mio/exception.py @@ -1,7 +1,6 @@ from __future__ import print_function import traceback import sys -import urllib2 def declaration(decl): try: diff --git a/src/mio/filecache.py b/src/mio/filecache.py index cb89186dc2af60edd830d11b3076c6061ba59f45..61217a237bf2724d0550b49f3d1b57427ea212e0 100755 --- a/src/mio/filecache.py +++ b/src/mio/filecache.py @@ -7,8 +7,13 @@ import re import sys import tempfile import time -import urlparse -import urllib +try: + # Python 3 + from urllib.parse import urlsplit, urlunsplit, unquote as urlunquote +except ImportError: + # Python 2 fallback + from urlparse import urlsplit, urlunsplit + from urllib import unquote as urlunquote import mio.exception import socket try: @@ -27,8 +32,8 @@ mirror = {} def subpath(path, *tail): result = [] for p in path: - u = urlparse.urlsplit(p) - result.append(urlparse.urlunsplit([ + u = urlsplit(p) + result.append(urlunsplit([ u.scheme, u.hostname, '/'.join([u.path] + list(tail)), @@ -81,10 +86,10 @@ class Unalias: def __call__(self, url): result = [] - u = urlparse.urlsplit(str(url)) + u = urlsplit(str(url)) if u.hostname: for hostname in self.unalias_host(u.hostname, u.port or 80): - result.append(urlparse.urlunsplit(( + result.append(urlunsplit(( u.scheme, u.netloc.replace(u.hostname, hostname), u.path, @@ -93,11 +98,10 @@ class Unalias: pass pass elif u.scheme in [ '', 'file' ]: - result.append(urlparse.urlunsplit(('file', '', u.path, '', ''))) + result.append(urlunsplit(('file', '', u.path, '', ''))) pass else: - print(u) - pass + raise Exception('Unknown URL:', u) return result unalias = Unalias() @@ -165,7 +169,7 @@ def cleanup(): os.remove(f) def createfile(): - f = open(tempfile.mktemp(), 'w') + f = open(tempfile.mktemp(), 'wb') temp.append(f.name) os.chmod(f.name, 0o700) return f @@ -185,7 +189,7 @@ def loadfile(path, *name): pass u = mirror[path].urlopen(key.name) if u.scheme == 'file': - p = urllib.unquote(urlparse.urlsplit(u.geturl()).path) + p = urlunquote(urlsplit(u.geturl()).path) cache[key] = CacheEntry(p, key) pass else: diff --git a/src/mio/parser.py b/src/mio/parser.py index 8e0f823af97b3240d7dc7b7a8626a29b52cace4c..582871a804b5c5d8e95b9b929d42c6c4e2d68ae4 100755 --- a/src/mio/parser.py +++ b/src/mio/parser.py @@ -6,8 +6,14 @@ import time import xml.sax import xml.parsers.expat import traceback -import urlparse -import urllib2 +try: + # Python 3 + from urllib.request import urlopen + from urllib.parse import urlparse +except ImportError: + # Python 2 fallback + from urllib2 import urlopen + from urlparse import urlparse __doc__ = """ Package for xml parsing @@ -233,6 +239,9 @@ class AttributeAccessor: self._node = node self._name = name + def __lt__(self, other): + return self._name < other._name + def __getattr__(self, attr): message = "%s.%s not qualified with [...] for %s" % ( self._node._tag, self._name, attr) @@ -334,6 +343,9 @@ class Node: raise Exception("Undefined attribute '%s' in '%s'" % (k, tag)) self._attribute[k] = attr[k] + def __lt__(self, other): + return self._tag < other._tag + def __copy__(self): """Copy node, but not children""" result = Node(self._tag, self._line, self._attribute) @@ -367,9 +379,9 @@ class Node: result = "" line = "%s<%s" % (" " * indent, self._tag) blanks = " " * len(line) - key = self._attribute.keys() - key.sort(AttrSortWrapper(self, attr_sort)) - for k in key: + for k in sorted(self._attribute.keys(), + key=(attr_sort and AttrSortWrapper(self, attr_sort) + or None)): s = " %s='%s'" % (k, xml_escape(self._attribute[k])) if len(line) + len(s) > width: result += "%s\n" % line @@ -384,9 +396,11 @@ class Node: result += '\n'.join(self._char) result += '\n' pass - child = self._children - child.sort(TagSortWrapper(self, tag_sort)) - for c in child: + print("YYY", (tag_sort and TagSortWrapper(self, tag_sort) + or None), "\n") + for c in sorted(self._children, + key=(tag_sort and TagSortWrapper(self, tag_sort) + or None)): result += c._xml(indent + 1, attr_sort, tag_sort, width) result += "%s</%s>\n" % (" " * indent, self._tag) return result @@ -523,7 +537,7 @@ class Parser: def parse(source, include_comments=False, url=None): """Parse the given 'source' returning an easily traversable tree""" - (scheme, host, path, param, query, frag) = urlparse.urlparse(source) + (scheme, host, path, param, query, frag) = urlparse(source) if not scheme: data = open(source).read() mtime = os.stat(source)[stat.ST_MTIME] diff --git a/src/mio/path.py b/src/mio/path.py index 4b83639e2e520229ccb1b2f90d5a171523f26d7c..5a555d8ee468a9f49dabf299f8f792f85ab22ae8 100755 --- a/src/mio/path.py +++ b/src/mio/path.py @@ -1,6 +1,11 @@ import re import os.path -import urlparse +try: + # Python 3 + from urllib.parse import urlparse, urlunparse +except ImportError: + # Python 2 fallback + from urlparse import urlparse, urlunparse def join(elements): """join and normalize elements to a proper (url) path""" @@ -10,16 +15,16 @@ def join(elements): if len(join) > 0: join += '/' join += e - (scheme, host, path, param, query, frag) = urlparse.urlparse(join) + (scheme, host, path, param, query, frag) = urlparse(join) if scheme: path = re.sub('/+', '/', path) - result = urlparse.urlunparse((scheme, host, path, param, query, frag)) + result = urlunparse((scheme, host, path, param, query, frag)) else: result = re.sub('/+', '/', join) return result def geturl(p): - (scheme, host, path, param, query, frag) = urlparse.urlparse(p) + (scheme, host, path, param, query, frag) = urlparse(p) if not scheme: scheme = 'file' host ='' @@ -27,10 +32,10 @@ def geturl(p): param = '' query = '' frag = '' - return urlparse.urlunparse((scheme, host, path, param, query, frag)) + return urlunparse((scheme, host, path, param, query, frag)) def getfile(p): - (scheme, host, path, param, query, frag) = urlparse.urlparse(geturl(p)) + (scheme, host, path, param, query, frag) = urlparse(geturl(p)) if scheme == 'file': return path else: diff --git a/src/mio/repository.py b/src/mio/repository.py index c1d5c23eb701e27aeffd5137b73d95f3fd890252..65a31323c7b0397052994fc6e219fb1138edbb95 100755 --- a/src/mio/repository.py +++ b/src/mio/repository.py @@ -53,8 +53,7 @@ class Repository: g._url = None group.append(g) result = self.expand(group, error, {}) - result.sort(by_name) - return result + return sorted(result, key=lambda a: a.name) def expand(self, targets, error=None, done={}): result = [] @@ -78,10 +77,3 @@ class Repository: raise return result -def by_name(a,b): - if a.name[0] < b.name[0]: - return -1 - elif a.name[0] == b.name[0]: - return 0 - else: - return 1 diff --git a/src/mio/urlgrabber_compat.py b/src/mio/urlgrabber_compat.py index b48ac394dff9e42f96c228f3fc15df4bf822f40f..c5654e3276c299ecc402726109704f45fd572f1c 100755 --- a/src/mio/urlgrabber_compat.py +++ b/src/mio/urlgrabber_compat.py @@ -1,7 +1,12 @@ # # Hackish compat library when urlgrabber is missing (MacOS) # -import urllib2 +try: + # Python 3 + from urllib.request import urlopen +except ImportError: + # Python 2 fallback + from urllib2 import urlopen import calendar import time @@ -27,7 +32,7 @@ class CurlWrapper: pass class Compat: - URLGrabError = Exception() + URLGrabError = Exception def URLGrabber(self): pass @@ -38,13 +43,15 @@ class Compat: self.urls = urls def urlopen(self, path): + errors = [] for u in self.urls: url = "%s/%s" % (u, path) try: - return CurlWrapper(urllib2.urlopen(url)) + return CurlWrapper(urlopen(url)) except IOError as e: + errors.append((url,e)) pass - raise IOError("Failed to get '%s' (%s)" % (path, e)) + raise IOError("Failed to get '%s' (%s)" % (path, errors)) pass diff --git a/src/mio/util.py b/src/mio/util.py index 3e691d2349f0cddf3eb54cb6986c4d538aeb9146..4418193f51f2fb904142eea2773980a0580f4f78 100755 --- a/src/mio/util.py +++ b/src/mio/util.py @@ -4,6 +4,12 @@ import pwd import re from mio.log import log, NORMAL, VERBOSE +try: + # Python 2 + from __builtin__ import unicode +except ModuleNotFoundError: + # Python 3 + from builtins import str as unicode def mode_mask(s): result = 0 for c in s: diff --git a/src/mio/yum.py b/src/mio/yum.py index e0874678f2f6ffbcc7d4a8885788691a33b0d56d..a8eab0ce7a35f71a3e0a2790c9e83b4aef174dc1 100755 --- a/src/mio/yum.py +++ b/src/mio/yum.py @@ -97,7 +97,7 @@ def run(path, rpm, exclude): # to be done before the install, because outdated packages # need to be updated before the install, or we might get # a conflict. - exclude_arg = map(lambda s: "-x %s" % s, exclude) + exclude_arg = [ "-x %s" % s for s in exclude ] update = "%s -c %s -e %s -d %s -y update %s" % ( CMD, f.name, verb, verb, " ".join(exclude_arg)) mio.log.log(NORMAL, update) @@ -111,5 +111,6 @@ def run(path, rpm, exclude): i += 1 mio.log.log(NORMAL, "[%d/%d] %s %s" % (i, len(rpm), install, p)) tmp = mio.daemon_cage.system("%s %s" % (install, p)) - result = max(filter(None, [result, tmp]) or [0]) + if tmp > result: + result = tmp return result