[Spice-devel] [PATCH] Make spice_codegen.py work on both Python 2 and 3

Alexander Wauck awauck at codeweavers.com
Thu Mar 26 08:56:53 PDT 2015


This *should* be enough to make spice_codegen.py work on both Python 2
and Python 3.  I have not tested with Python 2.5 or 2.6, though, nor
have I done particularly thorough testing in general.  I would
appreciate getting some more knowledgeable eyes on this.

(Sorry for the long diff, but I had to use six.py for the
 2/3 compatibility.  Should that be something the user is
 required to install instead of us bundling it?)

Signed-off-by: Alexander Wauck <awauck at codeweavers.com>
---
 python_modules/codegen.py      |  28 +-
 python_modules/demarshal.py    |  10 +-
 python_modules/marshal.py      |  18 +-
 python_modules/ptypes.py       |  62 +--
 python_modules/six.py          | 838 +++++++++++++++++++++++++++++++++++++++++
 python_modules/spice_parser.py |  13 +-
 spice_codegen.py               |  10 +-
 7 files changed, 913 insertions(+), 66 deletions(-)
 create mode 100644 python_modules/six.py

diff --git a/python_modules/codegen.py b/python_modules/codegen.py
index 009cf95..4ff4c55 100644
--- a/python_modules/codegen.py
+++ b/python_modules/codegen.py
@@ -1,5 +1,6 @@
-from __future__ import with_statement
-from cStringIO import StringIO
+
+from . import six
+from io import StringIO
 
 def camel_to_underscores(s, upper = False):
     res = ""
@@ -85,10 +86,10 @@ class CodeWriter:
         self.options[opt] = value
 
     def has_option(self, opt):
-        return self.options.has_key(opt)
+        return opt in self.options
 
     def set_is_generated(self, kind, name):
-        if not self.generated.has_key(kind):
+        if kind not in self.generated:
             v = {}
             self.generated[kind] = v
         else:
@@ -96,13 +97,13 @@ class CodeWriter:
         v[name] = 1
 
     def is_generated(self, kind, name):
-        if not self.generated.has_key(kind):
+        if kind not in self.generated:
             return False
         v = self.generated[kind]
-        return v.has_key(name)
+        return name in v
 
     def getvalue(self):
-        strs = map(lambda writer: writer.getvalue(), self.contents)
+        strs = [writer.getvalue() for writer in self.contents]
         return "".join(strs)
 
     def get_subwriter(self):
@@ -119,21 +120,24 @@ class CodeWriter:
         return writer
 
     def write(self, s):
-        # Ensure its a string
-        s = str(s)
+        # Ensure its a unicode string
+        if six.PY2:
+            s = unicode(s)
+        else:
+            s = str(s)
 
         if len(s) == 0:
             return
 
         if self.at_line_start:
             for i in range(self.indentation):
-                self.out.write(" ")
+                self.out.write(u" ")
             self.at_line_start = False
         self.out.write(s)
         return self
 
     def newline(self):
-        self.out.write("\n")
+        self.out.write(u"\n")
         self.at_line_start = True
         return self
 
@@ -341,7 +345,7 @@ class CodeWriter:
         self.indentation = indentation
 
     def add_function_variable(self, ctype, name):
-        if self.function_variables.has_key(name):
+        if name in self.function_variables:
             assert(self.function_variables[name] == ctype)
         else:
             self.function_variables[name] = ctype
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 109f5e6..f6047b0 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -1,6 +1,6 @@
-from __future__ import with_statement
-import ptypes
-import codegen
+
+from . import ptypes
+from . import codegen
 
 # The handling of sizes is somewhat complex, as there are several types of size:
 # * nw_size
@@ -1119,7 +1119,7 @@ def write_channel_parser(writer, channel, server):
     ids2 = ids.copy()
     while len(ids2) > 0:
         end = start = min(ids2.keys())
-        while ids2.has_key(end):
+        while end in ids2:
             del ids2[end]
             end = end + 1
 
@@ -1181,7 +1181,7 @@ def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
     writer.begin_block()
     channel = None
     for i in range(0, max_channel + 1):
-        if channel_parsers.has_key(i):
+        if i in channel_parsers:
             channel = channel_parsers[i][0]
             if channel.has_attr("ifdef"):
                 writer.ifdef(channel.attributes["ifdef"][0])
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 1eda1ba..b77b910 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -1,6 +1,6 @@
-from __future__ import with_statement
-import ptypes
-import codegen
+
+from . import ptypes
+from . import codegen
 
 def write_includes(writer):
     writer.header.writeln("#include <spice/protocol.h>")
@@ -112,7 +112,7 @@ def write_marshal_ptr_function(writer, target_type, is_helper=True):
     names = target_type.get_pointer_names(False)
     names_args = ""
     if len(names) > 0:
-        n = map(lambda name: ", SpiceMarshaller **%s_out" % name, names)
+        n = [", SpiceMarshaller **%s_out" % name for name in names]
         names_args = "".join(n)
 
     header = writer.header
