[libvirt] [PATCH v2 0/8] Introduce partial Python 3 support

This series takes care of all the trivial stuff, paving the way for someone with good Python knowledge to jump in and finish porting. Changes since [v1]: * the build system no longer needs tweaks; * patches are organized by type of change for easier review. [v1] https://www.redhat.com/archives/libvir-list/2018-March/msg00687.html Andrea Bolognani (8): python3: Use the print() function python3: Use the repr() function python3: Use the 'in' keyword python3: Remove uses of string.*() functions python3: Call list() explicitly as needed python3: Replace keys() + sort() with sorted() python3: Open files in text instead of binary mode python3: Fix sort function docs/apibuild.py | 372 ++++++++++++++++++------------------- src/esx/esx_vi_generator.py | 27 ++- src/hyperv/hyperv_wmi_generator.py | 17 +- 3 files changed, 200 insertions(+), 216 deletions(-) -- 2.14.3

It has replaced the 'print' statement. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 85 ++++++++++++++++++++------------------ src/esx/esx_vi_generator.py | 8 ++-- src/hyperv/hyperv_wmi_generator.py | 8 ++-- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index a788086a65..9ac6442337 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -7,6 +7,9 @@ # # daniel@veillard.com # + +from __future__ import print_function + import os, sys import string import glob @@ -150,8 +153,8 @@ class identifier: else: self.conditionals = conditionals[:] if self.name == debugsym and not quiet: - print "=> define %s : %s" % (debugsym, (module, type, info, - extra, conditionals)) + print("=> define %s : %s" % (debugsym, (module, type, info, + extra, conditionals))) def __repr__(self): r = "%s %s:" % (self.type, self.name) @@ -210,8 +213,8 @@ class identifier: def update(self, header, module, type = None, info = None, extra=None, conditionals=None): if self.name == debugsym and not quiet: - print "=> update %s : %s" % (debugsym, (module, type, info, - extra, conditionals)) + print("=> update %s : %s" % (debugsym, (module, type, info, + extra, conditionals))) if header is not None and self.header is None: self.set_header(module) if module is not None and (self.module is None or self.header == self.module): @@ -243,7 +246,7 @@ class index: def warning(self, msg): global warnings warnings = warnings + 1 - print msg + print(msg) def add_ref(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None): if name[0:2] == '__': @@ -263,7 +266,7 @@ class index: self.references[name] = d if name == debugsym and not quiet: - print "New ref: %s" % (d) + print("New ref: %s" % (d)) return d @@ -304,7 +307,7 @@ class index: self.warning("Unable to register type ", type) if name == debugsym and not quiet: - print "New symbol: %s" % (d) + print("New symbol: %s" % (d)) return d @@ -344,8 +347,8 @@ class index: self.identifiers[id] = idx.structs[id] for id in idx.unions.keys(): if self.unions.has_key(id): - print "union %s from %s redeclared in %s" % ( - id, self.unions[id].header, idx.unions[id].header) + print("union %s from %s redeclared in %s" % ( + id, self.unions[id].header, idx.unions[id].header)) else: self.unions[id] = idx.unions[id] self.identifiers[id] = idx.unions[id] @@ -394,8 +397,8 @@ class index: up = idx.functions[id] self.functions[id].update(None, up.module, up.type, up.info, up.extra) # else: - # print "Function %s from %s is not declared in headers" % ( - # id, idx.functions[id].module) + # print("Function %s from %s is not declared in headers" % ( + # id, idx.functions[id].module)) # TODO: do the same for variables. def analyze_dict(self, type, dict): @@ -407,9 +410,9 @@ class index: if id.static == 0: public = public + 1 if count != public: - print " %d %s , %d public" % (count, type, public) + print(" %d %s , %d public" % (count, type, public)) elif count != 0: - print " %d public %s" % (count, type) + print(" %d public %s" % (count, type)) def analyze(self): @@ -460,9 +463,9 @@ class CLexer: self.tokens.insert(0, token) def debug(self): - print "Last token: ", self.last - print "Token queue: ", self.tokens - print "Line %d end: " % (self.lineno), self.line + print("Last token: ", self.last) + print("Token queue: ", self.tokens) + print("Line %d end: " % (self.lineno), self.line) def token(self): while self.tokens == []: @@ -691,22 +694,22 @@ class CParser: warnings = warnings + 1 if self.no_error: return - print msg + print(msg) def error(self, msg, token=-1): if self.no_error: return - print "Parse Error: " + msg + print("Parse Error: " + msg) if token != -1: - print "Got token ", token + print("Got token ", token) self.lexer.debug() sys.exit(1) def debug(self, msg, token=-1): - print "Debug: " + msg + print("Debug: " + msg) if token != -1: - print "Got token ", token + print("Got token ", token) self.lexer.debug() def parseTopComment(self, comment): @@ -1018,7 +1021,7 @@ class CParser: def parsePreproc(self, token): if debug: - print "=> preproc ", token, self.lexer.tokens + print("=> preproc ", token, self.lexer.tokens) name = token[1] if name == "#include": token = self.lexer.token() @@ -1156,7 +1159,7 @@ class CParser: continue else: if debug: - print "=> ", token + print("=> ", token) return token return None @@ -1267,7 +1270,7 @@ class CParser: elif token[0] == "sep" and token[1] == "}": self.struct_fields = fields #self.debug("end parseStruct", token) - #print fields + #print(fields) token = self.token() return token else: @@ -1306,7 +1309,7 @@ class CParser: self.type = base_type self.struct_fields = fields #self.debug("end parseStruct", token) - #print fields + #print(fields) return token # @@ -1322,7 +1325,7 @@ class CParser: elif token[0] == "sep" and token[1] == "}": self.union_fields = fields # self.debug("end parseUnion", token) - # print fields + # print(fields) token = self.token() return token else: @@ -1356,7 +1359,7 @@ class CParser: self.type = base_type self.union_fields = fields # self.debug("end parseUnion", token) - # print fields + # print(fields) return token # @@ -1914,7 +1917,7 @@ class CParser: return token if token[0] == 'sep' and token[1] == "{": token = self.token() -# print 'Entering extern "C line ', self.lineno() +# print('Entering extern "C line ', self.lineno()) while token is not None and (token[0] != 'sep' or token[1] != "}"): if token[0] == 'name': @@ -1924,7 +1927,7 @@ class CParser: "token %s %s unexpected at the top level" % ( token[0], token[1])) token = self.parseGlobal(token) -# print 'Exiting extern "C" line', self.lineno() +# print('Exiting extern "C" line', self.lineno()) token = self.token() return token else: @@ -2025,7 +2028,7 @@ class CParser: def parse(self): if not quiet: - print "Parsing %s" % (self.filename) + print("Parsing %s" % (self.filename)) token = self.token() while token is not None: if token[0] == 'name': @@ -2064,11 +2067,11 @@ class docBuilder: def warning(self, msg): global warnings warnings = warnings + 1 - print msg + print(msg) def error(self, msg): self.errors += 1 - print >>sys.stderr, "Error:", msg + print("Error:", msg, file=sys.stderr) def indexString(self, id, str): if str is None: @@ -2110,7 +2113,7 @@ class docBuilder: def analyze(self): if not quiet: - print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys())) + print("Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))) self.idx.analyze() def scanHeaders(self): @@ -2271,7 +2274,7 @@ class docBuilder: def serialize_function(self, output, name): id = self.idx.functions[name] if name == debugsym and not quiet: - print "=>", id + print("=>", id) # NB: this is consumed by a regex in 'getAPIFilenames' in hvsupport.pl output.write(" <%s name='%s' file='%s' module='%s'>\n" % (id.type, @@ -2312,7 +2315,7 @@ class docBuilder: output.write(" <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2]))) self.indexString(name, param[2]) except: - print >>sys.stderr, "Exception:", sys.exc_info()[1] + print("Exception:", sys.exc_info()[1], file=sys.stderr) self.warning("Failed to save function %s info: %s" % (name, `id.info`)) output.write(" </%s>\n" % (id.type)) @@ -2542,7 +2545,7 @@ class docBuilder: def serialize(self): filename = "%s/%s-api.xml" % (self.path, self.name) if not quiet: - print "Saving XML description %s" % (filename) + print("Saving XML description %s" % (filename)) output = open(filename, "w") output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') output.write("<api name='%s'>\n" % self.name) @@ -2578,12 +2581,12 @@ class docBuilder: output.close() if self.errors > 0: - print >>sys.stderr, "apibuild.py: %d error(s) encountered during generation" % self.errors + print("apibuild.py: %d error(s) encountered during generation" % self.errors, file=sys.stderr) sys.exit(3) filename = "%s/%s-refs.xml" % (self.path, self.name) if not quiet: - print "Saving XML Cross References %s" % (filename) + print("Saving XML Cross References %s" % (filename)) output = open(filename, "w") output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') output.write("<apirefs name='%s'>\n" % self.name) @@ -2596,7 +2599,7 @@ class app: def warning(self, msg): global warnings warnings = warnings + 1 - print msg + print(msg) def rebuild(self, name): if name not in ["libvirt", "libvirt-qemu", "libvirt-lxc", "libvirt-admin"]: @@ -2609,7 +2612,7 @@ class app: builddir = None if glob.glob(srcdir + "/../src/libvirt.c") != [] : if not quiet: - print "Rebuilding API description for %s" % name + print("Rebuilding API description for %s" % name) dirs = [srcdir + "/../src", srcdir + "/../src/util", srcdir + "/../include/libvirt"] @@ -2619,7 +2622,7 @@ class app: builder = docBuilder(name, srcdir, dirs, []) elif glob.glob("src/libvirt.c") != [] : if not quiet: - print "Rebuilding API description for %s" % name + print("Rebuilding API description for %s" % name) builder = docBuilder(name, srcdir, ["src", "src/util", "include/libvirt"], []) diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index a2b8bef721..d7e68f69b1 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -22,6 +22,8 @@ # <http://www.gnu.org/licenses/>. # +from __future__ import print_function + import sys import os import os.path @@ -1196,7 +1198,7 @@ class Enum(Type): def report_error(message): - print "error: " + message + print("error: " + message) sys.exit(1) @@ -1321,9 +1323,9 @@ def is_known_type(type): def open_and_print(filename): if filename.startswith("./"): - print " GEN " + filename[2:] + print(" GEN " + filename[2:]) else: - print " GEN " + filename + print(" GEN " + filename) return open(filename, "wb") diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index b60335e26b..f6e0523f32 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -20,6 +20,8 @@ # <http://www.gnu.org/licenses/>. # +from __future__ import print_function + import sys import os import os.path @@ -390,16 +392,16 @@ class Property: def open_and_print(filename): if filename.startswith("./"): - print " GEN " + filename[2:] + print(" GEN " + filename[2:]) else: - print " GEN " + filename + print(" GEN " + filename) return open(filename, "wb") def report_error(message): - print "error: " + message + print("error: " + message) sys.exit(1) -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:03PM +0100, Andrea Bolognani wrote:
It has replaced the 'print' statement.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 85 ++++++++++++++++++++------------------ src/esx/esx_vi_generator.py | 8 ++-- src/hyperv/hyperv_wmi_generator.py | 8 ++-- 3 files changed, 54 insertions(+), 47 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

