extras/MySQL-python-1.2.3-python3.patch
author Radek Brich <radek.brich@devl.cz>
Mon, 27 Feb 2012 15:12:40 +0100
changeset 30 a8b7cd92f39f
parent 18 a9e12b7cc207
permissions -rw-r--r--
Fix analyzeall tool. Add user output formating to batchquery tool. Add isolation_level setting support to ToolBase.

Python3 patch for MySQL-python-1.2.3.
Based on https://github.com/davispuh/MySQL-for-Python-3
Removed incompatible (and absolutely unnecessary) changes.
diff -ru MySQL-python-1.2.3/_mysql.c MySQL-Python-1.2.3-python3/_mysql.c
--- MySQL-python-1.2.3/_mysql.c	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/_mysql.c	2011-10-05 12:49:58.000000000 +0200
@@ -31,33 +31,17 @@
 #if defined(MS_WINDOWS)
 #include <winsock2.h>
 #include <windows.h>
-#include <config-win.h>
-#else
-#include "my_config.h"
 #endif
+#include "my_config.h"
 #include "mysql.h"
 #include "mysqld_error.h"
 #include "errmsg.h"
 
-#if PY_VERSION_HEX < 0x02020000
-# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n, d)
-# define MyMember(a,b,c,d,e) {a,b,c,d}
-# define MyMemberlist(x) struct memberlist x
-# define MyAlloc(s,t) PyObject_New(s,&t)
-# define MyFree(o) PyObject_Del(o)
-#else
 # define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n)
 # define MyMember(a,b,c,d,e) {a,b,c,d,e}
 # define MyMemberlist(x) struct PyMemberDef x
 # define MyAlloc(s,t) (s *) t.tp_alloc(&t,0)
-# define MyFree(ob) ob->ob_type->tp_free((PyObject *)ob) 
-#endif
-
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#endif
+# define MyFree(ob) ob->ob_base.ob_type->tp_free((PyObject *)ob) 
 
 static PyObject *_mysql_MySQLError;
 static PyObject *_mysql_Warning;
@@ -86,7 +70,7 @@
 
 typedef struct {
 	PyObject_HEAD
-	PyObject *conn;
+	_mysql_ConnectionObject *conn;
 	MYSQL_RES *result;
 	int nfields;
 	int use;
@@ -102,17 +86,16 @@
 #define check_server_init(x) if (!_mysql_server_init_done) _mysql_server_init_done = 1
 #endif
 
-PyObject *
-_mysql_Exception(_mysql_ConnectionObject *c)
+PyObject * _mysql_Exception(_mysql_ConnectionObject *c)
 {
-	PyObject *t, *e;
+	PyObject *t, *e, *code, *message;
 	int merr;
 
 	if (!(t = PyTuple_New(2))) return NULL;
 	if (!_mysql_server_init_done) {
 		e = _mysql_InternalError;
-		PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L));
-		PyTuple_SET_ITEM(t, 1, PyString_FromString("server not initialized"));
+		PyTuple_SET_ITEM(t, 0, PyLong_FromLong(-1L));
+		PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("server not initialized"));
 		PyErr_SetObject(e, t);
 		Py_DECREF(t);
 		return NULL;
@@ -121,8 +104,8 @@
 	if (!merr)
 		e = _mysql_InterfaceError;
 	else if (merr > CR_MAX_ERROR) {
-		PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L));
-		PyTuple_SET_ITEM(t, 1, PyString_FromString("error totally whack"));
+		PyTuple_SET_ITEM(t, 0, PyLong_FromLong(-1L));
+		PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("error totally whack"));
 		PyErr_SetObject(_mysql_InterfaceError, t);
 		Py_DECREF(t);
 		return NULL;
@@ -209,8 +192,12 @@
 			e = _mysql_OperationalError;
 		break;
 	}
-	PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr));
-	PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection))));
+	code = PyLong_FromLong((long)merr);
+	message = PyUnicode_FromString(mysql_error(&(c->connection)));
+	PyTuple_SET_ITEM(t, 0, code );
+	PyTuple_SET_ITEM(t, 1, message );
+	PyObject_SetAttrString(e, "code", code );
+	PyObject_SetAttrString(e, "message", message );
 	PyErr_SetObject(e, t);
 	Py_DECREF(t);
 	return NULL;
@@ -259,7 +246,7 @@
 		cmd_args_c = (char **) PyMem_Malloc(cmd_argc*sizeof(char *));
 		for (i=0; i< cmd_argc; i++) {
 			item = PySequence_GetItem(cmd_args, i);
-			s = PyString_AsString(item);
+			s = PyBytes_AsString(item);
 			Py_DECREF(item);
 			if (!s) {
 				PyErr_SetString(PyExc_TypeError,
@@ -284,7 +271,7 @@
 		groups_c = (char **) PyMem_Malloc((1+groupc)*sizeof(char *));
 		for (i=0; i< groupc; i++) {
 			item = PySequence_GetItem(groups, i);
-			s = PyString_AsString(item);
+			s = PyBytes_AsString(item);
 			Py_DECREF(item);
 			if (!s) {
 				PyErr_SetString(PyExc_TypeError,
@@ -339,7 +326,7 @@
 	PyObject *flag;
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_server_init(NULL);
-	if (!(flag=PyInt_FromLong((long)mysql_thread_safe()))) return NULL;
+	if (!(flag=PyLong_FromLong((long)mysql_thread_safe()))) return NULL;
 	return flag;
 }
 #endif
@@ -372,7 +359,7 @@
 		return -1;
 	if (!conv) conv = PyDict_New();
 	if (!conv) return -1;
-	self->conn = (PyObject *) conn;
+	self->conn = conn;
 	Py_INCREF(conn);
 	self->use = use;
 	Py_BEGIN_ALLOW_THREADS ;
@@ -392,7 +379,7 @@
 	fields = mysql_fetch_fields(result);
 	for (i=0; i<n; i++) {
 		PyObject *tmp, *fun;
-		tmp = PyInt_FromLong((long) fields[i].type);
+		tmp = PyLong_FromLong((long) fields[i].type);
 		if (!tmp) return -1;
 		fun = PyObject_GetItem(conv, tmp);
 		Py_DECREF(tmp);
@@ -413,8 +400,8 @@
 					PyObject *pmask=NULL;
 					pmask = PyTuple_GET_ITEM(t, 0);
 					fun2 = PyTuple_GET_ITEM(t, 1);
-					if (PyInt_Check(pmask)) {
-						mask = PyInt_AS_LONG(pmask);
+					if (PyNumber_Check(pmask)) {
+						mask = PyLong_AS_LONG(pmask);
 						if (mask & fields[i].flags) {
 							Py_DECREF(t);
 							break;
@@ -440,7 +427,6 @@
 	return 0;
 }
 
-#if PY_VERSION_HEX >= 0x02020000
 static int _mysql_ResultObject_traverse(
 	_mysql_ResultObject *self,
 	visitproc visit,
@@ -451,10 +437,9 @@
 		if (!(r = visit(self->converter, arg))) return r;
 	}
 	if (self->conn)
-		return visit(self->conn, arg);
+		return visit((PyObject *)self->conn, arg);
 	return 0;
 }
-#endif
 
 static int _mysql_ResultObject_clear(
 	_mysql_ResultObject *self)
@@ -515,7 +500,7 @@
 		return -1;
 
 #define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\
-        if(t){d=PyString_AsString(t);Py_DECREF(t);}\
+        if(t){d=PyBytes_AsString(t);Py_DECREF(t);}\
         PyErr_Clear();}
 
 	if (ssl) {
@@ -663,7 +648,6 @@
 	return (PyObject *) c;
 }
 
-#if PY_VERSION_HEX >= 0x02020000
 static int _mysql_ConnectionObject_traverse(
 	_mysql_ConnectionObject *self,
 	visitproc visit,
@@ -673,7 +657,7 @@
 		return visit(self->converter, arg);
 	return 0;
 }
-#endif
+
 
 static int _mysql_ConnectionObject_clear(
 	_mysql_ConnectionObject *self)
@@ -862,7 +846,7 @@
 #endif
 	Py_END_ALLOW_THREADS
 	if (err > 0) return _mysql_Exception(self);
-	return PyInt_FromLong(err);
+	return PyLong_FromLong(err);
 }		
 
 #if MYSQL_VERSION_ID >= 40100
@@ -885,7 +869,7 @@
 	err = mysql_set_server_option(&(self->connection), flags);
 	Py_END_ALLOW_THREADS
 	if (err) return _mysql_Exception(self);
-	return PyInt_FromLong(err);
+	return PyLong_FromLong(err);
 }		
 
 static char _mysql_ConnectionObject_sqlstate__doc__[] =
@@ -906,7 +890,7 @@
 	PyObject *args)
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
-	return PyString_FromString(mysql_sqlstate(&(self->connection)));
+	return PyUnicode_FromString(mysql_sqlstate(&(self->connection)));
 }		
 
 static char _mysql_ConnectionObject_warning_count__doc__[] =
@@ -921,7 +905,7 @@
 	PyObject *args)
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
-	return PyInt_FromLong(mysql_warning_count(&(self->connection)));
+	return PyLong_FromLong(mysql_warning_count(&(self->connection)));
 }		
 
 #endif
@@ -939,7 +923,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
-	return PyInt_FromLong((long)mysql_errno(&(self->connection)));
+	return PyLong_FromLong((long)mysql_errno(&(self->connection)));
 }
 
 static char _mysql_ConnectionObject_error__doc__[] =
@@ -955,7 +939,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
-	return PyString_FromString(mysql_error(&(self->connection)));
+	return PyUnicode_FromString(mysql_error(&(self->connection)));
 }
 
 static char _mysql_escape_string__doc__[] =