@@ -345,7 +345,7 @@ def write_message_marshaller(writer, message, is_server, private):
     names = message.get_pointer_names(False)
     names_args = ""
     if len(names) > 0:
-        n = map(lambda name: ", SpiceMarshaller **%s_out" % name, names)
+        n = [", SpiceMarshaller **%s_out" % name for name in names]
         names_args = "".join(n)
 
     if not private:
@@ -383,9 +383,9 @@ def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
             for m in channel.client_messages:
                 message = m.message_type
                 f = write_message_marshaller(writer, message, is_server, private_marshallers)
-                if channel.has_attr("ifdef") and not functions.has_key(f):
+                if channel.has_attr("ifdef") and f not in functions:
                     functions[f] = channel.attributes["ifdef"][0]
-                elif message.has_attr("ifdef") and not functions.has_key(f):
+                elif message.has_attr("ifdef") and f not in functions:
                     functions[f] = message.attributes["ifdef"][0]
                 else:
                     functions[f] = True
@@ -393,9 +393,9 @@ def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
             for m in channel.server_messages:
                 message = m.message_type
                 f = write_message_marshaller(writer, message, is_server, private_marshallers)
-                if channel.has_attr("ifdef") and not functions.has_key(f):
+                if channel.has_attr("ifdef") and f not in functions:
                     functions[f] = channel.attributes["ifdef"][0]
-                elif message.has_attr("ifdef") and not functions.has_key(f):
+                elif message.has_attr("ifdef") and f not in functions:
                     functions[f] = message.attributes["ifdef"][0]
                 else:
                     functions[f] = True
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index 2bfbf0d..7ddc72a 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -1,4 +1,4 @@
-import codegen
+from . import codegen
 import types
 
 _types_by_name = {}
@@ -7,7 +7,7 @@ _types = []
 default_pointer_size = 4
 
 def type_exists(name):
-    return _types_by_name.has_key(name)
+    return name in _types_by_name
 
 def lookup_type(name):
     return _types_by_name[name]
@@ -24,7 +24,7 @@ class FixedSize:
             self.vals[minor] = val
 
     def __add__(self, other):
-        if isinstance(other, types.IntType):
+        if isinstance(other, int):
             other = FixedSize(other)
 
         new = FixedSize()
@@ -125,13 +125,13 @@ class Type:
         if self.registred or self.name == None:
             return
         self.registred = True
-        if _types_by_name.has_key(self.name):
-            raise Exception, "Type %s already defined" % self.name
+        if self.name in _types_by_name:
+            raise Exception("Type %s already defined" % self.name)
         _types.append(self)
         _types_by_name[self.name] = self
 
     def has_attr(self, name):
-        return self.attributes.has_key(name)
+        return name in self.attributes
 
 class TypeRef(Type):
     def __init__(self, name):
@@ -142,8 +142,8 @@ class TypeRef(Type):
         return "ref to %s" % (self.name)
 
     def resolve(self):
-        if not _types_by_name.has_key(self.name):
-            raise Exception, "Unknown type %s" % self.name
+        if self.name not in _types_by_name:
+            raise Exception("Unknown type %s" % self.name)
         return _types_by_name[self.name]
 
     def register(self):
@@ -252,7 +252,7 @@ class EnumBaseType(Type):
     def c_describe(self, writer):
         writer.write("static const value_string %s_vs[] = " % codegen.prefix_underscore_lower(self.name))
         writer.begin_block()
-        values = self.names.keys()
+        values = list(self.names.keys())
         values.sort()
         for i in values:
             writer.write("{ ")
@@ -281,7 +281,7 @@ class EnumType(EnumBaseType):
                 value = last + 1
             last = value
 
-            assert not names.has_key(value)
+            assert value not in names
             names[value] = name
             values[name] = value
 
@@ -298,7 +298,7 @@ class EnumType(EnumBaseType):
         writer.write("typedef enum ")
         writer.write(self.c_name())
         writer.begin_block()
-        values = self.names.keys()
+        values = list(self.names.keys())
         values.sort()
         current_default = 0
         for i in values:
@@ -335,7 +335,7 @@ class FlagsType(EnumBaseType):
                 value = last + 1
             last = value
 
-            assert not names.has_key(value)
+            assert value not in names
             names[value] = name
             values[name] = value
 
@@ -352,7 +352,7 @@ class FlagsType(EnumBaseType):
         writer.write("typedef enum ")
         writer.write(self.c_name())
         writer.begin_block()
-        values = self.names.keys()
+        values = list(self.names.keys())
         values.sort()
         mask = 0
         for i in values:
@@ -392,26 +392,26 @@ class ArrayType(Type):
         return self
 
     def is_constant_length(self):
-        return isinstance(self.size, types.IntType)
+        return isinstance(self.size, int)
 
     def is_remaining_length(self):
-        return isinstance(self.size, types.StringType) and len(self.size) == 0
+        return isinstance(self.size, str) and len(self.size) == 0
 
     def is_identifier_length(self):
-        return isinstance(self.size, types.StringType) and len(self.size) > 0
+        return isinstance(self.size, str) and len(self.size) > 0
 
     def is_image_size_length(self):