This replaces the `` built-in. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index 9ac6442337..2e8932bb5e 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -163,11 +163,11 @@ class identifier: if self.module is not None: r = r + " from %s" % (self.module) if self.info is not None: - r = r + " " + `self.info` + r = r + " " + repr(self.info) if self.extra is not None: - r = r + " " + `self.extra` + r = r + " " + repr(self.extra) if self.conditionals is not None: - r = r + " " + `self.conditionals` + r = r + " " + repr(self.conditionals) return r @@ -2316,7 +2316,7 @@ class docBuilder: self.indexString(name, param[2]) except: print("Exception:", sys.exc_info()[1], file=sys.stderr) - self.warning("Failed to save function %s info: %s" % (name, `id.info`)) + self.warning("Failed to save function %s info: %s" % (name, repr(id.info))) output.write(" </%s>\n" % (id.type)) def serialize_exports(self, output, file): -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:04PM +0100, Andrea Bolognani wrote:
This replaces the `` built-in.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

This replaces uses of the has_key() method. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 60 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index 2e8932bb5e..e448e37ace 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -317,9 +317,9 @@ class index: # macro might be used to override functions or variables # definitions # - if self.macros.has_key(id): + if id in self.macros: del self.macros[id] - if self.functions.has_key(id): + if id in self.functions: self.warning("function %s from %s redeclared in %s" % ( id, self.functions[id].header, idx.functions[id].header)) else: @@ -330,30 +330,30 @@ class index: # macro might be used to override functions or variables # definitions # - if self.macros.has_key(id): + if id in self.macros: del self.macros[id] - if self.variables.has_key(id): + if id in self.variables: self.warning("variable %s from %s redeclared in %s" % ( id, self.variables[id].header, idx.variables[id].header)) else: self.variables[id] = idx.variables[id] self.identifiers[id] = idx.variables[id] for id in idx.structs.keys(): - if self.structs.has_key(id): + if id in self.structs: self.warning("struct %s from %s redeclared in %s" % ( id, self.structs[id].header, idx.structs[id].header)) else: self.structs[id] = idx.structs[id] self.identifiers[id] = idx.structs[id] for id in idx.unions.keys(): - if self.unions.has_key(id): + if id in self.unions: print("union %s from %s redeclared in %s" % ( id, self.unions[id].header, idx.unions[id].header)) else: self.unions[id] = idx.unions[id] self.identifiers[id] = idx.unions[id] for id in idx.typedefs.keys(): - if self.typedefs.has_key(id): + if id in self.typedefs: self.warning("typedef %s from %s redeclared in %s" % ( id, self.typedefs[id].header, idx.typedefs[id].header)) else: @@ -364,20 +364,20 @@ class index: # macro might be used to override functions or variables # definitions # - if self.variables.has_key(id): + if id in self.variables: continue - if self.functions.has_key(id): + if id in self.functions: continue - if self.enums.has_key(id): + if id in self.enums: continue - if self.macros.has_key(id): + if id in self.macros: self.warning("macro %s from %s redeclared in %s" % ( id, self.macros[id].header, idx.macros[id].header)) else: self.macros[id] = idx.macros[id] self.identifiers[id] = idx.macros[id] for id in idx.enums.keys(): - if self.enums.has_key(id): + if id in self.enums: self.warning("enum %s from %s redeclared in %s" % ( id, self.enums[id].header, idx.enums[id].header)) else: @@ -386,7 +386,7 @@ class index: def merge_public(self, idx): for id in idx.functions.keys(): - if self.functions.has_key(id): + if id in self.functions: # check that function condition agrees with header if idx.functions[id].conditionals != \ self.functions[id].conditionals: @@ -725,7 +725,7 @@ class CParser: line = m.group(2).lstrip() if item: - if res.has_key(item): + if item in res: res[item] = res[item] + " " + line else: res[item] = line @@ -824,7 +824,7 @@ class CParser: if name[0:2] == '__': quiet = 1 - if ignored_macros.has_key(name): + if name in ignored_macros: quiet = 1 args = [] @@ -903,7 +903,7 @@ class CParser: quiet = 1 if name[0:2] == '__': quiet = 1 - if ignored_functions.has_key(name): + if name in ignored_functions: quiet = 1 (ret, args) = description @@ -1149,7 +1149,7 @@ class CParser: while token is not None and token[1] != ";": token = self.lexer.token() return token - elif token[0] == "name" and ignored_words.has_key(token[1]): + elif token[0] == "name" and token[1] in ignored_words: (n, info) = ignored_words[token[1]] i = 0 while i < n: @@ -2104,7 +2104,7 @@ class docBuilder: # TODO: generalize this a bit if lower == 'and' or lower == 'the': pass - elif self.xref.has_key(token): + elif token in self.xref: self.xref[token].append(id) else: self.xref[token] = [id] @@ -2228,7 +2228,7 @@ class docBuilder: output.write(" <struct name='%s' file='%s' type='%s'" % ( name, self.modulename_file(id.header), id.info)) name = id.info[7:] - if self.idx.structs.has_key(name) and ( \ + if name in self.idx.structs and ( \ type(self.idx.structs[name].info) == type(()) or type(self.idx.structs[name].info) == type([])): output.write(">\n") @@ -2297,7 +2297,7 @@ class docBuilder: if ret[0] is not None: if ret[0] == "void": output.write(" <return type='void'/>\n") - elif (ret[1] is None or ret[1] == '') and not ignored_functions.has_key(name): + elif (ret[1] is None or ret[1] == '') and name not in ignored_functions: self.error("Missing documentation for return of function `%s'" % name) else: output.write(" <return type='%s' info='%s'/>\n" % ( @@ -2307,7 +2307,7 @@ class docBuilder: if param[0] == 'void': continue if (param[2] is None or param[2] == ''): - if ignored_functions.has_key(name): + if name in ignored_functions: output.write(" <arg name='%s' type='%s' info=''/>\n" % (param[1], param[0])) else: self.error("Missing documentation for arg `%s' of function `%s'" % (param[1], name)) @@ -2332,7 +2332,7 @@ class docBuilder: string.lower(data))) except: self.warning("Header %s lacks a %s description" % (module, data)) - if dict.info.has_key('Description'): + if 'Description' in dict.info: desc = dict.info['Description'] if string.find(desc, "DEPRECATED") != -1: output.write(" <deprecated/>\n") @@ -2341,17 +2341,17 @@ class docBuilder: ids.sort() for id in uniq(ids): # Macros are sometime used to masquerade other types. - if dict.functions.has_key(id): + if id in dict.functions: continue - if dict.variables.has_key(id): + if id in dict.variables: continue - if dict.typedefs.has_key(id): + if id in dict.typedefs: continue - if dict.structs.has_key(id): + if id in dict.structs: continue - if dict.unions.has_key(id): + if id in dict.unions: continue - if dict.enums.has_key(id): + if id in dict.enums: continue output.write(" <exports symbol='%s' type='macro'/>\n" % (id)) ids = dict.enums.keys() @@ -2401,7 +2401,7 @@ class docBuilder: for param in params: if param[0] == 'void': continue - if funcs.has_key(param[0]): + if param[0] in funcs: funcs[param[0]].append(name) else: funcs[param[0]] = [name] @@ -2431,7 +2431,7 @@ class docBuilder: (ret, params, desc) = id.info if ret[0] == "void": continue - if funcs.has_key(ret[0]): + if ret[0] in funcs: funcs[ret[0]].append(name) else: funcs[ret[0]] = [name] -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:05PM +0100, Andrea Bolognani wrote:
This replaces uses of the has_key() method.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 60 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