@@ -966,18 +950,14 @@
 probably better off using connection.escape(o) instead, since\n\
 it will escape entire sequences as well as strings.";
 
-static PyObject *
-_mysql_escape_string(
-	_mysql_ConnectionObject *self,
-	PyObject *args)
+static PyObject *_mysql_ConnectionObject_escape_string(	_mysql_ConnectionObject *self,	PyObject *args)
 {
 	PyObject *str;
 	char *in, *out;
 	int len, size;
 	if (!PyArg_ParseTuple(args, "s#:escape_string", &in, &size)) return NULL;
-	str = PyString_FromStringAndSize((char *) NULL, size*2+1);
-	if (!str) return PyErr_NoMemory();
-	out = PyString_AS_STRING(str);
+	out = PyMem_New(char, size*2+1);
+	if (!out) return PyErr_NoMemory();
 #if MYSQL_VERSION_ID < 32321
 	len = mysql_escape_string(out, in, size);
 #else
@@ -987,10 +967,16 @@
 	else
 		len = mysql_escape_string(out, in, size);
 #endif
-	if (_PyString_Resize(&str, len) < 0) return NULL;
+	str = PyUnicode_FromString(out);
+	PyMem_Del(out);
 	return (str);
 }
 
+static PyObject *_mysql_escape_string( PyObject *self, PyObject *args)
+{
+	return _mysql_ConnectionObject_escape_string(NULL, args);
+}
+
 static char _mysql_string_literal__doc__[] =
 "string_literal(obj) -- converts object obj into a SQL string literal.\n\
 This means, any special SQL characters are escaped, and it is enclosed\n\
@@ -1001,43 +987,50 @@
 Use connection.string_literal(obj), if you use it at all.\n\
 _mysql.string_literal(obj) cannot handle character sets.";
 
-static PyObject *
-_mysql_string_literal(
-	_mysql_ConnectionObject *self,
-	PyObject *args)
+static PyObject *_mysql_ConnectionObject_string_literal(_mysql_ConnectionObject *self, PyObject *args)
 {
-	PyObject *str, *s, *o, *d;
+	PyObject *str, *s, *s2, *o, *d;
 	char *in, *out;
 	int len, size;
 	if (!PyArg_ParseTuple(args, "O|O:string_literal", &o, &d)) return NULL;
 	s = PyObject_Str(o);
 	if (!s) return NULL;
-	in = PyString_AsString(s);
-	size = PyString_GET_SIZE(s);
-	str = PyString_FromStringAndSize((char *) NULL, size*2+3);
-	if (!str) return PyErr_NoMemory();
-	out = PyString_AS_STRING(str);
+	s2 = PyUnicode_AsUTF8String(s);
+	if (!s2) return NULL;
+	in = PyBytes_AsString(s2);
+	if (!in) return NULL;
+	size = PyBytes_GET_SIZE(s2);
+	out = PyMem_New(char, size*2+3);
+	if (!out) return PyErr_NoMemory();
 #if MYSQL_VERSION_ID < 32321
 	len = mysql_escape_string(out+1, in, size);
 #else
 	check_server_init(NULL);
-	if (self && self->open)
+	if (self && self->open )
+	{
 		len = mysql_real_escape_string(&(self->connection), out+1, in, size);
-	else
+	} else
+	{
 		len = mysql_escape_string(out+1, in, size);
+	};
 #endif
 	*out = *(out+len+1) = '\'';
-	if (_PyString_Resize(&str, len+2) < 0) return NULL;
+	*(out+len+2) = '\0';
+	str = PyUnicode_FromString(out);
+	PyMem_Del(out);
+	Py_DECREF(s2);
 	Py_DECREF(s);
 	return (str);
 }
 
+static PyObject *_mysql_string_literal(PyObject *self, PyObject *args)
+{
+	return _mysql_ConnectionObject_string_literal(NULL, args);
+}
+
 static PyObject *_mysql_NULL;
 
-static PyObject *
-_escape_item(
-	PyObject *item,
-	PyObject *d)
+static PyObject *_escape_item( PyObject *item, PyObject *d)
 {
 	PyObject *quoted=NULL, *itemtype, *itemconv;
 	if (!(itemtype = PyObject_Type(item)))
@@ -1047,11 +1040,11 @@
 	if (!itemconv) {
 		PyErr_Clear();
 		itemconv = PyObject_GetItem(d,
-				 (PyObject *) &PyString_Type);
+			(PyObject *) &PyUnicode_Type);
 	}
 	if (!itemconv) {
 		PyErr_SetString(PyExc_TypeError,
-				"no default type converter defined");
+			"no default type converter defined");
 		goto error;
 	}
 	quoted = PyObject_CallFunction(itemconv, "OO", item, d);
@@ -1064,32 +1057,33 @@
 "escape(obj, dict) -- escape any special characters in object obj\n\
 using mapping dict to provide quoting functions for each type.\n\
 Returns a SQL literal string.";
-static PyObject *
-_mysql_escape(
-	PyObject *self,
-	PyObject *args)
+static PyObject *_mysql_ConnectionObject_escape( _mysql_ConnectionObject *self, PyObject *args)
 {
 	PyObject *o=NULL, *d=NULL;
 	if (!PyArg_ParseTuple(args, "O|O:escape", &o, &d))
 		return NULL;
 	if (d) {
 		if (!PyMapping_Check(d)) {
-			PyErr_SetString(PyExc_TypeError,
-					"argument 2 must be a mapping");
+			PyErr_SetString(PyExc_TypeError, "argument 2 must be a mapping");
 			return NULL;
 		}
 		return _escape_item(o, d);
-	} else {
-		if (!self) {
-			PyErr_SetString(PyExc_TypeError,
-					"argument 2 must be a mapping");
+	} else
+	{
+		if (!self)
+		{
+			PyErr_SetString(PyExc_TypeError, "argument 2 must be a mapping");
 			return NULL;
 		}
-		return _escape_item(o,
-			   ((_mysql_ConnectionObject *) self)->converter);
+		return _escape_item(o, self->converter);
 	}
 }
 
+static PyObject *_mysql_escape(	PyObject *self,	PyObject *args)
+{
+	return _mysql_ConnectionObject_escape(NULL, args);
+}
+
 static char _mysql_escape_sequence__doc__[] =
 "escape_sequence(seq, dict) -- escape any special characters in sequence\n\
 seq using mapping dict to provide quoting functions for each type.\n\
@@ -1160,20 +1154,28 @@
 the Cursor.description attribute.\n\
 ";
 
-static PyObject *
-_mysql_ResultObject_describe(
-	_mysql_ResultObject *self,
-	PyObject *args)
+static PyObject * _mysql_ResultObject_describe ( _mysql_ResultObject *self, PyObject *args)
 {
-	PyObject *d;
+	PyObject *d = NULL;
 	MYSQL_FIELD *fields;
 	unsigned int i, n;
-	if (!PyArg_ParseTuple(args, "")) return NULL;
+	
+	if ( !PyArg_ParseTuple(args, ""))
+	{
+		return NULL;
+	};
+
 	check_result_connection(self);
+
 	n = mysql_num_fields(self->result);
 	fields = mysql_fetch_fields(self->result);
-	if (!(d = PyTuple_New(n))) return NULL;
-	for (i=0; i<n; i++) {
+	d = PyTuple_New(n);
+	if ( d == NULL )
+	{
+		return NULL;
+	};
+	for (i = 0; i < n; i++)
+	{
 		PyObject *t;
 		t = Py_BuildValue("(siiiiii)",
 				  fields[i].name,
@@ -1183,13 +1185,16 @@
 				  (long) fields[i].length,
 				  (long) fields[i].decimals,
 				  (long) !(IS_NOT_NULL(fields[i].flags)));
-		if (!t) goto error;
+		if (t == NULL)
+		{
+			Py_XDECREF(d);
+			d = NULL;
+			break;
+		};
 		PyTuple_SET_ITEM(d, i, t);
-	}
+	};
+	
 	return d;
-  error:
-	Py_XDECREF(d);
-	return NULL;
 }
 	
 static char _mysql_ResultObject_field_flags__doc__[] =
@@ -1211,7 +1216,7 @@
 	if (!(d = PyTuple_New(n))) return NULL;
 	for (i=0; i<n; i++) {
 		PyObject *f;
-		if (!(f = PyInt_FromLong((long)fields[i].flags))) goto error;
+		if (!(f = PyLong_FromLong((long)fields[i].flags))) goto error;
 		PyTuple_SET_ITEM(d, i, f);
 	}
 	return d;
@@ -1221,27 +1226,44 @@
 }
 
 static PyObject *
-_mysql_field_to_python(
-	PyObject *converter,
-	char *rowitem,
-	unsigned long length)
+_mysql_field_to_python(PyObject *converter, char *rowitem, unsigned long length, const char *charset)
 {
 	PyObject *v;
-	if (rowitem) {
-		if (converter != Py_None)
-			v = PyObject_CallFunction(converter,
-						  "s#",
-						  rowitem,
-						  (int)length);
-		else
-			v = PyString_FromStringAndSize(rowitem,
-						       (int)length);
-		if (!v)
-			return NULL;
-	} else {
+	if (rowitem)
+	{
+		if (charset)
+		{
+			PyObject *rowitem_unicode = PyUnicode_Decode(rowitem, (int)length, charset, "replace");
+			if (rowitem_unicode == NULL)
+			{
+				return NULL;
+			} else
+			{
+				if (converter != Py_None)
+		        {
+					v = PyObject_CallFunction(converter, "O", rowitem_unicode);
+			                Py_XDECREF(rowitem_unicode);
+		        } else
+				{
+					v = rowitem_unicode;
+				};
+			};
+		} else
+		{
+			if (converter != Py_None)
+		    {
+				v = PyObject_CallFunction(converter, "s#", rowitem, (int)length);
+		    } else
+		    {
+				v = PyUnicode_FromStringAndSize(rowitem, (int)length);
+			    if (!v) return NULL;
+			};
+		};
+	} else
+	{
 		Py_INCREF(Py_None);
 		v = Py_None;
-	}
+	};
 	return v;
 }
 
