Add support for building with Python 3
authorDavid Coles <dcoles@gaikai.com>
Sat, 9 Apr 2011 00:47:05 +0000 (17:47 -0700)
committerJulien Danjou <julien@danjou.info>
Wed, 4 May 2011 13:00:21 +0000 (15:00 +0200)
Python 3 introduces some language changes that cause issues when running
c_client.py. This also breaks compatibility with Python 2.5 since it does not
support the "as" statement in try/except blocks and does not have reduce() in
the functools package.

The main changes are:
* try/except blocks require `except ... as ...:` to resolve syntactical ambiguity
* map() and filter() return iterators rather than lists in Python 3
* reduce() is now in functools package (and not built-in in Python 3)
* Dictionaries don't have a has_key() method in Python 3
* None and int types can't be directly compared in Python 3
* print() is a statement in Python 3

See http://diveintopython3.org/porting-code-to-python-3-with-2to3.html and
PEP-3110 for details.

Verified on Python 2.6.5 and 3.1.3.

Signed-off-by: David Coles <dcoles@gaikai.com>
Signed-off-by: Julien Danjou <julien@danjou.info>
configure.ac
src/c_client.py

index 7e88481..1a8cd2e 100644 (file)
@@ -9,7 +9,7 @@ AC_CONFIG_SRCDIR([xcb.pc.in])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
-AM_PATH_PYTHON([2.5])
+AM_PATH_PYTHON([2.6])
 
 PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no])
 AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
index a10b3f1..3e77e9e 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 from xml.etree.cElementTree import *
 from os.path import basename
+from functools import reduce
 import getopt
 import sys
 import re
@@ -323,7 +324,7 @@ def _c_type_setup(self, name, postfix):
             field.c_field_type = _t(field.field_type)
             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
             field.c_field_name = _cpp(field.field_name)
-            field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
+            field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
 
             # correct the c_pointer field for variable size non-list types
@@ -443,7 +444,7 @@ def _c_helper_field_mapping(complex_type, prefix, flat=False):
     else:
         for f in complex_type.fields:
             fname = _c_helper_absolute_name(prefix, f)
-            if all_fields.has_key(f.field_name):
+            if f.field_name in all_fields:
                 raise Exception("field name %s has been registered before" % f.field_name)
 
             all_fields[f.field_name] = (fname, f)
@@ -524,7 +525,7 @@ def get_expr_fields(self):
         prefix.append(('', '', self))
 
     all_fields = _c_helper_resolve_field_names (prefix)
-    resolved_fields_names = filter(lambda x: x in all_fields.keys(), unresolved_fields_names)
+    resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
     if len(unresolved_fields_names) != len(resolved_fields_names):
         raise Exception("could not resolve all fields for %s" % self.name)
     
@@ -743,8 +744,8 @@ def _c_serialize_helper_list_field(context, self, field,
     param_names = [p[2] for p in params]
     
     expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
-    resolved = filter(lambda x: x in param_names, expr_fields_names)
-    unresolved = filter(lambda x: x not in param_names, expr_fields_names)
+    resolved = list(filter(lambda x: x in param_names, expr_fields_names))
+    unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
     
     field_mapping = {}
     for r in resolved:
@@ -757,8 +758,8 @@ def _c_serialize_helper_list_field(context, self, field,
                             field.c_field_name)        
         
         field_mapping.update(_c_helper_resolve_field_names(prefix))
-        resolved += filter(lambda x: x in field_mapping, unresolved)
-        unresolved = filter(lambda x: x not in field_mapping, unresolved)
+        resolved += list(filter(lambda x: x in field_mapping, unresolved))
+        unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
         if len(unresolved)>0:
             raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
 
@@ -1083,7 +1084,7 @@ def _c_serialize(context, self):
         param_str.append("%s%s%s  %s%s  /**< */" % (indent, typespec, spacing, pointerspec, field_name))
     # insert function name
     param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
-    param_str = map(lambda x: "%s," % x, param_str)
+    param_str = list(map(lambda x: "%s," % x, param_str))
     for s in param_str[:-1]:
         _hc(s)
     _h("%s);" % param_str[-1].rstrip(','))
@@ -1159,7 +1160,7 @@ def _c_serialize(context, self):
         if not (self.is_switch or self.var_followed_by_fixed_fields):
 
             # look if we have to declare an '_aux' variable at all
-            if len(filter(lambda x: x.find('_aux')!=-1, code_lines))>0: 
+            if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
                 if not self.var_followed_by_fixed_fields:
                     _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 else:
@@ -2282,9 +2283,9 @@ output = {'open'    : c_open,
 # Check for the argument that specifies path to the xcbgen python package.
 try:
     opts, args = getopt.getopt(sys.argv[1:], 'p:')
-except getopt.GetoptError, err:
-    print str(err)
-    print 'Usage: c_client.py [-p path] file.xml'
+except getopt.GetoptError as err:
+    print(err)
+    print('Usage: c_client.py [-p path] file.xml')
     sys.exit(1)
 
 for (opt, arg) in opts:
@@ -2295,13 +2296,13 @@ for (opt, arg) in opts:
 try:
     from xcbgen.state import Module
 except ImportError:
-    print ''
-    print 'Failed to load the xcbgen Python package!'
-    print 'Make sure that xcb/proto installed it on your Python path.'
-    print 'If not, you will need to create a .pth file or define $PYTHONPATH'
-    print 'to extend the path.'
-    print 'Refer to the README file in xcb/proto for more info.'
-    print ''
+    print('''
+Failed to load the xcbgen Python package!
+Make sure that xcb/proto installed it on your Python path.
+If not, you will need to create a .pth file or define $PYTHONPATH
+to extend the path.
+Refer to the README file in xcb/proto for more info.
+''')
     raise
 
 # Parse the xml header