All of these have been replaced with methods. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 142 +++++++++++++++++++++++++++---------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index e448e37ace..2097400cd1 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -122,11 +122,11 @@ hidden_macros = { } def escape(raw): - raw = string.replace(raw, '&', '&') - raw = string.replace(raw, '<', '<') - raw = string.replace(raw, '>', '>') - raw = string.replace(raw, "'", ''') - raw = string.replace(raw, '"', '"') + raw = raw.replace('&', '&') + raw = raw.replace('<', '<') + raw = raw.replace('>', '>') + raw = raw.replace("'", ''') + raw = raw.replace('"', '"') return raw def uniq(items): @@ -440,16 +440,16 @@ class CLexer: if not line: return None self.lineno = self.lineno + 1 - line = string.lstrip(line) - line = string.rstrip(line) + line = line.lstrip() + line = line.rstrip() if line == '': continue while line[-1] == '\\': line = line[:-1] n = self.input.readline() self.lineno = self.lineno + 1 - n = string.lstrip(n) - n = string.rstrip(n) + n = n.lstrip() + n = n.rstrip() if not n: break else: @@ -478,8 +478,8 @@ class CLexer: return None if line[0] == '#': - self.tokens = map((lambda x: ('preproc', x)), - string.split(line)) + self.tokens = list(map((lambda x: ('preproc', x)), + line.split())) # We might have whitespace between the '#' and preproc # macro name, so instead of having a single token element @@ -572,21 +572,21 @@ class CLexer: while i < l: o = ord(line[i]) if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ - (o >= 48 and o <= 57) or string.find( - " \t(){}:;,+-*/%&!|[]=><", line[i]) == -1: + (o >= 48 and o <= 57) or \ + (" \t(){}:;,+-*/%&!|[]=><".find(line[i]) == -1): i = i + 1 else: break self.tokens.append(('name', line[s:i])) continue - if string.find("(){}:;,[]", line[i]) != -1: + if "(){}:;,[]".find(line[i]) != -1: # if line[i] == '(' or line[i] == ')' or line[i] == '{' or \ # line[i] == '}' or line[i] == ':' or line[i] == ';' or \ # line[i] == ',' or line[i] == '[' or line[i] == ']': self.tokens.append(('sep', line[i])) i = i + 1 continue - if string.find("+-*><=/%&!|.", line[i]) != -1: + if "+-*><=/%&!|.".find(line[i]) != -1: # if line[i] == '+' or line[i] == '-' or line[i] == '*' or \ # line[i] == '>' or line[i] == '<' or line[i] == '=' or \ # line[i] == '/' or line[i] == '%' or line[i] == '&' or \ @@ -599,7 +599,7 @@ class CLexer: j = i + 1 if j < l and ( - string.find("+-*><=/%&!|", line[j]) != -1): + "+-*><=/%&!|".find(line[j]) != -1): # line[j] == '+' or line[j] == '-' or line[j] == '*' or \ # line[j] == '>' or line[j] == '<' or line[j] == '=' or \ # line[j] == '/' or line[j] == '%' or line[j] == '&' or \ @@ -614,8 +614,8 @@ class CLexer: while i < l: o = ord(line[i]) if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \ - (o >= 48 and o <= 57) or ( - string.find(" \t(){}:;,+-*/%&!|[]=><", line[i]) == -1): + (o >= 48 and o <= 57) or \ + (" \t(){}:;,+-*/%&!|[]=><".find(line[i]) == -1): # line[i] != ' ' and line[i] != '\t' and # line[i] != '(' and line[i] != ')' and # line[i] != '{' and line[i] != '}' and @@ -714,7 +714,7 @@ class CParser: def parseTopComment(self, comment): res = {} - lines = string.split(comment, "\n") + lines = comment.split("\n") item = None for line in lines: line = line.lstrip().lstrip('*').lstrip() @@ -763,10 +763,10 @@ class CParser: self.comment = self.comment + com token = self.lexer.token() - if string.find(self.comment, "DOC_DISABLE") != -1: + if self.comment.find("DOC_DISABLE") != -1: self.stop_error() - if string.find(self.comment, "DOC_ENABLE") != -1: + if self.comment.find("DOC_ENABLE") != -1: self.start_error() return token @@ -789,7 +789,7 @@ class CParser: if not quiet: self.warning("Missing * in type comment for %s" % (name)) return((args, desc)) - lines = string.split(self.comment, '\n') + lines = self.comment.split('\n') if lines[0] == '*': del lines[0] if lines[0] != "* %s:" % (name): @@ -805,11 +805,11 @@ class CParser: l = lines[0] while len(l) > 0 and l[0] == '*': l = l[1:] - l = string.strip(l) + l = l.strip() desc = desc + " " + l del lines[0] - desc = string.strip(desc) + desc = desc.strip() if quiet == 0: if desc == "": @@ -838,7 +838,7 @@ class CParser: if not quiet: self.warning("Missing * in macro comment for %s" % (name)) return((args, desc)) - lines = string.split(self.comment, '\n') + lines = self.comment.split('\n') if lines[0] == '*': del lines[0] if lines[0] != "* %s:" % (name): @@ -852,9 +852,9 @@ class CParser: while len(lines) > 0 and lines[0][0:3] == '* @': l = lines[0][3:] try: - (arg, desc) = string.split(l, ':', 1) - desc=string.strip(desc) - arg=string.strip(arg) + (arg, desc) = l.split(':', 1) + desc = desc.strip() + arg = arg.strip() except: if not quiet: self.warning("Misformatted macro comment for %s" % (name)) @@ -862,11 +862,11 @@ class CParser: del lines[0] continue del lines[0] - l = string.strip(lines[0]) + l = lines[0].strip() while len(l) > 2 and l[0:3] != '* @': while l[0] == '*': l = l[1:] - desc = desc + ' ' + string.strip(l) + desc = desc + ' ' + l.strip() del lines[0] if len(lines) == 0: break @@ -879,11 +879,11 @@ class CParser: l = lines[0] while len(l) > 0 and l[0] == '*': l = l[1:] - l = string.strip(l) + l = l.strip() desc = desc + " " + l del lines[0] - desc = string.strip(desc) + desc = desc.strip() if quiet == 0: if desc == "": @@ -918,7 +918,7 @@ class CParser: if not quiet: self.warning("Missing * in function comment for %s" % (name)) return(((ret[0], retdesc), args, desc)) - lines = string.split(self.comment, '\n') + lines = self.comment.split('\n') if lines[0] == '*': del lines[0] if lines[0] != "* %s:" % (name): @@ -933,9 +933,9 @@ class CParser: while len(lines) > 0 and lines[0][0:3] == '* @': l = lines[0][3:] try: - (arg, desc) = string.split(l, ':', 1) - desc=string.strip(desc) - arg=string.strip(arg) + (arg, desc) = l.split(':', 1) + desc = desc.strip() + arg = arg.strip() except: if not quiet: self.warning("Misformatted function comment for %s" % (name)) @@ -943,11 +943,11 @@ class CParser: del lines[0] continue del lines[0] - l = string.strip(lines[0]) + l = lines[0].strip() while len(l) > 2 and l[0:3] != '* @': while l[0] == '*': l = l[1:] - desc = desc + ' ' + string.strip(l) + desc = desc + ' ' + l.strip() del lines[0] if len(lines) == 0: break @@ -978,16 +978,16 @@ class CParser: l = l[i:] if len(l) >= 6 and l[0:7] == "Returns": try: - l = string.split(l, ' ', 1)[1] + l = l.split(' ', 1)[1] except: l = "" - retdesc = string.strip(l) + retdesc = l.strip() del lines[0] while len(lines) > 0: l = lines[0] while len(l) > 0 and l[0] == '*': l = l[1:] - l = string.strip(l) + l = l.strip() retdesc = retdesc + " " + l del lines[0] else: @@ -999,8 +999,8 @@ class CParser: if desc is None: desc = "" - retdesc = string.strip(retdesc) - desc = string.strip(desc) + retdesc = retdesc.strip() + desc = desc.strip() if quiet == 0: # @@ -1046,7 +1046,7 @@ class CParser: lst.append(token[1]) token = self.lexer.token() try: - name = string.split(name, '(') [0] + name = name.split('(') [0] except: pass @@ -1083,7 +1083,7 @@ class CParser: apstr = self.lexer.tokens[0][1] try: self.defines.append(apstr) - if string.find(apstr, 'ENABLED') != -1: + if apstr.find('ENABLED') != -1: self.conditionals.append("defined(%s)" % apstr) except: pass @@ -1091,7 +1091,7 @@ class CParser: apstr = self.lexer.tokens[0][1] try: self.defines.append(apstr) - if string.find(apstr, 'ENABLED') != -1: + if apstr.find('ENABLED') != -1: self.conditionals.append("!defined(%s)" % apstr) except: pass @@ -1103,17 +1103,17 @@ class CParser: apstr = apstr + tok[1] try: self.defines.append(apstr) - if string.find(apstr, 'ENABLED') != -1: + if apstr.find('ENABLED') != -1: self.conditionals.append(apstr) except: pass elif name == "#else": if self.conditionals != [] and \ - string.find(self.defines[-1], 'ENABLED') != -1: + self.defines[-1].find('ENABLED') != -1: self.conditionals[-1] = "!(%s)" % self.conditionals[-1] elif name == "#endif": if self.conditionals != [] and \ - string.find(self.defines[-1], 'ENABLED') != -1: + self.defines[-1].find('ENABLED') != -1: self.conditionals = self.conditionals[:-1] self.defines = self.defines[:-1] token = self.lexer.token() @@ -1181,7 +1181,7 @@ class CParser: name = token[1] signature = self.signature if signature is not None: - type = string.split(type, '(')[0] + type = type.split('(')[0] d = self.mergeFunctionComment(name, ((type, None), signature), 1) self.index_add(name, self.filename, not self.is_header, @@ -1388,7 +1388,7 @@ class CParser: self.cleanupComment() if name is not None: if self.comment is not None: - comment = string.strip(self.comment) + comment = self.comment.strip() self.comment = None self.enums.append((name, value, comment)) name = token[1] @@ -2076,26 +2076,26 @@ class docBuilder: def indexString(self, id, str): if str is None: return - str = string.replace(str, "'", ' ') - str = string.replace(str, '"', ' ') - str = string.replace(str, "/", ' ') - str = string.replace(str, '*', ' ') - str = string.replace(str, "[", ' ') - str = string.replace(str, "]", ' ') - str = string.replace(str, "(", ' ') - str = string.replace(str, ")", ' ') - str = string.replace(str, "<", ' ') - str = string.replace(str, '>', ' ') - str = string.replace(str, "&", ' ') - str = string.replace(str, '#', ' ') - str = string.replace(str, ",", ' ') - str = string.replace(str, '.', ' ') - str = string.replace(str, ';', ' ') - tokens = string.split(str) + str = str.replace("'", ' ') + str = str.replace('"', ' ') + str = str.replace("/", ' ') + str = str.replace('*', ' ') + str = str.replace("[", ' ') + str = str.replace("]", ' ') + str = str.replace("(", ' ') + str = str.replace(")", ' ') + str = str.replace("<", ' ') + str = str.replace('>', ' ') + str = str.replace("&", ' ') + str = str.replace('#', ' ') + str = str.replace(",", ' ') + str = str.replace('.', ' ') + str = str.replace(';', ' ') + tokens = str.split() for token in tokens: try: c = token[0] - if string.find(string.letters, c) < 0: + if string.letters.find(c) < 0: pass elif len(token) < 3: pass @@ -2137,7 +2137,7 @@ class docBuilder: for file in files: skip = 1 for incl in self.includes: - if string.find(file, incl) != -1: + if file.find(incl) != -1: skip = 0 break if skip == 0: @@ -2146,7 +2146,7 @@ class docBuilder: for file in files: skip = 1 for incl in self.includes: - if string.find(file, incl) != -1: + if file.find(incl) != -1: skip = 0 break if skip == 0: @@ -2334,7 +2334,7 @@ class docBuilder: self.warning("Header %s lacks a %s description" % (module, data)) if 'Description' in dict.info: desc = dict.info['Description'] - if string.find(desc, "DEPRECATED") != -1: + if desc.find("DEPRECATED") != -1: output.write(" <deprecated/>\n") ids = dict.macros.keys() -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:06PM +0100, Andrea Bolognani wrote:
All of these have been replaced with methods.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 142 +++++++++++++++++++++++++++---------------------------- 1 file changed, 71 insertions(+), 71 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
@@ -478,8 +478,8 @@ class CLexer: return None
if line[0] == '#': - self.tokens = map((lambda x: ('preproc', x)), - string.split(line)) + self.tokens = list(map((lambda x: ('preproc', x)), + line.split()))
Nitpick - the list() addition belongs in a later patch Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, 2018-03-15 at 16:36 +0000, Daniel P. Berrangé wrote:
@@ -478,8 +478,8 @@ class CLexer: return None
if line[0] == '#': - self.tokens = map((lambda x: ('preproc', x)), - string.split(line)) + self.tokens = list(map((lambda x: ('preproc', x)), + line.split()))
Nitpick - the list() addition belongs in a later patch
Nice catch, I'll split the changes before pushing. -- Andrea Bolognani / Red Hat / Virtualization