@@ -1253,14 +1275,22 @@
 	unsigned int n, i;
 	unsigned long *length;
 	PyObject *r, *c;
+	const char *charset;
 
 	n = mysql_num_fields(self->result);
 	if (!(r = PyTuple_New(n))) return NULL;
 	length = mysql_fetch_lengths(self->result);
+
+#if MYSQL_VERSION_ID >= 32321
+	charset = mysql_character_set_name(&(self->conn->connection));
+#else
+	charset = "latin1";
+#endif
+
 	for (i=0; i<n; i++) {
 		PyObject *v;
 		c = PyTuple_GET_ITEM(self->converter, i);
-		v = _mysql_field_to_python(c, row[i], length[i]);
+		v = _mysql_field_to_python(c, row[i], length[i], charset);
 		if (!v) goto error;
 		PyTuple_SET_ITEM(r, i, v);
 	}
@@ -1278,16 +1308,24 @@
 	unsigned int n, i;
 	unsigned long *length;
 	PyObject *r, *c;
-        MYSQL_FIELD *fields;
+    MYSQL_FIELD *fields;
+	const char *charset;
 
 	n = mysql_num_fields(self->result);
 	if (!(r = PyDict_New())) return NULL;
 	length = mysql_fetch_lengths(self->result);
         fields = mysql_fetch_fields(self->result);
+
+#if MYSQL_VERSION_ID >= 32321
+	charset = mysql_character_set_name(&(self->conn->connection));
+#else
+	charset = "latin1";
+#endif
+
 	for (i=0; i<n; i++) {
 		PyObject *v;
 		c = PyTuple_GET_ITEM(self->converter, i);
-		v = _mysql_field_to_python(c, row[i], length[i]);
+		v = _mysql_field_to_python(c, row[i], length[i], charset);
 		if (!v) goto error;
 		if (!PyMapping_HasKeyString(r, fields[i].name)) {
 			PyMapping_SetItemString(r, fields[i].name, v);
@@ -1317,16 +1355,24 @@
 	unsigned int n, i;
 	unsigned long *length;
 	PyObject *r, *c;
-        MYSQL_FIELD *fields;
+    MYSQL_FIELD *fields;
+	const char *charset;
 
 	n = mysql_num_fields(self->result);
 	if (!(r = PyDict_New())) return NULL;
 	length = mysql_fetch_lengths(self->result);
         fields = mysql_fetch_fields(self->result);
+
+#if MYSQL_VERSION_ID >= 32321
+	charset = mysql_character_set_name(&(self->conn->connection));
+#else
+	charset = "latin1";
+#endif
+
 	for (i=0; i<n; i++) {
 		PyObject *v;
 		c = PyTuple_GET_ITEM(self->converter, i);
-		v = _mysql_field_to_python(c, row[i], length[i]);
+		v = _mysql_field_to_python(c, row[i], length[i], charset);
 		if (!v) goto error;
 		{
 			int len=0;
@@ -1354,8 +1400,8 @@
 _mysql__fetch_row(
 	_mysql_ResultObject *self,
 	PyObject **r,
-	int skiprows,
-	int maxrows,
+	unsigned int skiprows,
+	unsigned int maxrows,
 	_PYFUNC *convert_row)
 {
 	unsigned int i;
@@ -1516,7 +1562,7 @@
 #else
 	s = "latin1";
 #endif
-	return PyString_FromString(s);
+	return PyUnicode_FromString(s);
 }
 
 #if MYSQL_VERSION_ID >= 50007
@@ -1578,15 +1624,15 @@
 	mysql_get_character_set_info(&(self->connection), &cs);
 	if (!(result = PyDict_New())) return NULL;
 	if (cs.csname)
-		PyDict_SetItemString(result, "name", PyString_FromString(cs.csname));
+		PyDict_SetItemString(result, "name", PyUnicode_FromString(cs.csname));
 	if (cs.name)
-		PyDict_SetItemString(result, "collation", PyString_FromString(cs.name));
+		PyDict_SetItemString(result, "collation", PyUnicode_FromString(cs.name));
 	if (cs.comment)
-		PyDict_SetItemString(result, "comment", PyString_FromString(cs.comment));
+		PyDict_SetItemString(result, "comment", PyUnicode_FromString(cs.comment));
 	if (cs.dir)
-		PyDict_SetItemString(result, "dir", PyString_FromString(cs.dir));
-	PyDict_SetItemString(result, "mbminlen", PyInt_FromLong(cs.mbminlen));
-	PyDict_SetItemString(result, "mbmaxlen", PyInt_FromLong(cs.mbmaxlen));
+		PyDict_SetItemString(result, "dir", PyUnicode_FromString(cs.dir));
+	PyDict_SetItemString(result, "mbminlen", PyLong_FromLong(cs.mbminlen));
+	PyDict_SetItemString(result, "mbmaxlen", PyLong_FromLong(cs.mbmaxlen));
 	return result;
 }
 #endif
@@ -1596,12 +1642,12 @@
 the client library version.";
 static PyObject *
 _mysql_get_client_info(
-	PyObject *self,
-	PyObject *args)
+					   PyObject *self,
+					   PyObject *args)
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_server_init(NULL);
-	return PyString_FromString(mysql_get_client_info());
+	return PyUnicode_FromString(mysql_get_client_info());
 }
 
 static char _mysql_ConnectionObject_get_host_info__doc__[] =
@@ -1616,7 +1662,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
-	return PyString_FromString(mysql_get_host_info(&(self->connection)));
+	return PyUnicode_FromString(mysql_get_host_info(&(self->connection)));
 }
 
 static char _mysql_ConnectionObject_get_proto_info__doc__[] =
@@ -1631,7 +1677,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
-	return PyInt_FromLong((long)mysql_get_proto_info(&(self->connection)));
+	return PyLong_FromLong((long)mysql_get_proto_info(&(self->connection)));
 }
 
 static char _mysql_ConnectionObject_get_server_info__doc__[] =
@@ -1646,7 +1692,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
-	return PyString_FromString(mysql_get_server_info(&(self->connection)));
+	return PyUnicode_FromString(mysql_get_server_info(&(self->connection)));
 }
 
 static char _mysql_ConnectionObject_info__doc__[] =
@@ -1664,7 +1710,7 @@
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
 	s = mysql_info(&(self->connection));
-	if (s) return PyString_FromString(s);
+	if (s) return PyUnicode_FromString(s);
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1739,9 +1785,9 @@
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_connection(self);
 #if MYSQL_VERSION_ID < 32224
-	return PyInt_FromLong((long)mysql_num_fields(&(self->connection)));
+	return PyNumber_FromLong((long)mysql_num_fields(&(self->connection)));
 #else
-	return PyInt_FromLong((long)mysql_field_count(&(self->connection)));
+	return PyLong_FromLong((long)mysql_field_count(&(self->connection)));
 #endif
 }	
 
@@ -1755,7 +1801,7 @@
 {
 	if (!PyArg_ParseTuple(args, "")) return NULL;
 	check_result_connection(self);
-	return PyInt_FromLong((long)mysql_num_fields(self->result));
+	return PyLong_FromLong((long)mysql_num_fields(self->result));
 }	
 
 static char _mysql_ResultObject_num_rows__doc__[] =
@@ -1907,7 +1953,7 @@
 	s = mysql_stat(&(self->connection));
 	Py_END_ALLOW_THREADS
 	if (!s) return _mysql_Exception(self);
-	return PyString_FromString(s);
+	return PyUnicode_FromString(s);
 }
 
 static char _mysql_ConnectionObject_store_result__doc__[] =
@@ -1968,7 +2014,7 @@
 	Py_BEGIN_ALLOW_THREADS
 	pid = mysql_thread_id(&(self->connection));
 	Py_END_ALLOW_THREADS
-	return PyInt_FromLong((long)pid);
+	return PyLong_FromLong((long)pid);
 }
 
 static char _mysql_ConnectionObject_use_result__doc__[] =
@@ -2033,7 +2079,7 @@
 	else
 		sprintf(buf, "<_mysql.connection closed at %lx>",
 			(long)self);
-	return PyString_FromString(buf);
+	return PyUnicode_FromString(buf);
 }
 
 static char _mysql_ResultObject_data_seek__doc__[] =
@@ -2089,7 +2135,7 @@
 		return NULL;
 	}
 	r = mysql_row_tell(self->result);
-	return PyInt_FromLong(r-self->result->data->data);
+	return PyLong_FromLong(r-self->result->data->data);
 }
 
 static void
@@ -2109,7 +2155,7 @@
 	char buf[300];
 	sprintf(buf, "<_mysql.result object at %lx>",
 		(long)self);
-	return PyString_FromString(buf);
+	return PyUnicode_FromString(buf);
 }
 
 static PyMethodDef _mysql_ConnectionObject_methods[] = {
@@ -2207,13 +2253,13 @@
 	},
 	{
 		"escape",
-		(PyCFunction)_mysql_escape,
+		(PyCFunction)_mysql_ConnectionObject_escape,
 		METH_VARARGS,
 		_mysql_escape__doc__
 	},
 	{
 		"escape_string",
-		(PyCFunction)_mysql_escape_string,
+		(PyCFunction)_mysql_ConnectionObject_escape_string,
 		METH_VARARGS,
 		_mysql_escape_string__doc__
 	},