-        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+        if isinstance(self.size, int) or isinstance(self.size, str):
             return False
         return self.size[0] == "image_size"
 
     def is_bytes_length(self):
-        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+        if isinstance(self.size, int) or isinstance(self.size, str):
             return False
         return self.size[0] == "bytes"
 
     def is_cstring_length(self):
-        if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+        if isinstance(self.size, int) or isinstance(self.size, str):
             return False
         return self.size[0] == "cstring"
 
@@ -423,7 +423,7 @@ class ArrayType(Type):
 
     def get_fixed_nw_size(self):
         if not self.is_fixed_nw_size():
-            raise Exception, "Not a fixed size type"
+            raise Exception("Not a fixed size type")
 
         return self.element_type.get_fixed_nw_size() * self.size
 
@@ -433,13 +433,13 @@ class ArrayType(Type):
             return 0
         if self.is_constant_length(self):
             return element_count * self.size
-        raise Exception, "Pointers in dynamic arrays not supported"
+        raise Exception("Pointers in dynamic arrays not supported")
 
     def get_pointer_names(self, marshalled):
         element_count = self.element_type.get_num_pointers()
         if element_count  == 0:
             return []
-        raise Exception, "Pointer names in arrays not supported"
+        raise Exception("Pointer names in arrays not supported")
 
     def is_extra_size(self):
         return self.has_attr("ptr_array")
@@ -517,7 +517,7 @@ class Containee:
         return not self.is_switch() and self.member_type.is_primitive()
 
     def has_attr(self, name):
-        return self.attributes.has_key(name)
+        return name in self.attributes
 
     def has_minor_attr(self):
         return self.has_attr("minor")
@@ -599,7 +599,7 @@ class Member(Containee):
             names = self.member_type.get_pointer_names(marshalled)
         if self.has_attr("outvar"):
             prefix = self.attributes["outvar"][0]
-            names = map(lambda name: prefix + "_" + name, names)
+            names = [prefix + "_" + name for name in names]
         return names
 
 class SwitchCase:
@@ -656,7 +656,7 @@ class Switch(Containee):
 
     def resolve(self, container):
         self.container = container
-        self.cases = map(lambda c : c.resolve(self), self.cases)
+        self.cases = [c.resolve(self) for c in self.cases]
         return self
 
     def __repr__(self):
@@ -703,7 +703,7 @@ class Switch(Containee):
 
     def get_fixed_nw_size(self):
         if not self.is_fixed_nw_size():
-            raise Exception, "Not a fixed size type"
+            raise Exception("Not a fixed size type")
         size = 0
         for c in self.cases:
             size = max(size, c.member.get_fixed_nw_size())
@@ -774,7 +774,7 @@ class ContainerType(Type):
         return size
 
     def resolve(self):
-        self.members = map(lambda m : m.resolve(self), self.members)
+        self.members = [m.resolve(self) for m in self.members]
         return self
 
     def get_num_pointers(self):
@@ -819,7 +819,7 @@ class ContainerType(Type):
             name = name[:dot]
 
         member = None
-        if self.members_by_name.has_key(name):
+        if name in self.members_by_name:
             member = self.members_by_name[name]
         else:
             for m in self.members:
@@ -831,7 +831,7 @@ class ContainerType(Type):
                     break
 
         if member == None:
-            raise Exception, "No member called %s found" % name
+            raise Exception("No member called %s found" % name)
 
         if rest != None:
             return member.member_type.lookup_member(rest)
@@ -880,7 +880,7 @@ class MessageType(ContainerType):
 
     def c_name(self):
         if self.name == None:
-            cms = self.reverse_members.keys()
+            cms = list(self.reverse_members.keys())
             if len(cms) != 1:
                 raise "Unknown typename for message"
             cm = cms[0]
@@ -900,7 +900,7 @@ class MessageType(ContainerType):
         if self.has_attr("ctype"):
             return self.attributes["ctype"][0]
         if self.name == None:
-            cms = self.reverse_members.keys()
+            cms = list(self.reverse_members.keys())
             if len(cms) != 1:
                 raise "Unknown typename for message"
             cm = cms[0]