For list concatenation to work, the value returned by the keys() method must be converted to a list first. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index 2097400cd1..bc6c609431 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -2049,13 +2049,13 @@ class docBuilder: self.path = path self.directories = directories if name == "libvirt": - self.includes = includes + included_files.keys() + self.includes = includes + list(included_files.keys()) elif name == "libvirt-qemu": - self.includes = includes + qemu_included_files.keys() + self.includes = includes + list(qemu_included_files.keys()) elif name == "libvirt-lxc": - self.includes = includes + lxc_included_files.keys() + self.includes = includes + list(lxc_included_files.keys()) elif name == "libvirt-admin": - self.includes = includes + admin_included_files.keys() + self.includes = includes + list(admin_included_files.keys()) self.modules = {} self.headers = {} self.idx = index() @@ -2383,9 +2383,12 @@ class docBuilder: module = self.modulename_file(file) output.write(" <file name='%s'>\n" % (module)) dict = self.headers[file] - ids = uniq(dict.functions.keys() + dict.variables.keys() + \ - dict.macros.keys() + dict.typedefs.keys() + \ - dict.structs.keys() + dict.enums.keys()) + ids = uniq(list(dict.functions.keys()) + \ + list(dict.variables.keys()) + \ + list(dict.macros.keys()) + \ + list(dict.typedefs.keys()) + \ + list(dict.structs.keys()) + \ + list(dict.enums.keys())) ids.sort() for id in ids: output.write(" <ref name='%s'/>\n" % (id)) -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:07PM +0100, Andrea Bolognani wrote:
For list concatenation to work, the value returned by the keys() method must be converted to a list first.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