@@ -2309,7 +2355,7 @@
 	},
 	{
 		"string_literal",
-		(PyCFunction)_mysql_string_literal,
+		(PyCFunction)_mysql_ConnectionObject_string_literal,
 		METH_VARARGS,
 		_mysql_string_literal__doc__},
 	{
@@ -2332,7 +2378,7 @@
 		"open",
 		T_INT,
 		offsetof(_mysql_ConnectionObject,open),
-		RO,
+		READONLY,
 		"True if connection is open"
 		),
 	MyMember(
@@ -2346,20 +2392,20 @@
 		"server_capabilities",
 		T_UINT,
 		offsetof(_mysql_ConnectionObject,connection.server_capabilities),
-		RO,
+		READONLY,
 		"Capabilites of server; consult MySQLdb.constants.CLIENT"
 		),
 	MyMember(
 		 "port",
 		 T_UINT,
 		 offsetof(_mysql_ConnectionObject,connection.port),
-		 RO,
+		 READONLY,
 		 "TCP/IP port of the server connection"
 		 ),
 	MyMember(
 		 "client_flag",
 		 T_UINT,
-		 RO,
+		 READONLY,
 		 offsetof(_mysql_ConnectionObject,connection.client_flag),
 		 "Client flags; refer to MySQLdb.constants.CLIENT"
 		 ),
@@ -2423,127 +2469,22 @@
 		"converter",
 		T_OBJECT,
 		offsetof(_mysql_ResultObject,converter),
-		RO,
+		READONLY,
 		"Type conversion mapping"
 		),
 	{NULL} /* Sentinel */
 };
