2to3c: an implementation of Python's 2to3 for C code

David Malcolm dmalcolm at redhat.com
Sat Nov 21 02:01:17 CET 2009


I've written a tool to help people port their C python extensions from
Python 2 to Python 3.

It uses the Coccinelle tool [1] to apply a series of "semantic patches"
to .c files. I also had to code one of the refactorings in python with
regular expressions (due to the need to manipulate preprocessor macros
containing commas).

Sample session, running on a tarball of dbus-python:
[david at brick 2to3]$ ./2to3c --help
Usage: 2to3c [options] filenames...

Options:
  -h, --help   show this help message and exit
  -w, --write  Write back modified files
[david at brick 2to3]$ ./2to3c ../../python3/packaging/modules/by-hand/dbus-python/devel/dbus-python-0.83.0/_dbus_bindings/*.c > dbus-python.patch 

[david at brick 2to3]$ diffstat dbus-python.patch
 abstract.c       |   28 ++----
 bus.c            |    4 
 bytes.c          |   16 +--
 conn.c           |    7 -
 containers.c     |   21 ++--
 float.c          |    6 -
 generic.c        |    4 
 int.c            |   31 ++-----
 libdbusconn.c    |    5 -
 mainloop.c       |    3 
 message-append.c |    4 
 message.c        |   17 +--
 module.c         |  243 ++++++++++++++++++++++++++++++++++++++++++++-----------
 pending-call.c   |    3 
 server.c         |    7 -
 signature.c      |    6 -
 string.c         |    9 --
 17 files changed, 267 insertions(+), 147 deletions(-)

[david at brick 2to3]$ head -n 30 dbus-python.patch
--- ../../python3/packaging/modules/by-hand/dbus-python/devel/dbus-python-0.83.0/_dbus_bindings/abstract.c.orig 
+++ ../../python3/packaging/modules/by-hand/dbus-python/devel/dbus-python-0.83.0/_dbus_bindings/abstract.c 
@@ -54,7 +54,7 @@
 
     if (!vl_obj)
         return 0;
-    return PyInt_AsLong(vl_obj);
+    return PyLong_AsLong(vl_obj);
 }
 
 dbus_bool_t
@@ -76,7 +76,7 @@
         }
     }
     else {
-        PyObject *vl_obj = PyInt_FromLong(variant_level);
+        PyObject *vl_obj = PyLong_FromLong(variant_level);
         if (!vl_obj) {
             Py_DECREF(key);
             return FALSE;
@@ -127,7 +127,7 @@
     Py_DECREF(key);
 
     if (!value)
-        return PyInt_FromLong(0);
+        return PyLong_FromLong(0);
     Py_INCREF(value);
     return value;
 }


You can see the full patch it generated
here: http://dmalcolm.fedorapeople.org/dbus-python.patch

It hasn't done all of the work, there are some places involving the
preprocessor where it didn't quite generate correct code, and there are
some remaining issues - for example, a human is going to have to decide
whether the strings are bytes or unicode.

However, I think this ought to save a lot of time: it takes care of a
lot of the tedious parts of such patches.

The public git repo can be seen here:
http://fedorapeople.org/gitweb?p=dmalcolm/public_git/2to3c.git;a=tree

You should be able to download it by cloning it thus:
git clone git://fedorapeople.org/home/fedora/dmalcolm/public_git/2to3c.git

You'll need coccinelle installed; you can install it on Fedora using:
   yum install coccinelle

Patches most welcome! I intend to license this under LGPLv2.1, but am
happy to relicense as the Python core development community sees fit.

Dave

[1] http://coccinelle.lip6.fr/




More information about the Python-announce-list mailing list