The keys() method no longer returns a list, so converting the return value would be necessary before calling sort() on it; alternatively, we can just call sorted(), which returns a sorted list. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 60 +++++++++++++------------------------- src/esx/esx_vi_generator.py | 15 ++++------ src/hyperv/hyperv_wmi_generator.py | 3 +- 3 files changed, 26 insertions(+), 52 deletions(-) diff --git a/docs/apibuild.py b/docs/apibuild.py index bc6c609431..67b7eed1e6 100755 --- a/docs/apibuild.py +++ b/docs/apibuild.py @@ -133,8 +133,7 @@ def uniq(items): d = {} for item in items: d[item]=1 - k = d.keys() - k.sort() + k = sorted(d.keys()) return k class identifier: @@ -2337,8 +2336,7 @@ class docBuilder: if desc.find("DEPRECATED") != -1: output.write(" <deprecated/>\n") - ids = dict.macros.keys() - ids.sort() + ids = sorted(dict.macros.keys()) for id in uniq(ids): # Macros are sometime used to masquerade other types. if id in dict.functions: @@ -2354,31 +2352,25 @@ class docBuilder: if id in dict.enums: continue output.write(" <exports symbol='%s' type='macro'/>\n" % (id)) - ids = dict.enums.keys() - ids.sort() + ids = sorted(dict.enums.keys()) for id in uniq(ids): output.write(" <exports symbol='%s' type='enum'/>\n" % (id)) - ids = dict.typedefs.keys() - ids.sort() + ids = sorted(dict.typedefs.keys()) for id in uniq(ids): output.write(" <exports symbol='%s' type='typedef'/>\n" % (id)) - ids = dict.structs.keys() - ids.sort() + ids = sorted(dict.structs.keys()) for id in uniq(ids): output.write(" <exports symbol='%s' type='struct'/>\n" % (id)) - ids = dict.variables.keys() - ids.sort() + ids = sorted(dict.variables.keys()) for id in uniq(ids): output.write(" <exports symbol='%s' type='variable'/>\n" % (id)) - ids = dict.functions.keys() - ids.sort() + ids = sorted(dict.functions.keys()) for id in uniq(ids): output.write(" <exports symbol='%s' type='function'/>\n" % (id)) output.write(" </file>\n") def serialize_xrefs_files(self, output): - headers = self.headers.keys() - headers.sort() + headers = sorted(self.headers.keys()) for file in headers: module = self.modulename_file(file) output.write(" <file name='%s'>\n" % (module)) @@ -2410,8 +2402,7 @@ class docBuilder: funcs[param[0]] = [name] except: pass - typ = funcs.keys() - typ.sort() + typ = sorted(funcs.keys()) for type in typ: if type == '' or type == 'void' or type == "int" or \ type == "char *" or type == "const char *" : @@ -2440,23 +2431,20 @@ class docBuilder: funcs[ret[0]] = [name] except: pass - typ = funcs.keys() - typ.sort() + typ = sorted(funcs.keys()) for type in typ: if type == '' or type == 'void' or type == "int" or \ type == "char *" or type == "const char *" : continue output.write(" <type name='%s'>\n" % (type)) - ids = funcs[type] - ids.sort() + ids = sorted(funcs[type]) for id in ids: output.write(" <ref name='%s'/>\n" % (id)) output.write(" </type>\n") def serialize_xrefs_alpha(self, output): letter = None - ids = self.idx.identifiers.keys() - ids.sort() + ids = sorted(self.idx.identifiers.keys()) for id in ids: if id[0] != letter: if letter is not None: @@ -2468,8 +2456,7 @@ class docBuilder: output.write(" </letter>\n") def serialize_xrefs_references(self, output): - typ = self.idx.identifiers.keys() - typ.sort() + typ = sorted(self.idx.identifiers.keys()) for id in typ: idf = self.idx.identifiers[id] module = idf.header @@ -2480,8 +2467,7 @@ class docBuilder: def serialize_xrefs_index(self, output): index = self.xref - typ = index.keys() - typ.sort() + typ = sorted(index.keys()) letter = None count = 0 chunk = 0 @@ -2553,30 +2539,24 @@ class docBuilder: output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n') output.write("<api name='%s'>\n" % self.name) output.write(" <files>\n") - headers = self.headers.keys() - headers.sort() + headers = sorted(self.headers.keys()) for file in headers: self.serialize_exports(output, file) output.write(" </files>\n") output.write(" <symbols>\n") - macros = self.idx.macros.keys() - macros.sort() + macros = sorted(self.idx.macros.keys()) for macro in macros: self.serialize_macro(output, macro) - enums = self.idx.enums.keys() - enums.sort() + enums = sorted(self.idx.enums.keys()) for enum in enums: self.serialize_enum(output, enum) - typedefs = self.idx.typedefs.keys() - typedefs.sort() + typedefs = sorted(self.idx.typedefs.keys()) for typedef in typedefs: self.serialize_typedef(output, typedef) - variables = self.idx.variables.keys() - variables.sort() + variables = sorted(self.idx.variables.keys()) for variable in variables: self.serialize_variable(output, variable) - functions = self.idx.functions.keys() - functions.sort() + functions = sorted(self.idx.functions.keys()) for function in functions: self.serialize_function(output, function) output.write(" </symbols>\n") diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index d7e68f69b1..2f3c88812d 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1704,8 +1704,7 @@ types_typedef.write(separator + " * VI Enums\n" + " */\n\n") -names = enums_by_name.keys() -names.sort() +names = sorted(enums_by_name.keys()) for name in names: types_typedef.write(enums_by_name[name].generate_typedef()) @@ -1726,8 +1725,7 @@ types_typeenum.write("\n") types_typetostring.write("\n") types_typefromstring.write("\n") -names = objects_by_name.keys() -names.sort() +names = sorted(objects_by_name.keys()) for name in names: types_typedef.write(objects_by_name[name].generate_typedef()) @@ -1748,8 +1746,7 @@ types_typeenum.write("\n") types_typetostring.write("\n") types_typefromstring.write("\n") -names = managed_objects_by_name.keys() -names.sort() +names = sorted(managed_objects_by_name.keys()) for name in names: types_typedef.write(managed_objects_by_name[name].generate_typedef()) @@ -1762,8 +1759,7 @@ for name in names: # output methods -names = methods_by_name.keys() -names.sort() +names = sorted(methods_by_name.keys()) for name in names: methods_header.write(methods_by_name[name].generate_header()) @@ -1782,8 +1778,7 @@ for name in names: # output helpers -names = managed_objects_by_name.keys() -names.sort() +names = sorted(managed_objects_by_name.keys()) for name in names: helpers_header.write(managed_objects_by_name[name].generate_helper_header()) diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index f6e0523f32..1cf16a7836 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -501,8 +501,7 @@ def main(): classes_header.write(notice) classes_source.write(notice) - names = wmi_classes_by_name.keys() - names.sort() + names = sorted(wmi_classes_by_name.keys()) for name in names: cls = wmi_classes_by_name[name] -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:08PM +0100, Andrea Bolognani wrote:
The keys() method no longer returns a list, so converting the return value would be necessary before calling sort() on it; alternatively, we can just call sorted(), which returns a sorted list.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- docs/apibuild.py | 60 +++++++++++++------------------------- src/esx/esx_vi_generator.py | 15 ++++------ src/hyperv/hyperv_wmi_generator.py | 3 +- 3 files changed, 26 insertions(+), 52 deletions(-)
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