-                                                                        
-static PyObject *
-_mysql_ConnectionObject_getattr(
-	_mysql_ConnectionObject *self,
-	char *name)
-{
-	PyObject *res;
-
-	res = Py_FindMethod(_mysql_ConnectionObject_methods, (PyObject *)self, name);
-	if (res != NULL)
-		return res;
-	PyErr_Clear();
-	if (strcmp(name, "closed") == 0)
-		return PyInt_FromLong((long)!(self->open));
-#if PY_VERSION_HEX < 0x02020000
-	return PyMember_Get((char *)self, _mysql_ConnectionObject_memberlist, name);
-#else
-	{
-		MyMemberlist(*l);
-		for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) {
-			if (strcmp(l->name, name) == 0)
-				return PyMember_GetOne((char *)self, l);
-		}
-		PyErr_SetString(PyExc_AttributeError, name);
-		return NULL;
-	}
-#endif
-}
-
-static PyObject *
-_mysql_ResultObject_getattr(
-	_mysql_ResultObject *self,
-	char *name)
-{
-	PyObject *res;
-
-	res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name);
-	if (res != NULL)
-		return res;
-	PyErr_Clear();
-#if PY_VERSION_HEX < 0x02020000
-	return PyMember_Get((char *)self, _mysql_ResultObject_memberlist, name);
-#else
-	{
-		MyMemberlist(*l);
-		for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) {
-			if (strcmp(l->name, name) == 0)
-				return PyMember_GetOne((char *)self, l);
-		}
-		PyErr_SetString(PyExc_AttributeError, name);
-		return NULL;
-	}
-#endif
-}
-
-static int
-_mysql_ConnectionObject_setattr(
-	_mysql_ConnectionObject *self,
-	char *name,
-	PyObject *v)
-{
-	if (v == NULL) {
-		PyErr_SetString(PyExc_AttributeError,
-				"can't delete connection attributes");
-		return -1;
-	}
-#if PY_VERSION_HEX < 0x02020000
-	return PyMember_Set((char *)self, _mysql_ConnectionObject_memberlist, name, v);
-#else
-        {
-		MyMemberlist(*l);
-		for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++)
-			if (strcmp(l->name, name) == 0)
-				return PyMember_SetOne((char *)self, l, v);
-	}
-        PyErr_SetString(PyExc_AttributeError, name);
-        return -1;
-#endif
-}
-
-static int
-_mysql_ResultObject_setattr(
-	_mysql_ResultObject *self,
-	char *name,
-	PyObject *v)
-{
-	if (v == NULL) {
-		PyErr_SetString(PyExc_AttributeError,
-				"can't delete connection attributes");
-		return -1;
-	}
-#if PY_VERSION_HEX < 0x02020000
-	return PyMember_Set((char *)self, _mysql_ResultObject_memberlist, name, v);
-#else
-        {
-		MyMemberlist(*l);
-		for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++)
-			if (strcmp(l->name, name) == 0)
-				return PyMember_SetOne((char *)self, l, v);
-	}
-        PyErr_SetString(PyExc_AttributeError, name);
-        return -1;
-#endif
-}
 
 PyTypeObject _mysql_ConnectionObject_Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+	PyVarObject_HEAD_INIT(NULL, 0)
 	"_mysql.connection", /* (char *)tp_name For printing */
 	sizeof(_mysql_ConnectionObject),
 	0,
 	(destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */
-	0, /*tp_print*/
-	(getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */
-	(setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */
-	0, /*tp_compare*/
+	0, /* tp_print*/
+	0, /* tp_getattr */
+	0, /* tp_setattr */
+	0, /* tp_compare*/
 	(reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */
 	
 	/* Method suites for standard classes */
@@ -2564,33 +2505,20 @@
 	0, /* (PyBufferProcs *) tp_as_buffer */
 	
 	/* Flags to define presence of optional/expanded features */
-#if PY_VERSION_HEX < 0x02020000
-	Py_TPFLAGS_DEFAULT, /* (long) tp_flags */
-#else
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
-#endif
 	_mysql_connect__doc__, /* (char *) tp_doc Documentation string */
-#if PY_VERSION_HEX >= 0x02000000	
 	/* Assigned meaning in release 2.0 */
-#if PY_VERSION_HEX >= 0x02020000
 	/* call function for all accessible objects */
 	(traverseproc) _mysql_ConnectionObject_traverse, /* tp_traverse */
 	
 	/* delete references to contained objects */
 	(inquiry) _mysql_ConnectionObject_clear, /* tp_clear */
-#else
-	/* not supporting pre-2.2 GC */
-	0,
-	0,
-#endif
-#if PY_VERSION_HEX >= 0x02010000	
 	/* Assigned meaning in release 2.1 */
 	/* rich comparisons */
 	0, /* (richcmpfunc) tp_richcompare */
 	
 	/* weak reference enabler */
 	0, /* (long) tp_weaklistoffset */
-#if PY_VERSION_HEX >= 0x02020000
 	/* Added in release 2.2 */
 	/* Iterators */
 	0, /* (getiterfunc) tp_iter */
@@ -2612,22 +2540,18 @@
 	0, /* (PyObject *) tp_bases */
 	0, /* (PyObject *) tp_mro method resolution order */
 	0, /* (PyObject *) tp_defined */
-#endif /* python 2.2 */
-#endif /* python 2.1 */
-#endif /* python 2.0 */
 } ;
 
 PyTypeObject _mysql_ResultObject_Type = {
-	PyObject_HEAD_INIT(NULL)
-	0,
+	 PyVarObject_HEAD_INIT(NULL, 0)
 	"_mysql.result",
 	sizeof(_mysql_ResultObject),
 	0,
 	(destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */
-	0, /*tp_print*/
-	(getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */
-	(setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */
-	0, /*tp_compare*/
+	0, /* tp_print */
+	0, /* tp_getattr */
+	0, /* tp_setattr */
+	0, /* tp_compare */
 	(reprfunc)_mysql_ResultObject_repr, /* tp_repr */
 	
 	/* Method suites for standard classes */
@@ -2648,34 +2572,20 @@
 	0, /* (PyBufferProcs *) tp_as_buffer */
 	
 	/* Flags to define presence of optional/expanded features */
-#if PY_VERSION_HEX < 0x02020000
-	Py_TPFLAGS_DEFAULT, /* (long) tp_flags */
-#else
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
-#endif
-	
 	_mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */
-#if PY_VERSION_HEX >= 0x02000000	
 	/* Assigned meaning in release 2.0 */
-#if PY_VERSION_HEX >= 0x02020000
 	/* call function for all accessible objects */
 	(traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */
 	
 	/* delete references to contained objects */
 	(inquiry) _mysql_ResultObject_clear, /* tp_clear */
-#else
-	/* not supporting pre-2.2 GC */
-	0,
-	0,
-#endif
-#if PY_VERSION_HEX >= 0x02010000	
 	/* Assigned meaning in release 2.1 */
 	/* rich comparisons */
 	0, /* (richcmpfunc) tp_richcompare */
 	
 	/* weak reference enabler */
 	0, /* (long) tp_weaklistoffset */
-#if PY_VERSION_HEX >= 0x02020000
 	/* Added in release 2.2 */
 	/* Iterators */
 	0, /* (getiterfunc) tp_iter */
@@ -2697,13 +2607,9 @@
 	0, /* (PyObject *) tp_bases */
 	0, /* (PyObject *) tp_mro method resolution order */
 	0, /* (PyObject *) tp_defined */
-#endif /* python 2.2 */
-#endif /* python 2.1 */
-#endif /* python 2.0 */
 };
 
-static PyMethodDef
-_mysql_methods[] = {
+static PyMethodDef _mysql_methods[] = {
 	{ 
 		"connect",
 		(PyCFunction)_mysql_connect,
@@ -2775,16 +2681,11 @@
 	{NULL, NULL} /* sentinel */
 };
 
-static PyObject *
-_mysql_NewException(
-	PyObject *dict,
-	PyObject *edict,
-	char *name)
+static PyObject *_mysql_NewException( PyObject *dict, PyObject *edict, char *name)
 {
 	PyObject *e;
 
-	if (!(e = PyDict_GetItemString(edict, name)))
-		return NULL;
+	if (!(e = PyDict_GetItemString(edict, name))) return NULL;
 	if (PyDict_SetItemString(dict, name, e)) return NULL;
 	return e;
 }
@@ -2806,85 +2707,111 @@
 (as of 3.23) are NOT implemented.\n\
 ";
 
-DL_EXPORT(void)
-init_mysql(void)
+/* module definition */
+static struct PyModuleDef mysqlModule = {
+	PyModuleDef_HEAD_INIT,
+	"_mysql",	/* name of module */
+	_mysql___doc__,		/* module documentation */
+	-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
+	_mysql_methods,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+int CheckError()
+{
+	if ( PyErr_Occurred() )
+	{
+		PyErr_Print();
+		PyErr_SetString(PyExc_ImportError, "_mysql: init failed");
+		PyErr_Print();
+		return -1;
+	};
+	return 0;
+};
+
+PyMODINIT_FUNC PyInit__mysql(void)
 {
 	PyObject *dict, *module, *emod, *edict;
-	module = Py_InitModule4("_mysql", _mysql_methods, _mysql___doc__,
-				(PyObject *)NULL, PYTHON_API_VERSION);
-	if (!module) return; /* this really should never happen */
-	_mysql_ConnectionObject_Type.ob_type = &PyType_Type;
-	_mysql_ResultObject_Type.ob_type = &PyType_Type;
-#if PY_VERSION_HEX >= 0x02020000
+
+	_mysql_ConnectionObject_Type.ob_base.ob_base.ob_type = &PyType_Type;
+	_mysql_ResultObject_Type.ob_base.ob_base.ob_type = &PyType_Type;
 	_mysql_ConnectionObject_Type.tp_alloc = PyType_GenericAlloc;
 	_mysql_ConnectionObject_Type.tp_new = PyType_GenericNew;
-	_mysql_ConnectionObject_Type.tp_free = _PyObject_GC_Del; 
+	_mysql_ConnectionObject_Type.tp_free = PyObject_GC_Del; 
 	_mysql_ResultObject_Type.tp_alloc = PyType_GenericAlloc;
 	_mysql_ResultObject_Type.tp_new = PyType_GenericNew;
-	_mysql_ResultObject_Type.tp_free = _PyObject_GC_Del;
-#endif
+	_mysql_ResultObject_Type.tp_free = PyObject_GC_Del;
 
-	if (!(dict = PyModule_GetDict(module))) goto error;
-	if (PyDict_SetItemString(dict, "version_info",
-			       PyRun_String(QUOTE(version_info), Py_eval_input,
-				       dict, dict)))
-		goto error;
-	if (PyDict_SetItemString(dict, "__version__",
-			       PyString_FromString(QUOTE(__version__))))
-		goto error;
-	if (PyDict_SetItemString(dict, "connection",
-			       (PyObject *)&_mysql_ConnectionObject_Type))
-		goto error;
-	Py_INCREF(&_mysql_ConnectionObject_Type);
-	if (PyDict_SetItemString(dict, "result",
-			       (PyObject *)&_mysql_ResultObject_Type))
-		goto error;	
-	Py_INCREF(&_mysql_ResultObject_Type);
-	if (!(emod = PyImport_ImportModule("_mysql_exceptions")))
-		goto error;
-	if (!(edict = PyModule_GetDict(emod))) goto error;
-	if (!(_mysql_MySQLError =
-	      _mysql_NewException(dict, edict, "MySQLError")))
-		goto error;
-	if (!(_mysql_Warning =
-	      _mysql_NewException(dict, edict, "Warning")))
-		goto error;
-	if (!(_mysql_Error =
-	      _mysql_NewException(dict, edict, "Error")))
-		goto error;
-	if (!(_mysql_InterfaceError =
-	      _mysql_NewException(dict, edict, "InterfaceError")))
-		goto error;
-	if (!(_mysql_DatabaseError =
-	      _mysql_NewException(dict, edict, "DatabaseError")))
-		goto error;
-	if (!(_mysql_DataError =
-	      _mysql_NewException(dict, edict, "DataError")))
-		goto error;
-	if (!(_mysql_OperationalError =
-	      _mysql_NewException(dict, edict, "OperationalError")))
-		goto error;
-	if (!(_mysql_IntegrityError =
-	      _mysql_NewException(dict, edict, "IntegrityError")))
-		goto error;
-	if (!(_mysql_InternalError =
-	      _mysql_NewException(dict, edict, "InternalError")))
-		goto error;
-	if (!(_mysql_ProgrammingError =
-	      _mysql_NewException(dict, edict, "ProgrammingError")))
-		goto error;
-	if (!(_mysql_NotSupportedError =
-	      _mysql_NewException(dict, edict, "NotSupportedError")))
-		goto error;
-	Py_DECREF(emod);
-	if (!(_mysql_NULL = PyString_FromString("NULL")))
-		goto error;
-	if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error;
-  error:
-	if (PyErr_Occurred())
-		PyErr_SetString(PyExc_ImportError,
-				"_mysql: init failed");
-	return;
+	if (PyType_Ready(&_mysql_ConnectionObject_Type) < 0) return NULL;
+	if (PyType_Ready(&_mysql_ResultObject_Type) < 0) return NULL;
+
+	module = PyModule_Create2(&mysqlModule,PYTHON_API_VERSION);
+	
+	if (module == NULL)
+	{
+		return NULL;
+	};
+	
+	dict = PyModule_GetDict(module);
+	if (PyDict_SetItemString(dict, "version_info", PyRun_String(QUOTE(version_info), Py_eval_input, dict, dict)) == -1)
+	{
+	} else if (PyDict_SetItemString(dict, "__version__",
+			       PyUnicode_FromString(QUOTE(__version__))) == -1 )
+	{
+	} else if (PyDict_SetItemString(dict, "connection",
+			       (PyObject *)&_mysql_ConnectionObject_Type) == -1 )
+	{
+
+	} else
+	{
+		Py_INCREF(&_mysql_ConnectionObject_Type);
+		if ( PyDict_SetItemString(dict, "result",(PyObject *)&_mysql_ResultObject_Type) == -1 )
+		{
+
+		} else
+		{
+			Py_INCREF(&_mysql_ResultObject_Type);
+			emod = PyImport_ImportModule("_mysql_exceptions");
+			if (emod != NULL )
+			{
+				edict = PyModule_GetDict(emod);
+				_mysql_MySQLError = _mysql_NewException(dict, edict, "MySQLError");
+				if (_mysql_MySQLError != NULL)
+				{
+					_mysql_Warning = _mysql_NewException(dict, edict, "Warning");
+					_mysql_Error = _mysql_NewException(dict, edict, "Error");
+					_mysql_InterfaceError = _mysql_NewException(dict, edict, "InterfaceError");
+					_mysql_DatabaseError = _mysql_NewException(dict, edict, "DatabaseError");
+					_mysql_DataError = _mysql_NewException(dict, edict, "DataError");
+					_mysql_OperationalError = _mysql_NewException(dict, edict, "OperationalError");
+					_mysql_IntegrityError = _mysql_NewException(dict, edict, "IntegrityError");
+					_mysql_InternalError = _mysql_NewException(dict, edict, "InternalError");
+					_mysql_ProgrammingError = _mysql_NewException(dict, edict, "ProgrammingError");
+					_mysql_NotSupportedError = _mysql_NewException(dict, edict, "NotSupportedError");
+					if ( _mysql_Warning != NULL && _mysql_Error != NULL && _mysql_InterfaceError != NULL &&
+						 _mysql_DatabaseError != NULL && _mysql_DataError != NULL && _mysql_OperationalError != NULL &&
+						 _mysql_IntegrityError != NULL && _mysql_InternalError != NULL &&
+						 _mysql_ProgrammingError != NULL && _mysql_NotSupportedError != NULL
+					   )
+					{
+						Py_DECREF(emod);
+					    _mysql_NULL = PyUnicode_FromString("NULL");
+					    PyDict_SetItemString(dict, "NULL", _mysql_NULL);
+					};
+				};
+			};
+		};
+	};
+
+	if ( CheckError() == -1 )
+	{
+		return NULL;
+	};
+
+	return module;
 }
 
 
diff -ru MySQL-python-1.2.3/MySQLdb/connections.py MySQL-Python-1.2.3-python3/MySQLdb/connections.py
--- MySQL-python-1.2.3/MySQLdb/connections.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/MySQLdb/connections.py	2011-11-25 16:44:27.000000000 +0100
@@ -6,7 +6,7 @@
 override Connection.default_cursor with a non-standard Cursor class.
 
 """
-import cursors
+import MySQLdb.cursors
 from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \
      DatabaseError, OperationalError, IntegrityError, InternalError, \
      NotSupportedError, ProgrammingError
@@ -33,7 +33,7 @@
         connection.messages.append(error)
     del cursor
     del connection
-    raise errorclass, errorvalue
+    raise errorclass(errorvalue)
 
 re_numeric_part = re.compile(r"^(\d+)")
 
@@ -57,7 +57,7 @@
 
     """MySQL Database Connection Object"""
 
-    default_cursor = cursors.Cursor
+    default_cursor = MySQLdb.cursors.Cursor
     
     def __init__(self, *args, **kwargs):
         """
@@ -109,17 +109,9 @@
         cursorclass
           class object, used to create cursors (keyword only)
 
-        use_unicode
-          If True, text-like columns are returned as unicode objects
-          using the connection's character set.  Otherwise, text-like
-          columns are returned as strings.  columns are returned as
-          normal strings. Unicode objects will always be encoded to
-          the connection's character set regardless of this setting.
-
         charset
           If supplied, the connection character set will be changed
-          to this character set (MySQL-4.1 and newer). This implies
-          use_unicode=True.
+          to this character set (MySQL-4.1 and newer).
 
         sql_mode
           If supplied, the session SQL mode will be changed to this
@@ -143,15 +135,15 @@
         documentation for the MySQL C API for some hints on what they do.
 
         """
-        from constants import CLIENT, FIELD_TYPE
-        from converters import conversions
+        from .constants import CLIENT, FIELD_TYPE
+        from .converters import conversions
         from weakref import proxy, WeakValueDictionary
         
         import types
 
         kwargs2 = kwargs.copy()
         
-        if kwargs.has_key('conv'):
+        if 'conv' in kwargs:
             conv = kwargs['conv']
         else:
             conv = conversions
@@ -165,14 +157,8 @@
         kwargs2['conv'] = conv2
 
         self.cursorclass = kwargs2.pop('cursorclass', self.default_cursor)
-        charset = kwargs2.pop('charset', '')
+        charset = kwargs2.pop('charset', 'utf8')
 
-        if charset:
-            use_unicode = True
-        else:
-            use_unicode = False
-            
-        use_unicode = kwargs2.pop('use_unicode', use_unicode)
         sql_mode = kwargs2.pop('sql_mode', '')
 
         client_flag = kwargs.get('client_flag', 0)
@@ -197,19 +183,13 @@
                 return db.string_literal(obj)
             return string_literal
 
-        def _get_unicode_literal():
-            def unicode_literal(u, dummy=None):
-                return db.literal(u.encode(unicode_literal.charset))
-            return unicode_literal
-
-        def _get_string_decoder():
-            def string_decoder(s):
-                return s.decode(string_decoder.charset)
-            return string_decoder
-        
+        def _get_bytes_literal():
+            def bytes_literal(u, dummy=None):
+                return db.literal(u.decode(bytes_literal.charset))
+            return bytes_literal
+       
         string_literal = _get_string_literal()
-        self.unicode_literal = unicode_literal = _get_unicode_literal()
-        self.string_decoder = string_decoder = _get_string_decoder()
+        self.bytes_literal = bytes_literal = _get_bytes_literal()
         if not charset:
             charset = self.character_set_name()
         self.set_character_set(charset)
@@ -217,14 +197,9 @@
         if sql_mode:
             self.set_sql_mode(sql_mode)
 
-        if use_unicode:
-            self.converter[FIELD_TYPE.STRING].append((None, string_decoder))
-            self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder))
-            self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder))
-            self.converter[FIELD_TYPE.BLOB].append((None, string_decoder))
-
-        self.encoders[types.StringType] = string_literal
-        self.encoders[types.UnicodeType] = unicode_literal
+        self.encoders[str] = string_literal
+        self.encoders[bytes] = bytes_literal
+        
         self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
         if self._transactional:
             # PEP-249 requires autocommit to be initially off
@@ -297,8 +272,7 @@
                     raise NotSupportedError("server is too old to set charset")
                 self.query('SET NAMES %s' % charset)
                 self.store_result()
-        self.string_decoder.charset = charset
-        self.unicode_literal.charset = charset
+        self.bytes_literal.charset = charset
 
     def set_sql_mode(self, sql_mode):
         """Set the connection sql_mode. See MySQL documentation for
Pouze v MySQL-python-1.2.3/MySQLdb/constants: .cvsignore
Pouze v MySQL-Python-1.2.3-python3/MySQLdb/constants: __pycache__
diff -ru MySQL-python-1.2.3/MySQLdb/converters.py MySQL-Python-1.2.3-python3/MySQLdb/converters.py
--- MySQL-python-1.2.3/MySQLdb/converters.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/MySQLdb/converters.py	2011-10-05 12:49:58.000000000 +0200
@@ -33,9 +33,9 @@
 """
 
 from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL
-from constants import FIELD_TYPE, FLAG
-from times import *
-import types
+from .constants import FIELD_TYPE, FLAG
+from .times import *
+import datetime
 import array
 
 try:
@@ -55,16 +55,16 @@
     """Convert something into a string via str()."""
     return str(s)
 
-def Unicode2Str(s, d):
-    """Convert a unicode object to a string using the default encoding.
+def Bytes2Str(s, d):
+    """Convert a bytes object to a string using the default encoding.
     This is only used as a placeholder for the real function, which
     is connection-dependent."""
-    return s.encode()
+    return s.decode()
 
 Long2Int = Thing2Str
 
 def Float2Str(o, d):
-    return '%.15g' % o
+    return '{:f}'.format(o)
 
 def None2NULL(o, d):
     """Convert None to NULL."""
@@ -115,30 +115,30 @@
     return Thing2Literal(o.tostring(), d)
 
 conversions = {
-    types.IntType: Thing2Str,
-    types.LongType: Long2Int,
-    types.FloatType: Float2Str,
-    types.NoneType: None2NULL,
-    types.TupleType: escape_sequence,
-    types.ListType: escape_sequence,
-    types.DictType: escape_dict,
-    types.InstanceType: Instance2Str,
+    int: Long2Int,
+    float: Float2Str,
+    type(None): None2NULL,
+    tuple: escape_sequence,
+    list: escape_sequence,
+    dict: escape_dict,
+    object: Instance2Str,
     array.ArrayType: array2Str,
-    types.StringType: Thing2Literal, # default
-    types.UnicodeType: Unicode2Str,
-    types.ObjectType: Instance2Str,
-    types.BooleanType: Bool2Str,
-    DateTimeType: DateTime2literal,
-    DateTimeDeltaType: DateTimeDelta2literal,
+    str: Thing2Literal, # default
+    bytes: Bytes2Str,
+    bool: Bool2Str,
+    datetime.date: DateTime2literal,
+    datetime.time: DateTime2literal,
+    datetime.datetime: DateTime2literal,
+    datetime.timedelta: DateTimeDelta2literal,
     set: Set2Str,
     FIELD_TYPE.TINY: int,
     FIELD_TYPE.SHORT: int,
-    FIELD_TYPE.LONG: long,
+    FIELD_TYPE.LONG: int,
     FIELD_TYPE.FLOAT: float,
     FIELD_TYPE.DOUBLE: float,
     FIELD_TYPE.DECIMAL: float,
     FIELD_TYPE.NEWDECIMAL: float,
-    FIELD_TYPE.LONGLONG: long,
+    FIELD_TYPE.LONGLONG: int,
     FIELD_TYPE.INT24: int,
     FIELD_TYPE.YEAR: int,
     FIELD_TYPE.SET: Str2Set,
diff -ru MySQL-python-1.2.3/MySQLdb/cursors.py MySQL-Python-1.2.3-python3/MySQLdb/cursors.py
--- MySQL-python-1.2.3/MySQLdb/cursors.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/MySQLdb/cursors.py	2011-11-25 16:53:26.000000000 +0100
@@ -7,7 +7,6 @@
 
 import re
 import sys
-from types import ListType, TupleType, UnicodeType
 
 
 restr = (r"\svalues\s*"
@@ -153,13 +152,19 @@
         del self.messages[:]
         db = self._get_db()
         charset = db.character_set_name()
-        if isinstance(query, unicode):
-            query = query.encode(charset)
+
         if args is not None:
+            if isinstance(query, bytes):
+                query = query.decode();
+
             query = query % db.literal(args)
+
+        if isinstance(query, str):
+            query = query.encode(charset);
+
         try:
             r = self._query(query)
-        except TypeError, m:
+        except TypeError as m:
             if m.args[0] in ("not enough arguments for format string",
                              "not all arguments converted"):
                 self.messages.append((ProgrammingError, m.args[0]))
@@ -197,8 +202,6 @@
         del self.messages[:]
         db = self._get_db()
         if not args: return
-        charset = db.character_set_name()
-        if isinstance(query, unicode): query = query.encode(charset)
         m = insert_values.search(query)
         if not m:
             r = 0
@@ -210,7 +213,7 @@
         qv = m.group(1)
         try:
             q = [ qv % db.literal(a) for a in args ]
-        except TypeError, msg:
+        except TypeError as msg:
             if msg.args[0] in ("not enough arguments for format string",
                                "not all arguments converted"):
                 self.errorhandler(self, ProgrammingError, msg.args[0])
@@ -259,7 +262,7 @@
         for index, arg in enumerate(args):
             q = "SET @_%s_%d=%s" % (procname, index,
                                          db.literal(arg))
-            if isinstance(q, unicode):
+            if isinstance(q, str):
                 q = q.encode(charset)
             self._query(q)
             self.nextset()
@@ -267,7 +270,7 @@
         q = "CALL %s(%s)" % (procname,
                              ','.join(['@_%s_%d' % (procname, i)
                                        for i in range(len(args))]))
-        if type(q) is UnicodeType:
+        if type(q) is str:
             q = q.encode(charset)
         self._query(q)
         self._executed = q
@@ -363,7 +366,7 @@
             r = value
         else:
             self.errorhandler(self, ProgrammingError,
-                              "unknown scroll mode %s" % `mode`)
+                              "unknown scroll mode %r" % mode)
         if r < 0 or r >= len(self._rows):
             self.errorhandler(self, IndexError, "out of range")
         self.rownumber = r
Pouze v MySQL-python-1.2.3/MySQLdb: .cvsignore
diff -ru MySQL-python-1.2.3/MySQLdb/__init__.py MySQL-Python-1.2.3-python3/MySQLdb/__init__.py
--- MySQL-python-1.2.3/MySQLdb/__init__.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/MySQLdb/__init__.py	2011-10-05 12:49:58.000000000 +0200
@@ -14,7 +14,7 @@
 """
 
 __revision__ = """$Revision: 603 $"""[11:-2]
-from release import __version__, version_info, __author__
+from .release import __version__, version_info, __author__
 
 import _mysql
 
@@ -77,7 +77,7 @@
 
 def Connect(*args, **kwargs):
     """Factory function for connections.Connection."""
-    from connections import Connection
+    from .connections import Connection
     return Connection(*args, **kwargs)
 
 connect = Connection = Connect
diff -ru MySQL-python-1.2.3/_mysql_exceptions.py MySQL-Python-1.2.3-python3/_mysql_exceptions.py
--- MySQL-python-1.2.3/_mysql_exceptions.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/_mysql_exceptions.py	2011-10-05 12:49:58.000000000 +0200
@@ -5,9 +5,8 @@
     http://www.python.org/topics/database/DatabaseAPI-2.0.html
 """
 
-from exceptions import Exception, StandardError, Warning
 
-class MySQLError(StandardError):
+class MySQLError(Exception):
     
     """Exception related to operation with MySQL."""
 
@@ -80,4 +79,3 @@
     has transactions turned off."""
 
 
-del Exception, StandardError
diff -ru MySQL-python-1.2.3/MySQL_python.egg-info/SOURCES.txt MySQL-Python-1.2.3-python3/MySQL_python.egg-info/SOURCES.txt
--- MySQL-python-1.2.3/MySQL_python.egg-info/SOURCES.txt	2010-06-17 09:22:07.000000000 +0200
+++ MySQL-Python-1.2.3-python3/MySQL_python.egg-info/SOURCES.txt	2011-11-25 16:54:24.000000000 +0100
@@ -1,4 +1,3 @@
-.cvsignore
 HISTORY
 MANIFEST.in
 README
@@ -17,14 +16,12 @@
 MySQL_python.egg-info/SOURCES.txt
 MySQL_python.egg-info/dependency_links.txt
 MySQL_python.egg-info/top_level.txt
-MySQLdb/.cvsignore
 MySQLdb/__init__.py
 MySQLdb/connections.py
 MySQLdb/converters.py
 MySQLdb/cursors.py
 MySQLdb/release.py
 MySQLdb/times.py
-MySQLdb/constants/.cvsignore
 MySQLdb/constants/CLIENT.py
 MySQLdb/constants/CR.py
 MySQLdb/constants/ER.py
@@ -32,7 +29,6 @@
 MySQLdb/constants/FLAG.py
 MySQLdb/constants/REFRESH.py
 MySQLdb/constants/__init__.py
-doc/.cvsignore
 doc/FAQ.txt
 doc/MySQLdb.txt
 tests/capabilities.py
diff -ru MySQL-python-1.2.3/README MySQL-Python-1.2.3-python3/README
--- MySQL-python-1.2.3/README	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/README	2011-10-05 12:49:58.000000000 +0200
@@ -8,22 +8,18 @@
 Prerequisites
 -------------
 
-+ Python 2.3.4 or higher
++ Python 3.2 or higher
 
   * http://www.python.org/
 
-  * Versions lower than 2.3 WON'T WORK.
-
-  * 2.4 is the primary test environment.
-
   * Red Hat Linux:
 
     - Make sure you have the Python development headers and libraries
       (python-devel).
 
-+ setuptools
++ distribute
 
-  * http://pypi.python.org/pypi/setuptools
+  * http://pypi.python.org/pypi/distribute/
 
 + MySQL 3.23.32 or higher
 
diff -ru MySQL-python-1.2.3/setup_common.py MySQL-Python-1.2.3-python3/setup_common.py
--- MySQL-python-1.2.3/setup_common.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/setup_common.py	2011-10-05 12:49:58.000000000 +0200
@@ -1,4 +1,4 @@
-from ConfigParser import SafeConfigParser
+from configparser import SafeConfigParser
 
 def get_metadata_and_options():
     config = SafeConfigParser()
@@ -7,8 +7,8 @@
     metadata = dict(config.items('metadata'))
     options = dict(config.items('options'))
 
-    metadata['py_modules'] = filter(None, metadata['py_modules'].split('\n'))
-    metadata['classifiers'] = filter(None, metadata['classifiers'].split('\n'))
+    metadata['py_modules'] = list(filter(None, metadata['py_modules'].split('\n')))
+    metadata['classifiers'] = list(filter(None, metadata['classifiers'].split('\n')))
 
     return metadata, options
 
@@ -30,3 +30,4 @@
 __version__ = "%(version)s"
 """ % metadata)
     rel.close()
+
diff -ru MySQL-python-1.2.3/setup_posix.py MySQL-Python-1.2.3-python3/setup_posix.py
--- MySQL-python-1.2.3/setup_posix.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/setup_posix.py	2011-11-25 17:13:11.000000000 +0100
@@ -1,4 +1,4 @@
-from ConfigParser import SafeConfigParser
+from configparser import SafeConfigParser
 
 # This dequote() business is required for some older versions
 # of mysql_config
@@ -98,5 +98,5 @@
     return metadata, ext_options
 
 if __name__ == "__main__":
-    print """You shouldn't be running this directly; it is used by setup.py."""
+    print("""You shouldn't be running this directly; it is used by setup.py.""")
 
diff -ru MySQL-python-1.2.3/setup.py MySQL-Python-1.2.3-python3/setup.py
--- MySQL-python-1.2.3/setup.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/setup.py	2011-10-05 12:49:58.000000000 +0200
@@ -4,8 +4,8 @@
 import sys
 from setuptools import setup, Extension
 
-if not hasattr(sys, "hexversion") or sys.hexversion < 0x02030000:
-    raise Error("Python 2.3 or newer is required")
+if not hasattr(sys, "hexversion") or sys.hexversion < 0x03000000:
+    raise Exception("Python 3.0 or newer is required")
 
 if os.name == "posix":
     from setup_posix import get_config
diff -ru MySQL-python-1.2.3/setup_windows.py MySQL-Python-1.2.3-python3/setup_windows.py
--- MySQL-python-1.2.3/setup_windows.py	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/setup_windows.py	2011-10-05 12:49:58.000000000 +0200
@@ -1,11 +1,11 @@
 def get_config():
-    import os, sys, _winreg
+    import os, sys, winreg
     from setup_common import get_metadata_and_options, enabled, create_release_file
 
     metadata, options = get_metadata_and_options()
 
-    serverKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, options['registry_key'])
-    mysql_root, dummy = _winreg.QueryValueEx(serverKey,'Location')
+    serverKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, options['registry_key'])
+    mysql_root, dummy = winreg.QueryValueEx(serverKey,options['location'])
 
     extra_objects = []
     static = enabled(options, 'static')
@@ -15,7 +15,7 @@
     else:
         client = "mysqlclient"
 
-    library_dirs = [ os.path.join(mysql_root, r'lib\opt') ]
+    library_dirs = [ os.path.join(mysql_root, r'lib') ]
     libraries = [ 'kernel32', 'advapi32', 'wsock32', client ]
     include_dirs = [ os.path.join(mysql_root, r'include') ]
     extra_compile_args = [ '/Zl' ]
@@ -43,5 +43,5 @@
     return metadata, ext_options
 
 if __name__ == "__main__":
-    print """You shouldn't be running this directly; it is used by setup.py."""
+    print ("""You shouldn't be running this directly; it is used by setup.py.""")
     
diff -ru MySQL-python-1.2.3/site.cfg MySQL-Python-1.2.3-python3/site.cfg
--- MySQL-python-1.2.3/site.cfg	2010-06-17 09:21:56.000000000 +0200
+++ MySQL-Python-1.2.3-python3/site.cfg	2011-10-05 12:49:58.000000000 +0200
@@ -15,4 +15,6 @@
 # The Windows registry key for MySQL.
 # This has to be set for Windows builds to work.
 # Only change this if you have a different version.
-registry_key = SOFTWARE\MySQL AB\MySQL Server 5.0
+registry_key = SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{2DB39FB6-161E-44E7-B2A1-B654C85EFBC1}
+location = InstallLocation
+
diff -ru MySQL-python-1.2.3/tests/capabilities.py MySQL-Python-1.2.3-python3/tests/capabilities.py
--- MySQL-python-1.2.3/tests/capabilities.py	2010-06-17 09:21:55.000000000 +0200
+++ MySQL-Python-1.2.3-python3/tests/capabilities.py	2011-10-05 12:49:58.000000000 +0200
@@ -25,7 +25,7 @@
         self.connection = db
         self.cursor = db.cursor()
         self.BLOBText = ''.join([chr(i) for i in range(256)] * 100);
-        self.BLOBUText = u''.join([unichr(i) for i in range(16384)])
+        self.BLOBUText = ''.join([chr(i) for i in range(16384)])
         self.BLOBBinary = self.db_module.Binary(''.join([chr(i) for i in range(256)] * 16))
 
     leak_test = True
@@ -35,11 +35,11 @@
             import gc
             del self.cursor
             orphans = gc.collect()
-            self.failIf(orphans, "%d orphaned objects found after deleting cursor" % orphans)
+            self.assertFalse(orphans, "%d orphaned objects found after deleting cursor" % orphans)
             
             del self.connection
             orphans = gc.collect()
-            self.failIf(orphans, "%d orphaned objects found after deleting connection" % orphans)
+            self.assertFalse(orphans, "%d orphaned objects found after deleting connection" % orphans)
             
     def table_exists(self, name):
         try:
@@ -81,18 +81,18 @@
         self.create_table(columndefs)
         insert_statement = ('INSERT INTO %s VALUES (%s)' % 
                             (self.table,
-                             ','.join(['%s'] * len(columndefs))))
+                             ','.join(['{!s}'] * len(columndefs))))
         data = [ [ generator(i,j) for j in range(len(columndefs)) ]
                  for i in range(self.rows) ]
         if self.debug:
-            print data
+            print(data)
         self.cursor.executemany(insert_statement, data)
         self.connection.commit()
         # verify
         self.cursor.execute('select * from %s' % self.table)
         l = self.cursor.fetchall()
         if self.debug:
-            print l
+            print(l)
         self.assertEquals(len(l), self.rows)
         try:
             for i in range(self.rows):
@@ -110,7 +110,7 @@
         self.create_table(columndefs)
         insert_statement = ('INSERT INTO %s VALUES (%s)' % 
                             (self.table,
-                             ','.join(['%s'] * len(columndefs))))
+                             ','.join(['{!s}'] * len(columndefs))))
         data = [ [ generator(i,j) for j in range(len(columndefs)) ]
                  for i in range(self.rows) ]
         self.cursor.executemany(insert_statement, data)
@@ -122,33 +122,33 @@
         for i in range(self.rows):
             for j in range(len(columndefs)):
                 self.assertEquals(l[i][j], generator(i,j))
-        delete_statement = 'delete from %s where col1=%%s' % self.table
+        delete_statement = 'delete from %s where col1={!s}' % self.table
         self.cursor.execute(delete_statement, (0,))
         self.cursor.execute('select col1 from %s where col1=%s' % \
                             (self.table, 0))
         l = self.cursor.fetchall()
-        self.failIf(l, "DELETE didn't work")
+        self.assertFalse(l, "DELETE didn't work")
         self.connection.rollback()
         self.cursor.execute('select col1 from %s where col1=%s' % \
                             (self.table, 0))
         l = self.cursor.fetchall()
-        self.failUnless(len(l) == 1, "ROLLBACK didn't work")
+        self.assertTrue(len(l) == 1, "ROLLBACK didn't work")
         self.cursor.execute('drop table %s' % (self.table))
 
     def test_truncation(self):
         columndefs = ( 'col1 INT', 'col2 VARCHAR(255)')
         def generator(row, col):
             if col == 0: return row
-            else: return ('%i' % (row%10))*((255-self.rows/2)+row)
+            else: return ('{:d}'.format(row%10))*(round(255-self.rows/2)+row)
         self.create_table(columndefs)
         insert_statement = ('INSERT INTO %s VALUES (%s)' % 
                             (self.table,
-                             ','.join(['%s'] * len(columndefs))))
+                             ','.join(['{!s}'] * len(columndefs))))
 
         try:
             self.cursor.execute(insert_statement, (0, '0'*256))
         except Warning:
-            if self.debug: print self.cursor.messages
+            if self.debug: print(self.cursor.messages)
         except self.connection.DataError:
             pass
         else:
@@ -163,7 +163,7 @@
                     data.append(generator(i,j))
                 self.cursor.execute(insert_statement,tuple(data))
         except Warning:
-            if self.debug: print self.cursor.messages
+            if self.debug: print(self.cursor.messages)
         except self.connection.DataError:
             pass
         else:
@@ -176,7 +176,7 @@
                      for i in range(self.rows) ]
             self.cursor.executemany(insert_statement, data)
         except Warning:
-            if self.debug: print self.cursor.messages
+            if self.debug: print(self.cursor.messages)
         except self.connection.DataError:
             pass
         else:
diff -ru MySQL-python-1.2.3/tests/dbapi20.py MySQL-Python-1.2.3-python3/tests/dbapi20.py
--- MySQL-python-1.2.3/tests/dbapi20.py	2010-06-17 09:21:55.000000000 +0200
+++ MySQL-Python-1.2.3-python3/tests/dbapi20.py	2011-10-05 12:49:58.000000000 +0200
@@ -177,8 +177,8 @@
     def test_Exceptions(self):
         # Make sure required exceptions exist, and are in the
         # defined heirarchy.
-        self.failUnless(issubclass(self.driver.Warning,StandardError))
-        self.failUnless(issubclass(self.driver.Error,StandardError))
+        self.failUnless(issubclass(self.driver.Warning,Exception))
+        self.failUnless(issubclass(self.driver.Error,Exception))
         self.failUnless(
             issubclass(self.driver.InterfaceError,self.driver.Error)
             )
@@ -382,27 +382,27 @@
 
         if self.driver.paramstyle == 'qmark':
             cur.execute(
-                'insert into %sbooze values (?)' % self.table_prefix,
+                'insert into %sbooze values ({!s})' % self.table_prefix,
                 ("Cooper's",)
                 )
         elif self.driver.paramstyle == 'numeric':
             cur.execute(
-                'insert into %sbooze values (:1)' % self.table_prefix,
+                'insert into %sbooze values ({:1})' % self.table_prefix,
                 ("Cooper's",)
                 )
         elif self.driver.paramstyle == 'named':
             cur.execute(
-                'insert into %sbooze values (:beer)' % self.table_prefix, 
+                'insert into %sbooze values ({beer})' % self.table_prefix, 
                 {'beer':"Cooper's"}
                 )
         elif self.driver.paramstyle == 'format':
             cur.execute(
-                'insert into %sbooze values (%%s)' % self.table_prefix,
+                'insert into %sbooze values ({!s})' % self.table_prefix,
                 ("Cooper's",)
                 )
         elif self.driver.paramstyle == 'pyformat':
             cur.execute(
-                'insert into %sbooze values (%%(beer)s)' % self.table_prefix,
+                'insert into %sbooze values ({beer})' % self.table_prefix,
                 {'beer':"Cooper's"}
                 )
         else:
@@ -432,27 +432,27 @@
             margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ]
             if self.driver.paramstyle == 'qmark':
                 cur.executemany(
-                    'insert into %sbooze values (?)' % self.table_prefix,
+                    'insert into %sbooze values ({!s})' % self.table_prefix,
                     largs
                     )
             elif self.driver.paramstyle == 'numeric':
                 cur.executemany(
-                    'insert into %sbooze values (:1)' % self.table_prefix,
+                    'insert into %sbooze values ({:1})' % self.table_prefix,
                     largs
                     )
             elif self.driver.paramstyle == 'named':
                 cur.executemany(
-                    'insert into %sbooze values (:beer)' % self.table_prefix,
+                    'insert into %sbooze values ({beer})' % self.table_prefix,
                     margs
                     )
             elif self.driver.paramstyle == 'format':
                 cur.executemany(
-                    'insert into %sbooze values (%%s)' % self.table_prefix,
+                    'insert into %sbooze values ({!s})' % self.table_prefix,
                     largs
                     )
             elif self.driver.paramstyle == 'pyformat':
                 cur.executemany(
-                    'insert into %sbooze values (%%(beer)s)' % (
+                    'insert into %sbooze values ({beer})' % (
                         self.table_prefix
                         ),
                     margs
@@ -706,7 +706,7 @@
             that returns two result sets, first the 
 	    number of rows in booze then "name from booze"
         '''
-        raise NotImplementedError,'Helper not implemented'
+        raise NotImplementedError('Helper not implemented')
         #sql="""
         #    create procedure deleteme as
         #    begin
@@ -718,7 +718,7 @@
 
     def help_nextset_tearDown(self,cur):
         'If cleaning up is needed after nextSetTest'
-        raise NotImplementedError,'Helper not implemented'
+        raise NotImplementedError('Helper not implemented')
         #cur.execute("drop procedure deleteme")
 
     def test_nextset(self):
@@ -751,7 +751,7 @@
             con.close()
 
     def test_nextset(self):
-        raise NotImplementedError,'Drivers need to override this test'
+        raise NotImplementedError('Drivers need to override this test')
 
     def test_arraysize(self):
         # Not much here - rest of the tests for this are in test_fetchmany
@@ -786,7 +786,7 @@
 
     def test_setoutputsize(self):
         # Real test for setoutputsize is driver dependant
-        raise NotImplementedError,'Driver need to override this test'
+        raise NotImplementedError('Driver need to override this test')
 
     def test_None(self):
         con = self._connect()
diff -ru MySQL-python-1.2.3/tests/test_MySQLdb_capabilities.py MySQL-Python-1.2.3-python3/tests/test_MySQLdb_capabilities.py
--- MySQL-python-1.2.3/tests/test_MySQLdb_capabilities.py	2010-06-17 09:21:55.000000000 +0200
+++ MySQL-Python-1.2.3-python3/tests/test_MySQLdb_capabilities.py	2011-10-05 12:49:58.000000000 +0200
@@ -41,8 +41,7 @@
         db = self.connection
         c = self.cursor
         self.create_table(('pos INT', 'tree CHAR(20)'))
-        c.executemany("INSERT INTO %s (pos,tree) VALUES (%%s,%%s)" % self.table,
-                      list(enumerate('ash birch cedar larch pine'.split())))
+        c.executemany("INSERT INTO %s (pos,tree) VALUES ({!s},{!s})" % self.table, list(enumerate('ash birch cedar larch pine'.split())) )
         db.commit()
         
         c.execute("""
@@ -77,9 +76,9 @@
         from MySQLdb.constants import ER
         try:
             self.cursor.execute("describe some_non_existent_table");
-        except self.connection.ProgrammingError, msg:
-            self.failUnless(msg[0] == ER.NO_SUCH_TABLE)
-    
+        except self.connection.ProgrammingError as msg:
+            self.assertTrue(msg.code == ER.NO_SUCH_TABLE)
+        
     def test_ping(self):
         self.connection.ping()
         
@@ -90,4 +89,4 @@
         gc.enable()
         gc.set_debug(gc.DEBUG_LEAK)
     unittest.main()
-    print '''"Huh-huh, he said 'unit'." -- Butthead'''
+    print ('''"Huh-huh, he said 'unit'." -- Butthead''')
diff -ru MySQL-python-1.2.3/tests/test_MySQLdb_dbapi20.py MySQL-Python-1.2.3-python3/tests/test_MySQLdb_dbapi20.py
--- MySQL-python-1.2.3/tests/test_MySQLdb_dbapi20.py	2010-06-17 09:21:55.000000000 +0200
+++ MySQL-Python-1.2.3-python3/tests/test_MySQLdb_dbapi20.py	2011-10-05 12:49:58.000000000 +0200
@@ -202,4 +202,4 @@
     
 if __name__ == '__main__':
     unittest.main()
-    print '''"Huh-huh, he said 'unit'." -- Butthead'''
+    print ('''"Huh-huh, he said 'unit'." -- Butthead''')