diff --git a/python_modules/six.py b/python_modules/six.py
new file mode 100644
index 0000000..ffa3fe1
--- /dev/null
+++ b/python_modules/six.py
@@ -0,0 +1,838 @@
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+# Copyright (c) 2010-2015 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+from __future__ import absolute_import
+
+import functools
+import itertools
+import operator
+import sys
+import types
+
+__author__ = "Benjamin Peterson <benjamin at python.org>"
+__version__ = "1.9.0"
+
+
+# Useful for very coarse version differentiation.
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    string_types = str,
+    integer_types = int,
+    class_types = type,
+    text_type = str
+    binary_type = bytes
+
+    MAXSIZE = sys.maxsize
+else:
+    string_types = basestring,
+    integer_types = (int, long)
+    class_types = (type, types.ClassType)
+    text_type = unicode
+    binary_type = str
+
+    if sys.platform.startswith("java"):
+        # Jython always uses 32 bits.
+        MAXSIZE = int((1 << 31) - 1)
+    else:
+        # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
+        class X(object):
+            def __len__(self):
+                return 1 << 31
+        try:
+            len(X())
+        except OverflowError:
+            # 32-bit
+            MAXSIZE = int((1 << 31) - 1)
+        else:
+            # 64-bit
+            MAXSIZE = int((1 << 63) - 1)
+        del X
+
+
+def _add_doc(func, doc):
+    """Add documentation to a function."""
+    func.__doc__ = doc
+
+
+def _import_module(name):
+    """Import module, returning the module after the last dot."""
+    __import__(name)
+    return sys.modules[name]
+
+
+class _LazyDescr(object):
+
+    def __init__(self, name):
+        self.name = name
+
+    def __get__(self, obj, tp):
+        result = self._resolve()
+        setattr(obj, self.name, result) # Invokes __set__.
+        try:
+            # This is a bit ugly, but it avoids running this again by
+            # removing this descriptor.
+            delattr(obj.__class__, self.name)
+        except AttributeError:
+            pass
+        return result
+
+
+class MovedModule(_LazyDescr):
+
+    def __init__(self, name, old, new=None):
+        super(MovedModule, self).__init__(name)
+        if PY3:
+            if new is None:
+                new = name
+            self.mod = new
+        else:
+            self.mod = old
+
+    def _resolve(self):
+        return _import_module(self.mod)
+
+    def __getattr__(self, attr):
+        _module = self._resolve()
+        value = getattr(_module, attr)
+        setattr(self, attr, value)
+        return value
+
+
+class _LazyModule(types.ModuleType):
+
+    def __init__(self, name):
+        super(_LazyModule, self).__init__(name)
+        self.__doc__ = self.__class__.__doc__
+
+    def __dir__(self):
+        attrs = ["__doc__", "__name__"]
+        attrs += [attr.name for attr in self._moved_attributes]
+        return attrs
+
+    # Subclasses should override this
+    _moved_attributes = []
+
+
+class MovedAttribute(_LazyDescr):
+
+    def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
+        super(MovedAttribute, self).__init__(name)
+        if PY3:
+            if new_mod is None:
+                new_mod = name
+            self.mod = new_mod
+            if new_attr is None:
+                if old_attr is None:
+                    new_attr = name
+                else:
+                    new_attr = old_attr
+            self.attr = new_attr
+        else:
+            self.mod = old_mod
+            if old_attr is None:
+                old_attr = name
+            self.attr = old_attr
+
+    def _resolve(self):
+        module = _import_module(self.mod)
+        return getattr(module, self.attr)
+
+
+class _SixMetaPathImporter(object):
+    """
+    A meta path importer to import six.moves and its submodules.
+
+    This class implements a PEP302 finder and loader. It should be compatible
+    with Python 2.5 and all existing versions of Python3
+    """
+    def __init__(self, six_module_name):
+        self.name = six_module_name
+        self.known_modules = {}
+
+    def _add_module(self, mod, *fullnames):
+        for fullname in fullnames:
+            self.known_modules[self.name + "." + fullname] = mod
+
+    def _get_module(self, fullname):
+        return self.known_modules[self.name + "." + fullname]
+
+    def find_module(self, fullname, path=None):
+        if fullname in self.known_modules:
+            return self
+        return None
+
+    def __get_module(self, fullname):
+        try:
+            return self.known_modules[fullname]
+        except KeyError:
+            raise ImportError("This loader does not know module " + fullname)
+
+    def load_module(self, fullname):
+        try:
+            # in case of a reload
+            return sys.modules[fullname]
+        except KeyError:
+            pass
+        mod = self.__get_module(fullname)
+        if isinstance(mod, MovedModule):
+            mod = mod._resolve()
+        else:
+            mod.__loader__ = self
+        sys.modules[fullname] = mod
+        return mod
+
+    def is_package(self, fullname):
+        """
+        Return true, if the named module is a package.
+
+        We need this method to get correct spec objects with
+        Python 3.4 (see PEP451)
+        """
+        return hasattr(self.__get_module(fullname), "__path__")
+
+    def get_code(self, fullname):
+        """Return None
+
+        Required, if is_package is implemented"""
+        self.__get_module(fullname)  # eventually raises ImportError
+        return None
+    get_source = get_code  # same as get_code
+
+_importer = _SixMetaPathImporter(__name__)
+
+
+class _MovedItems(_LazyModule):
+    """Lazy loading of moved objects"""
+    __path__ = []  # mark as package
+
+
+_moved_attributes = [
+    MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
+    MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
+    MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
+    MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
+    MovedAttribute("intern", "__builtin__", "sys"),
+    MovedAttribute("map", "itertools", "builtins", "imap", "map"),
+    MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
+    MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
+    MovedAttribute("reduce", "__builtin__", "functools"),
+    MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
+    MovedAttribute("StringIO", "StringIO", "io"),
+    MovedAttribute("UserDict", "UserDict", "collections"),
+    MovedAttribute("UserList", "UserList", "collections"),
+    MovedAttribute("UserString", "UserString", "collections"),
+    MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
+    MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
+    MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
+
+    MovedModule("builtins", "__builtin__"),
+    MovedModule("configparser", "ConfigParser"),
+    MovedModule("copyreg", "copy_reg"),
+    MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
+    MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
+    MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
+    MovedModule("http_cookies", "Cookie", "http.cookies"),
+    MovedModule("html_entities", "htmlentitydefs", "html.entities"),
+    MovedModule("html_parser", "HTMLParser", "html.parser"),
+    MovedModule("http_client", "httplib", "http.client"),
+    MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
+    MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
+    MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
+    MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
+    MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
+    MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
+    MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
+    MovedModule("cPickle", "cPickle", "pickle"),
+    MovedModule("queue", "Queue"),
+    MovedModule("reprlib", "repr"),
+    MovedModule("socketserver", "SocketServer"),
+    MovedModule("_thread", "thread", "_thread"),
+    MovedModule("tkinter", "Tkinter"),
+    MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
+    MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
+    MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
+    MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
+    MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
+    MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
+    MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
+    MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
+    MovedModule("tkinter_colorchooser", "tkColorChooser",
+                "tkinter.colorchooser"),
+    MovedModule("tkinter_commondialog", "tkCommonDialog",
+                "tkinter.commondialog"),
+    MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
+    MovedModule("tkinter_font", "tkFont", "tkinter.font"),
+    MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
+    MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
+                "tkinter.simpledialog"),
+    MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
+    MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
+    MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
+    MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
+    MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
+    MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
+    MovedModule("winreg", "_winreg"),
+]
+for attr in _moved_attributes:
+    setattr(_MovedItems, attr.name, attr)
+    if isinstance(attr, MovedModule):
+        _importer._add_module(attr, "moves." + attr.name)
+del attr
+
+_MovedItems._moved_attributes = _moved_attributes
+
+moves = _MovedItems(__name__ + ".moves")
+_importer._add_module(moves, "moves")
+
+
+class Module_six_moves_urllib_parse(_LazyModule):
+    """Lazy loading of moved objects in six.moves.urllib_parse"""
+
+
+_urllib_parse_moved_attributes = [
+    MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
+    MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
+    MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
+    MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
+    MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
+    MovedAttribute("urljoin", "urlparse", "urllib.parse"),
+    MovedAttribute("urlparse", "urlparse", "urllib.parse"),
+    MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
+    MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
+    MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
+    MovedAttribute("quote", "urllib", "urllib.parse"),
+    MovedAttribute("quote_plus", "urllib", "urllib.parse"),
+    MovedAttribute("unquote", "urllib", "urllib.parse"),
+    MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
+    MovedAttribute("urlencode", "urllib", "urllib.parse"),
+    MovedAttribute("splitquery", "urllib", "urllib.parse"),
+    MovedAttribute("splittag", "urllib", "urllib.parse"),
+    MovedAttribute("splituser", "urllib", "urllib.parse"),
+    MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_params", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_query", "urlparse", "urllib.parse"),
+    MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
+]
+for attr in _urllib_parse_moved_attributes:
+    setattr(Module_six_moves_urllib_parse, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
+                      "moves.urllib_parse", "moves.urllib.parse")
+
+
+class Module_six_moves_urllib_error(_LazyModule):
+    """Lazy loading of moved objects in six.moves.urllib_error"""
+
+
+_urllib_error_moved_attributes = [
+    MovedAttribute("URLError", "urllib2", "urllib.error"),
+    MovedAttribute("HTTPError", "urllib2", "urllib.error"),
+    MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
+]
+for attr in _urllib_error_moved_attributes:
+    setattr(Module_six_moves_urllib_error, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
+                      "moves.urllib_error", "moves.urllib.error")
+
+
+class Module_six_moves_urllib_request(_LazyModule):
+    """Lazy loading of moved objects in six.moves.urllib_request"""
+
+
+_urllib_request_moved_attributes = [
+    MovedAttribute("urlopen", "urllib2", "urllib.request"),
+    MovedAttribute("install_opener", "urllib2", "urllib.request"),
+    MovedAttribute("build_opener", "urllib2", "urllib.request"),
+    MovedAttribute("pathname2url", "urllib", "urllib.request"),
+    MovedAttribute("url2pathname", "urllib", "urllib.request"),
+    MovedAttribute("getproxies", "urllib", "urllib.request"),
+    MovedAttribute("Request", "urllib2", "urllib.request"),
+    MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
+    MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
+    MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
+    MovedAttribute("FileHandler", "urllib2", "urllib.request"),
+    MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
+    MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
+    MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
+    MovedAttribute("urlretrieve", "urllib", "urllib.request"),
+    MovedAttribute("urlcleanup", "urllib", "urllib.request"),
+    MovedAttribute("URLopener", "urllib", "urllib.request"),
+    MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
+    MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
+]
+for attr in _urllib_request_moved_attributes:
+    setattr(Module_six_moves_urllib_request, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
+                      "moves.urllib_request", "moves.urllib.request")
+
+
+class Module_six_moves_urllib_response(_LazyModule):
+    """Lazy loading of moved objects in six.moves.urllib_response"""
+
+
+_urllib_response_moved_attributes = [
+    MovedAttribute("addbase", "urllib", "urllib.response"),
+    MovedAttribute("addclosehook", "urllib", "urllib.response"),
+    MovedAttribute("addinfo", "urllib", "urllib.response"),
+    MovedAttribute("addinfourl", "urllib", "urllib.response"),
+]
+for attr in _urllib_response_moved_attributes:
+    setattr(Module_six_moves_urllib_response, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
+                      "moves.urllib_response", "moves.urllib.response")
+
+
+class Module_six_moves_urllib_robotparser(_LazyModule):
+    """Lazy loading of moved objects in six.moves.urllib_robotparser"""
+
+
+_urllib_robotparser_moved_attributes = [
+    MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
+]
+for attr in _urllib_robotparser_moved_attributes:
+    setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
+                      "moves.urllib_robotparser", "moves.urllib.robotparser")
+
+
+class Module_six_moves_urllib(types.ModuleType):
+    """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
+    __path__ = []  # mark as package
+    parse = _importer._get_module("moves.urllib_parse")
+    error = _importer._get_module("moves.urllib_error")
+    request = _importer._get_module("moves.urllib_request")
+    response = _importer._get_module("moves.urllib_response")
+    robotparser = _importer._get_module("moves.urllib_robotparser")
+
+    def __dir__(self):
+        return ['parse', 'error', 'request', 'response', 'robotparser']
+
+_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
+                      "moves.urllib")
+
+
+def add_move(move):
+    """Add an item to six.moves."""
+    setattr(_MovedItems, move.name, move)
+
+
+def remove_move(name):
+    """Remove item from six.moves."""
+    try:
+        delattr(_MovedItems, name)
+    except AttributeError:
+        try:
+            del moves.__dict__[name]
+        except KeyError:
+            raise AttributeError("no such move, %r" % (name,))
+
+
+if PY3:
+    _meth_func = "__func__"
+    _meth_self = "__self__"
+
+    _func_closure = "__closure__"
+    _func_code = "__code__"
+    _func_defaults = "__defaults__"
+    _func_globals = "__globals__"
+else:
+    _meth_func = "im_func"
+    _meth_self = "im_self"
+
+    _func_closure = "func_closure"
+    _func_code = "func_code"
+    _func_defaults = "func_defaults"
+    _func_globals = "func_globals"
+
+
+try:
+    advance_iterator = next
+except NameError:
+    def advance_iterator(it):
+        return it.next()
+next = advance_iterator
+
+
+try:
+    callable = callable
+except NameError:
+    def callable(obj):
+        return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+
+if PY3:
+    def get_unbound_function(unbound):
+        return unbound
+
+    create_bound_method = types.MethodType
+
+    Iterator = object
+else:
+    def get_unbound_function(unbound):
+        return unbound.im_func
+
+    def create_bound_method(func, obj):
+        return types.MethodType(func, obj, obj.__class__)
+
+    class Iterator(object):
+
+        def next(self):
+            return type(self).__next__(self)
+
+    callable = callable
+_add_doc(get_unbound_function,
+         """Get the function out of a possibly unbound function""")
+
+
+get_method_function = operator.attrgetter(_meth_func)
+get_method_self = operator.attrgetter(_meth_self)
+get_function_closure = operator.attrgetter(_func_closure)
+get_function_code = operator.attrgetter(_func_code)
+get_function_defaults = operator.attrgetter(_func_defaults)
+get_function_globals = operator.attrgetter(_func_globals)
+
+
+if PY3:
+    def iterkeys(d, **kw):
+        return iter(d.keys(**kw))
+
+    def itervalues(d, **kw):
+        return iter(d.values(**kw))
+
+    def iteritems(d, **kw):
+        return iter(d.items(**kw))
+
+    def iterlists(d, **kw):
+        return iter(d.lists(**kw))
+
+    viewkeys = operator.methodcaller("keys")
+
+    viewvalues = operator.methodcaller("values")
+
+    viewitems = operator.methodcaller("items")
+else:
+    def iterkeys(d, **kw):
+        return iter(d.iterkeys(**kw))
+
+    def itervalues(d, **kw):
+        return iter(d.itervalues(**kw))
+
+    def iteritems(d, **kw):
+        return iter(d.iteritems(**kw))
+
+    def iterlists(d, **kw):
+        return iter(d.iterlists(**kw))
+
+    viewkeys = operator.methodcaller("viewkeys")
+
+    viewvalues = operator.methodcaller("viewvalues")
+
+    viewitems = operator.methodcaller("viewitems")
+
+_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
+_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
+_add_doc(iteritems,
+         "Return an iterator over the (key, value) pairs of a dictionary.")
+_add_doc(iterlists,
+         "Return an iterator over the (key, [values]) pairs of a dictionary.")
+
+
+if PY3:
+    def b(s):
+        return s.encode("latin-1")
+    def u(s):
+        return s
+    unichr = chr
+    if sys.version_info[1] <= 1:
+        def int2byte(i):
+            return bytes((i,))
+    else:
+        # This is about 2x faster than the implementation above on 3.2+
+        int2byte = operator.methodcaller("to_bytes", 1, "big")
+    byte2int = operator.itemgetter(0)
+    indexbytes = operator.getitem
+    iterbytes = iter
+    import io
+    StringIO = io.StringIO
+    BytesIO = io.BytesIO
+    _assertCountEqual = "assertCountEqual"
+    _assertRaisesRegex = "assertRaisesRegex"
+    _assertRegex = "assertRegex"
+else:
+    def b(s):
+        return s
+    # Workaround for standalone backslash
+    def u(s):
+        return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
+    unichr = unichr
+    int2byte = chr
+    def byte2int(bs):
+        return ord(bs[0])
+    def indexbytes(buf, i):
+        return ord(buf[i])
+    iterbytes = functools.partial(itertools.imap, ord)
+    import StringIO
+    StringIO = BytesIO = StringIO.StringIO
+    _assertCountEqual = "assertItemsEqual"
+    _assertRaisesRegex = "assertRaisesRegexp"
+    _assertRegex = "assertRegexpMatches"
+_add_doc(b, """Byte literal""")
+_add_doc(u, """Text literal""")
+
+
+def assertCountEqual(self, *args, **kwargs):
+    return getattr(self, _assertCountEqual)(*args, **kwargs)
+
+
+def assertRaisesRegex(self, *args, **kwargs):
+    return getattr(self, _assertRaisesRegex)(*args, **kwargs)
+
+
+def assertRegex(self, *args, **kwargs):
+    return getattr(self, _assertRegex)(*args, **kwargs)
+
+
+if PY3:
+    exec_ = getattr(moves.builtins, "exec")
+
+
+    def reraise(tp, value, tb=None):
+        if value is None:
+            value = tp()
+        if value.__traceback__ is not tb:
+            raise value.with_traceback(tb)
+        raise value
+
+else:
+    def exec_(_code_, _globs_=None, _locs_=None):
+        """Execute code in a namespace."""
+        if _globs_ is None:
+            frame = sys._getframe(1)
+            _globs_ = frame.f_globals
+            if _locs_ is None:
+                _locs_ = frame.f_locals
+            del frame
+        elif _locs_ is None:
+            _locs_ = _globs_
+        exec("""exec _code_ in _globs_, _locs_""")
+
+
+    exec_("""def reraise(tp, value, tb=None):
+    raise tp, value, tb
+""")
+
+
+if sys.version_info[:2] == (3, 2):
+    exec_("""def raise_from(value, from_value):
+    if from_value is None:
+        raise value
+    raise value from from_value
+""")
+elif sys.version_info[:2] > (3, 2):
+    exec_("""def raise_from(value, from_value):
+    raise value from from_value
+""")
+else:
+    def raise_from(value, from_value):
+        raise value
+
+
+print_ = getattr(moves.builtins, "print", None)
+if print_ is None:
+    def print_(*args, **kwargs):
+        """The new-style print function for Python 2.4 and 2.5."""
+        fp = kwargs.pop("file", sys.stdout)
+        if fp is None:
+            return
+        def write(data):
+            if not isinstance(data, basestring):
+                data = str(data)
+            # If the file has an encoding, encode unicode with it.
+            if (isinstance(fp, file) and
+                isinstance(data, unicode) and
+                fp.encoding is not None):
+                errors = getattr(fp, "errors", None)
+                if errors is None:
+                    errors = "strict"
+                data = data.encode(fp.encoding, errors)
+            fp.write(data)
+        want_unicode = False
+        sep = kwargs.pop("sep", None)
+        if sep is not None:
+            if isinstance(sep, unicode):
+                want_unicode = True
+            elif not isinstance(sep, str):
+                raise TypeError("sep must be None or a string")
+        end = kwargs.pop("end", None)
+        if end is not None:
+            if isinstance(end, unicode):
+                want_unicode = True
+            elif not isinstance(end, str):
+                raise TypeError("end must be None or a string")
+        if kwargs:
+            raise TypeError("invalid keyword arguments to print()")
+        if not want_unicode:
+            for arg in args:
+                if isinstance(arg, unicode):
+                    want_unicode = True
+                    break
+        if want_unicode:
+            newline = unicode("\n")
+            space = unicode(" ")
+        else:
+            newline = "\n"
+            space = " "
+        if sep is None:
+            sep = space
+        if end is None:
+            end = newline
+        for i, arg in enumerate(args):
+            if i:
+                write(sep)
+            write(arg)
+        write(end)
+if sys.version_info[:2] < (3, 3):
+    _print = print_
+    def print_(*args, **kwargs):
+        fp = kwargs.get("file", sys.stdout)
+        flush = kwargs.pop("flush", False)
+        _print(*args, **kwargs)
+        if flush and fp is not None:
+            fp.flush()
+
+_add_doc(reraise, """Reraise an exception.""")
+
+if sys.version_info[0:2] < (3, 4):
+    def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
+              updated=functools.WRAPPER_UPDATES):
+        def wrapper(f):
+            f = functools.wraps(wrapped, assigned, updated)(f)
+            f.__wrapped__ = wrapped
+            return f
+        return wrapper
+else:
+    wraps = functools.wraps
+
+def with_metaclass(meta, *bases):
+    """Create a base class with a metaclass."""
+    # This requires a bit of explanation: the basic idea is to make a dummy
+    # metaclass for one level of class instantiation that replaces itself with
+    # the actual metaclass.
+    class metaclass(meta):
+        def __new__(cls, name, this_bases, d):
+            return meta(name, bases, d)
+    return type.__new__(metaclass, 'temporary_class', (), {})
+
+
+def add_metaclass(metaclass):
+    """Class decorator for creating a class with a metaclass."""
+    def wrapper(cls):
+        orig_vars = cls.__dict__.copy()
+        slots = orig_vars.get('__slots__')
+        if slots is not None:
+            if isinstance(slots, str):
+                slots = [slots]
+            for slots_var in slots:
+                orig_vars.pop(slots_var)
+        orig_vars.pop('__dict__', None)
+        orig_vars.pop('__weakref__', None)
+        return metaclass(cls.__name__, cls.__bases__, orig_vars)
+    return wrapper
+
+
+def python_2_unicode_compatible(klass):
+    """
+    A decorator that defines __unicode__ and __str__ methods under Python 2.
+    Under Python 3 it does nothing.
+
+    To support Python 2 and 3 with a single code base, define a __str__ method
+    returning text and apply this decorator to the class.
+    """
+    if PY2:
+        if '__str__' not in klass.__dict__:
+            raise ValueError("@python_2_unicode_compatible cannot be applied "
+                             "to %s because it doesn't define __str__()." %
+                             klass.__name__)
+        klass.__unicode__ = klass.__str__
+        klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
+    return klass
+
+
+# Complete the moves implementation.
+# This code is at the end of this module to speed up module loading.
+# Turn this module into a package.
+__path__ = []  # required for PEP 302 and PEP 451
+__package__ = __name__  # see PEP 366 @ReservedAssignment
+if globals().get("__spec__") is not None:
+    __spec__.submodule_search_locations = []  # PEP 451 @UndefinedVariable
+# Remove other six meta path importers, since they cause problems. This can
+# happen if six is removed from sys.modules and then reloaded. (Setuptools does
+# this for some reason.)
+if sys.meta_path:
+    for i, importer in enumerate(sys.meta_path):
+        # Here's some real nastiness: Another "instance" of the six module might
+        # be floating around. Therefore, we can't use isinstance() to check for
+        # the six meta path importer, since the other six instance will have
+        # inserted an importer with different class.
+        if (type(importer).__name__ == "_SixMetaPathImporter" and
+            importer.name == __name__):
+            del sys.meta_path[i]
+            break
+    del i, importer
+# Finally, add the importer to the meta path import hook.
+sys.meta_path.append(_importer)
diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py
index 44456ab..89bdf1e 100644
--- a/python_modules/spice_parser.py
+++ b/python_modules/spice_parser.py
@@ -3,11 +3,12 @@ try:
             Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \
             alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith
 except ImportError:
-    print "Module pyparsing not found."
+    six.print_("Module pyparsing not found.")
     exit(1)
 
 
-import ptypes
+from . import ptypes
+from . import six
 import sys
 
 cvtInt = lambda toks: int(toks[0])
@@ -148,10 +149,10 @@ def parse(filename):
     try:
         bnf = SPICE_BNF()
         types = bnf.parseFile(filename)
-    except ParseException, err:
-        print >> sys.stderr, err.line
-        print >> sys.stderr, " "*(err.column-1) + "^"
-        print >> sys.stderr, err
+    except ParseException as err:
+        six.print_(err.line, file=sys.stderr)
+        six.print_(" "*(err.column-1) + "^", file=sys.stderr)
+        six.print_(err, file=sys.stderr)
         return None
 
     for t in types:
diff --git a/spice_codegen.py b/spice_codegen.py
index c8376cc..c559999 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -9,6 +9,7 @@ from python_modules import ptypes
 from python_modules import codegen
 from python_modules import demarshal
 from python_modules import marshal
+from python_modules import six
 
 def write_channel_enums(writer, channel, client, describe):
     messages = filter(lambda m : m.channel == channel, \
@@ -257,15 +258,18 @@ if options.keep_identical_file:
         f.close()
 
         if content == old_content:
-            print "No changes to %s" % dest_file
+            six.print_("No changes to %s" % dest_file)
             sys.exit(0)
 
     except IOError:
         pass
 
 f = open(dest_file, 'wb')
-f.write(content)
+if six.PY2:
+    f.write(content)
+else:
+    f.write(bytes(content, 'UTF-8'))
 f.close()
 
-print "Wrote %s" % dest_file
+six.print_("Wrote %s" % dest_file)
 sys.exit(0)
-- 
2.3.4



More information about the Spice-devel mailing list