We use text operations on the contents after reading them. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- This seems reasonable and works correctly AFAICT, but I'm not 100% confident it's the right way to address the issue. src/esx/esx_vi_generator.py | 4 ++-- src/hyperv/hyperv_wmi_generator.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 2f3c88812d..6ce017d794 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1327,7 +1327,7 @@ def open_and_print(filename): else: print(" GEN " + filename) - return open(filename, "wb") + return open(filename, "wt") @@ -1435,7 +1435,7 @@ block = None # parse input file -for line in file(input_filename, "rb").readlines(): +for line in open(input_filename, "rt").readlines(): number += 1 if "#" in line: diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 1cf16a7836..7dc11ba905 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -396,7 +396,7 @@ def open_and_print(filename): else: print(" GEN " + filename) - return open(filename, "wb") + return open(filename, "wt") @@ -468,7 +468,7 @@ def main(): number = 0 block = None - for line in file(input_filename, "rb").readlines(): + for line in open(input_filename, "rt").readlines(): number += 1 if "#" in line: -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:09PM +0100, Andrea Bolognani wrote:
We use text operations on the contents after reading them.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- This seems reasonable and works correctly AFAICT, but I'm not 100% confident it's the right way to address the issue.
So in Python3 if you open in binary mode, it always gives you back "bytes", where as in text mode it gives you back "str". In python2 is always gives you back "str", which is actually equivalent to python3's "bytes" type. What fun. None the less, I think this change is likely correct.
src/esx/esx_vi_generator.py | 4 ++-- src/hyperv/hyperv_wmi_generator.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 2f3c88812d..6ce017d794 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1327,7 +1327,7 @@ def open_and_print(filename): else: print(" GEN " + filename)
- return open(filename, "wb") + return open(filename, "wt")
@@ -1435,7 +1435,7 @@ block = None
# parse input file -for line in file(input_filename, "rb").readlines(): +for line in open(input_filename, "rt").readlines(): number += 1
if "#" in line: diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 1cf16a7836..7dc11ba905 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -396,7 +396,7 @@ def open_and_print(filename): else: print(" GEN " + filename)
- return open(filename, "wb") + return open(filename, "wt")
@@ -468,7 +468,7 @@ def main(): number = 0 block = None
- for line in file(input_filename, "rb").readlines(): + for line in open(input_filename, "rt").readlines(): number += 1
if "#" in line: -- 2.14.3
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, Mar 15, 2018 at 04:28:56PM +0000, Daniel P. Berrangé wrote:
On Thu, Mar 15, 2018 at 05:11:09PM +0100, Andrea Bolognani wrote:
We use text operations on the contents after reading them.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- This seems reasonable and works correctly AFAICT, but I'm not 100% confident it's the right way to address the issue.
So in Python3 if you open in binary mode, it always gives you back "bytes", where as in text mode it gives you back "str". In python2 is always gives you back "str", which is actually equivalent to python3's "bytes" type. What fun.
None the less, I think this change is likely correct.
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
src/esx/esx_vi_generator.py | 4 ++-- src/hyperv/hyperv_wmi_generator.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index 2f3c88812d..6ce017d794 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1327,7 +1327,7 @@ def open_and_print(filename): else: print(" GEN " + filename)
- return open(filename, "wb") + return open(filename, "wt")
@@ -1435,7 +1435,7 @@ block = None
# parse input file -for line in file(input_filename, "rb").readlines(): +for line in open(input_filename, "rt").readlines(): number += 1
if "#" in line: diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 1cf16a7836..7dc11ba905 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -396,7 +396,7 @@ def open_and_print(filename): else: print(" GEN " + filename)
- return open(filename, "wb") + return open(filename, "wt")
@@ -468,7 +468,7 @@ def main(): number = 0 block = None
- for line in file(input_filename, "rb").readlines(): + for line in open(input_filename, "rt").readlines(): number += 1
if "#" in line: -- 2.14.3
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

This deals with cls.version possibly being None. Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- Really not sure about this one. The script runs all the way to the end after applying it, so there's that I guess. src/hyperv/hyperv_wmi_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 7dc11ba905..d548102117 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -59,7 +59,7 @@ class WmiClass: """ # sort vesioned classes by version in case input file did not have them # in order - self.versions = sorted(self.versions, key=lambda cls: cls.version) + self.versions = sorted(self.versions, key=lambda cls: cls.version or "") # if there's more than one verion make sure first one has name suffixed # because we'll generate "common" memeber and will be the "base" name -- 2.14.3

On Thu, Mar 15, 2018 at 05:11:10PM +0100, Andrea Bolognani wrote:
This deals with cls.version possibly being None.
Signed-off-by: Andrea Bolognani <abologna@redhat.com> --- Really not sure about this one. The script runs all the way to the end after applying it, so there's that I guess.
Python2 sorts None before "", which is in turn before any other non-zero length string. eg None < "" < "a" I'm thinking that cls.version doesn't care about the distinction between None and "", so your change is likely to be fine.
src/hyperv/hyperv_wmi_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/hyperv/hyperv_wmi_generator.py b/src/hyperv/hyperv_wmi_generator.py index 7dc11ba905..d548102117 100755 --- a/src/hyperv/hyperv_wmi_generator.py +++ b/src/hyperv/hyperv_wmi_generator.py @@ -59,7 +59,7 @@ class WmiClass: """ # sort vesioned classes by version in case input file did not have them # in order - self.versions = sorted(self.versions, key=lambda cls: cls.version) + self.versions = sorted(self.versions, key=lambda cls: cls.version or "")
# if there's more than one verion make sure first one has name suffixed # because we'll generate "common" memeber and will be the "base" name
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
participants (2)
-
Andrea Bolognani
-
Daniel P. Berrangé