On Fri, 2010-05-07 at 14:36 -0400, David Malcolm wrote:
> On Fri, 2010-05-07 at 11:08 -0700, Kyle VanderBeek wrote:
> > On Fri, May 7, 2010 at 9:05 AM, David Malcolm <[email protected]>
> > wrote:
> > On Fri, 2010-05-07 at 12:25 +0000, Rawhide Report wrote:
> >
> > Three more python 3 subpackages in today's "rawhide" heading
> > for F14 -
> > I've gone ahead and added these to the wiki here:
> >
> > https://fedoraproject.org/wiki/Features/Python3F13#Python_3_already_in_Fedora
> >
> > Are we missing anything?
> >
> >
> >
> > Crud, this probably means I need to either finish my pure-python MySQL
> > driver, or work on making MySQLdb run with python3. :-) If you want
>
> :)
>
> > to update the upstream status for MySQLdb, we simply haven't started
> > porting it.
>
> You're probably in a better position to give accurate status on that
> page (it's a wiki, feel free to edit)
>
> I actually had a go at porting MySQLdb to py3k, I'll see if I can find
> my source tree.
In the hope that's its helpful, attached is a messy, mostly-compiling
port of the code.
It's from SVN r633; this was an experiment I did back in November 2009.
The .py parts are from 2to3 and are python 3 only, but ought to be
regeneratable via 2to3.
The .c parts are from my 2to3c code and some manual hacking. The aim is
that they're compilable against both 2 and 3 from the same sources.
(I may be misremembering all this)
It may well not fully compile, and I'm definitely playing fast-and-loose
with things like encodings. IIRC I was able to get it to compile, and
to at least connect to MySQL from python3, but I'm definitely getting
things wrong with anything non-ASCII, I'm afraid.
(I'm assuming an invocation of 2to3 upon the .py code, and the use of
the "distribute" fork of setuptools; I'm using python 3.1.1 FWIW)
Hope this is helpful; I'd appreciate a shout-out to Red Hat if it does
help.
Dave
Index: MySQLdb/ez_setup.py
===================================================================
--- MySQLdb/ez_setup.py (revision 633)
+++ MySQLdb/ez_setup.py (working copy)
@@ -62,10 +62,10 @@
if egg_name in md5_data:
digest = md5(data).hexdigest()
if digest != md5_data[egg_name]:
- print >>sys.stderr, (
+ print((
"md5 validation of %s failed! (Possible download problem?)"
% egg_name
- )
+ ), file=sys.stderr)
sys.exit(2)
return data
@@ -95,14 +95,14 @@
return do_download()
try:
pkg_resources.require("setuptools>="+version); return
- except pkg_resources.VersionConflict, e:
+ except pkg_resources.VersionConflict as e:
if was_imported:
- print >>sys.stderr, (
+ print((
"The required version of setuptools (>=%s) is not available, and\n"
"can't be installed while this script is running. Please install\n"
" a more recent version first, using 'easy_install -U setuptools'."
"\n\n(Currently using %r)"
- ) % (version, e.args[0])
+ ) % (version, e.args[0]), file=sys.stderr)
sys.exit(2)
else:
del pkg_resources, sys.modules['pkg_resources'] # reload ok
@@ -121,7 +121,7 @@
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download attempt.
"""
- import urllib2, shutil
+ import urllib.request, urllib.error, urllib.parse, shutil
egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
url = download_base + egg_name
saveto = os.path.join(to_dir, egg_name)
@@ -147,7 +147,7 @@
version, download_base, delay, url
); from time import sleep; sleep(delay)
log.warn("Downloading %s", url)
- src = urllib2.urlopen(url)
+ src = urllib.request.urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = _validate_md5(egg_name, src.read())
@@ -208,10 +208,10 @@
os.unlink(egg)
else:
if setuptools.__version__ == '0.0.1':
- print >>sys.stderr, (
+ print((
"You have an obsolete version of setuptools installed. Please\n"
"remove it from your system entirely before rerunning this script."
- )
+ ), file=sys.stderr)
sys.exit(2)
req = "setuptools>="+version
@@ -230,8 +230,8 @@
from setuptools.command.easy_install import main
main(argv)
else:
- print "Setuptools version",version,"or greater has been installed."
- print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
+ print("Setuptools version",version,"or greater has been installed.")
+ print('(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)')
def update_md5(filenames):
"""Update our built-in md5 registry"""
@@ -244,7 +244,7 @@
md5_data[base] = md5(f.read()).hexdigest()
f.close()
- data = [" %r: %r,\n" % it for it in md5_data.items()]
+ data = [" %r: %r,\n" % it for it in list(md5_data.items())]
data.sort()
repl = "".join(data)
@@ -254,7 +254,7 @@
match = re.search("\nmd5_data = {\n([^}]+)}", src)
if not match:
- print >>sys.stderr, "Internal error!"
+ print("Internal error!", file=sys.stderr)
sys.exit(2)
src = src[:match.start(1)] + repl + src[match.end(1):]
Index: MySQLdb/src/results.c
===================================================================
--- MySQLdb/src/results.c (revision 633)
+++ MySQLdb/src/results.c (working copy)
@@ -184,7 +184,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;
@@ -203,12 +203,12 @@
if (rowitem) {
if (decoder != Py_None)
v = PyObject_CallFunction(decoder,
- "s#",
+ "y#", /* convert from raw bytes to a python "bytes" object */
rowitem,
(int)length);
else
- v = PyString_FromStringAndSize(rowitem,
- (int)length);
+ v = PyBytes_FromStringAndSize(rowitem,
+ (int)length);
if (!v)
return NULL;
} else {
@@ -439,7 +439,7 @@
PyObject *unused)
{
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__[] =
@@ -511,7 +511,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
@@ -531,7 +531,7 @@
char buf[300];
sprintf(buf, "<_mysql.result object at %lx>",
(long)self);
- return PyString_FromString(buf);
+ return PyUnicode_FromString(buf);
}
static PyMethodDef _mysql_ResultObject_methods[] = {
@@ -591,47 +591,25 @@
"connection",
T_OBJECT,
offsetof(_mysql_ConnectionObject, connection),
- RO,
+ READONLY,
"Connection associated with result"
},
{
"decoders",
T_OBJECT,
offsetof(_mysql_ResultObject, decoders),
- RO,
+ READONLY,
"Field decoders for result set"
},
{
"fields",
T_OBJECT,
offsetof(_mysql_ResultObject, fields),
- RO,
+ READONLY,
"Field metadata for result set"
}, {NULL} /* Sentinel */
};
-static PyObject *
-_mysql_ResultObject_getattr(
- _mysql_ResultObject *self,
- char *name)
-{
- PyObject *res;
- struct PyMemberDef *l;
-
- res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name);
- if (res != NULL)
- return res;
- PyErr_Clear();
-
- 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;
-}
-
static int
_mysql_ResultObject_setattr(
_mysql_ResultObject *self,
@@ -655,14 +633,13 @@
}
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 */
+ (getattrfunc)0, /* tp_getattr */
(setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */
0, /*tp_compare*/
(reprfunc)_mysql_ResultObject_repr, /* tp_repr */
@@ -678,7 +655,7 @@
0, /* (hashfunc) tp_hash */
0, /* (ternaryfunc) tp_call */
0, /* (reprfunc) tp_str */
- 0, /* (getattrofunc) tp_getattro */
+ PyObject_GenericGetAttr, /* (getattrofunc) tp_getattro */
0, /* (setattrofunc) tp_setattro */
/* Functions to access object as input/output buffer */
Index: MySQLdb/src/connections.c
===================================================================
--- MySQLdb/src/connections.c (revision 633)
+++ MySQLdb/src/connections.c (working copy)
@@ -50,7 +50,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) {
@@ -227,11 +227,11 @@
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);
+ str = PyBytes_FromStringAndSize((char *) NULL, size*2+1);
if (!str) return PyErr_NoMemory();
- out = PyString_AS_STRING(str);
+ out = PyBytes_AS_STRING(str);
len = mysql_real_escape_string(&(self->connection), out, in, size);
- if (_PyString_Resize(&str, len) < 0) return NULL;
+ if (_PyBytes_Resize(&str, len) < 0) return NULL;
return (str);
}
@@ -252,12 +252,12 @@
char *in, *out;
int len, size;
if (!PyArg_ParseTuple(args, "s#:string_literal", &in, &size)) return NULL;
- str = PyString_FromStringAndSize((char *) NULL, size*2+3);
+ str = PyBytes_FromStringAndSize((char *) NULL, size*2+3);
if (!str) return PyErr_NoMemory();
- out = PyString_AS_STRING(str);
+ out = PyBytes_AS_STRING(str);
len = mysql_real_escape_string(&(self->connection), out+1, in, size);
*out = *(out+len+1) = '\'';
- if (_PyString_Resize(&str, len+2) < 0) return NULL;
+ if (_PyBytes_Resize(&str, len+2) < 0) return NULL;
return (str);
}
@@ -418,7 +418,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
@@ -441,7 +441,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__[] =
@@ -461,7 +461,7 @@
_mysql_ConnectionObject *self,
PyObject *unused)
{
- return PyString_FromString(mysql_sqlstate(&(self->connection)));
+ return PyUnicode_FromString(mysql_sqlstate(&(self->connection)));
}
static char _mysql_ConnectionObject_warning_count__doc__[] =
@@ -475,7 +475,7 @@
_mysql_ConnectionObject *self,
PyObject *unused)
{
- return PyInt_FromLong(mysql_warning_count(&(self->connection)));
+ return PyLong_FromLong(mysql_warning_count(&(self->connection)));
}
#endif
@@ -492,7 +492,7 @@
PyObject *unused)
{
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__[] =
@@ -507,7 +507,7 @@
PyObject *unused)
{
check_connection(self);
- return PyString_FromString(mysql_error(&(self->connection)));
+ return PyUnicode_FromString(mysql_error(&(self->connection)));
}
#if MYSQL_VERSION_ID >= 32303
@@ -570,7 +570,7 @@
#else
s = "latin1";
#endif
- return PyString_FromString(s);
+ return PyUnicode_FromString(s);
}
#if MYSQL_VERSION_ID >= 50007
@@ -631,15 +631,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
@@ -655,7 +655,7 @@
PyObject *unused)
{
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__[] =
@@ -669,7 +669,7 @@
PyObject *unused)
{
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__[] =
@@ -683,7 +683,7 @@
PyObject *unused)
{
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__[] =
@@ -701,7 +701,7 @@
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;
}
@@ -775,9 +775,9 @@
{
check_connection(self);
#if MYSQL_VERSION_ID < 32224
- return PyInt_FromLong((long)mysql_num_fields(&(self->connection)));
+ return PyLong_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
}
@@ -914,7 +914,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__[] =
@@ -974,7 +974,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__[] =
@@ -1038,7 +1038,7 @@
else
sprintf(buf, "<_mysql.connection closed at %lx>",
(long)self);
- return PyString_FromString(buf);
+ return PyUnicode_FromString(buf);
}
static PyMethodDef _mysql_ConnectionObject_methods[] = {
@@ -1255,7 +1255,7 @@
"open",
T_INT,
offsetof(_mysql_ConnectionObject, open),
- RO,
+ READONLY,
"True if connection is open"
},
{
@@ -1269,20 +1269,20 @@
"server_capabilities",
T_UINT,
offsetof(_mysql_ConnectionObject, connection.server_capabilities),
- RO,
+ READONLY,
"Capabilites of server; consult MySQLdb.constants.CLIENT"
},
{
"port",
T_UINT,
offsetof(_mysql_ConnectionObject, connection.port),
- RO,
+ READONLY,
"TCP/IP port of the server connection"
},
{
"client_flag",
T_UINT,
- RO,
+ READONLY,
offsetof(_mysql_ConnectionObject, connection.client_flag),
"Client flags; refer to MySQLdb.constants.CLIENT"
},
@@ -1290,27 +1290,20 @@
};
static PyObject *
-_mysql_ConnectionObject_getattr(
+_mysql_ConnectionObject_getattro(
_mysql_ConnectionObject *self,
- char *name)
+ PyObject *name)
{
- PyObject *res;
- struct PyMemberDef *l;
-
- 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));
-
- for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) {
- if (strcmp(l->name, name) == 0)
- return PyMember_GetOne((char *)self, l);
+ if (!PyUnicode_Check(name)){
+ PyErr_Format(PyExc_TypeError,
+ "attribute name must be string, not '%.200s'",
+ name->ob_type->tp_name);
+ return NULL;
}
+ if (PyUnicode_CompareWithASCIIString(name,"closed") == 0)
+ return PyLong_FromLong((long)!(self->open));
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
+ return PyObject_GenericGetAttr((PyObject*)self, name);
}
static int
@@ -1336,14 +1329,13 @@
}
PyTypeObject _mysql_ConnectionObject_Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
"_mysql.connection", /* (char *)tp_name For printing */
sizeof(_mysql_ConnectionObject), /* tp_basicsize */
0,
(destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */
0, /*tp_print*/
- (getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */
+ (getattrfunc)0, /* tp_getattr */
(setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */
0, /*tp_compare*/
(reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */
@@ -1359,7 +1351,7 @@
0, /* (hashfunc) tp_hash */
0, /* (ternaryfunc) tp_call */
0, /* (reprfunc) tp_str */
- 0, /* (getattrofunc) tp_getattro */
+ (getattrofunc) _mysql_ConnectionObject_getattro, /* tp_getattro */
0, /* (setattrofunc) tp_setattro */
/* Functions to access object as input/output buffer */
@@ -1403,3 +1395,4 @@
0, /* (PyObject *) tp_mro method resolution order */
0, /* (PyObject *) tp_defined */
};
+
Index: MySQLdb/src/mysqlmod.c
===================================================================
--- MySQLdb/src/mysqlmod.c (revision 633)
+++ MySQLdb/src/mysqlmod.c (working copy)
@@ -26,8 +26,8 @@
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;
@@ -36,14 +36,14 @@
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;
}
else {
- PyObject *py_merr = PyInt_FromLong(merr);
+ PyObject *py_merr = PyLong_FromLong(merr);
e = PyDict_GetItem(_mysql_error_map, py_merr);
Py_DECREF(py_merr);
if (!e) {
@@ -51,8 +51,8 @@
else e = _mysql_OperationalError;
}
}
- PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr));
- PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection))));
+ PyTuple_SET_ITEM(t, 0, PyLong_FromLong((long)merr));
+ PyTuple_SET_ITEM(t, 1, PyUnicode_FromString(mysql_error(&(c->connection))));
PyErr_SetObject(e, t);
Py_DECREF(t);
return NULL;
@@ -101,11 +101,11 @@
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,
- "args must contain strings");
+ "args must contain bytes");
goto finish;
}
cmd_args_c[i] = s;
@@ -126,11 +126,11 @@
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,
- "groups must contain strings");
+ "groups must contain bytes");
goto finish;
}
groups_c[i] = s;
@@ -180,7 +180,7 @@
PyObject *unused) {
check_server_init(NULL);
- return PyInt_FromLong((long)mysql_thread_safe());
+ return PyLong_FromLong((long)mysql_thread_safe());
}
#endif
@@ -236,7 +236,7 @@
if (!itemconv) {
PyErr_Clear();
itemconv = PyObject_GetItem(d,
- (PyObject *) &PyString_Type);
+ (PyObject *) &PyBytes_Type);
}
if (!itemconv) {
PyErr_SetString(PyExc_TypeError,
@@ -329,7 +329,7 @@
PyObject *unused)
{
check_server_init(NULL);
- return PyString_FromString(mysql_get_client_info());
+ return PyUnicode_FromString(mysql_get_client_info());
}
extern PyTypeObject _mysql_ConnectionObject_Type;
@@ -409,19 +409,43 @@
(as of 3.23) are NOT implemented.\n\
";
-PyMODINIT_FUNC
-init_mysql(void)
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "_mysql",/* m_name */
+ _mysql___doc__,/* m_doc */
+ 0,/* m_size */
+ _mysql_methods,/* m_methods */
+ NULL,/* m_reload */
+ NULL,/* m_traverse */
+ NULL,/* m_clear */
+ NULL,/* m_free */
+};
+#define MOD_ERROR_VAL NULL
+#else
+#define MOD_ERROR_VAL
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+PyMODINIT_FUNC PyInit__mysql(void)
+#else
+PyMODINIT_FUNC init_mysql(void)
+#endif
{
PyObject *dict, *module, *emod, *edict, *version_tuple;
+#if PY_MAJOR_VERSION >= 3
+ module = PyModule_Create(&moduledef);
+#else
module = Py_InitModule3("_mysql", _mysql_methods, _mysql___doc__);
+#endif
if (!module)
- return; /* this really should never happen */
+ return MOD_ERROR_VAL; /* this really should never happen */
/* Populate final object settings */
- _mysql_ConnectionObject_Type.ob_type = &PyType_Type;
- _mysql_ResultObject_Type.ob_type = &PyType_Type;
- _mysql_FieldObject_Type.ob_type = &PyType_Type;
+ Py_TYPE(&_mysql_ConnectionObject_Type) = &PyType_Type;
+ Py_TYPE(&_mysql_ResultObject_Type) = &PyType_Type;
+ Py_TYPE(&_mysql_FieldObject_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;
@@ -502,11 +526,16 @@
goto error;
Py_DECREF(emod);
+ #if PY_MAJOR_VERSION >= 3
+ return module;
+ #endif
+
error:
if (PyErr_Occurred())
PyErr_SetString(PyExc_ImportError,
"_mysql: init failed");
- return;
+ return NULL;
}
+
Index: MySQLdb/src/fields.c
===================================================================
--- MySQLdb/src/fields.c (revision 633)
+++ MySQLdb/src/fields.c (working copy)
@@ -61,7 +61,7 @@
_mysql_FieldObject_repr(
_mysql_FieldObject *self)
{
- return PyString_FromFormat("<_mysql.field object at %p>", self);
+ return PyUnicode_FromFormat("<_mysql.field object at %p>", self);
}
static PyMethodDef _mysql_FieldObject_methods[] = {
@@ -73,14 +73,14 @@
"result",
T_OBJECT,
offsetof(_mysql_FieldObject, result),
- RO,
+ READONLY,
"Result set"
},
{
"name",
T_STRING,
offsetof(_mysql_FieldObject, field.name),
- RO,
+ READONLY,
"The name of the field. If the field was given\n\
an alias with an AS clause, the value of name is the alias."
},
@@ -88,14 +88,14 @@
"org_name",
T_STRING,
offsetof(_mysql_FieldObject, field.org_name),
- RO,
+ READONLY,
"The name of the field. Aliases are ignored."
},
{
"table",
T_STRING,
offsetof(_mysql_FieldObject, field.table),
- RO,
+ READONLY,
"The name of the table containing this field,\n\
if it isn't a calculated field. For calculated fields,\n\
the table value is an empty string. If the column is selected from a view,\n\
@@ -106,7 +106,7 @@
"org_table",
T_STRING,
offsetof(_mysql_FieldObject, field.org_table),
- RO,
+ READONLY,
"The name of the table. Aliases are ignored.\n\
If the column is selected from a view, org_table names the underlying table.\n"
},
@@ -114,7 +114,7 @@
"db",
T_STRING,
offsetof(_mysql_FieldObject, field.db),
- RO,
+ READONLY,
"The name of the database that the field comes from.\n\
If the field is a calculated field, db is an empty string."
},
@@ -122,14 +122,14 @@
"catalog",
T_STRING,
offsetof(_mysql_FieldObject, field.catalog),
- RO,
+ READONLY,
"The catalog name. This value is always \"def\"."
},
{
"length",
T_ULONG,
offsetof(_mysql_FieldObject, field.length),
- RO,
+ READONLY,
"The width of the field.\n\
as specified in the table definition.\n"
},
@@ -137,7 +137,7 @@
"max_length",
T_ULONG,
offsetof(_mysql_FieldObject, field.max_length),
- RO,
+ READONLY,
"The maximum width of the field for the result set\n\
(the length of the longest field value for the rows actually in the\n\
result set). If you use conn.store_result(), this contains the\n\
@@ -148,21 +148,21 @@
"decimals",
T_UINT,
offsetof(_mysql_FieldObject, field.decimals),
- RO,
+ READONLY,
"The number of decimals for numeric fields.\n"
},
{
"charsetnr",
T_UINT,
offsetof(_mysql_FieldObject, field.charsetnr),
- RO,
+ READONLY,
"The character set number for the field."
},
{
"flags",
T_UINT,
offsetof(_mysql_FieldObject, field.flags),
- RO,
+ READONLY,
"Different bit-flags for the field.\n\
The bits are enumerated in MySQLdb.constants.FLAG.\n\
The flags value may have zero or more of these bits set.\n"
@@ -171,35 +171,13 @@
"type",
T_UINT,
offsetof(_mysql_FieldObject, field.type),
- RO,
+ READONLY,
"The type of the field. The type values\n\
are enumerated in MySQLdb.constants.FIELD_TYPE.\n"
},
{NULL} /* Sentinel */
};
-static PyObject *
-_mysql_FieldObject_getattr(
- _mysql_FieldObject *self,
- char *name)
-{
- PyObject *res;
- struct PyMemberDef *l;
-
- res = Py_FindMethod(_mysql_FieldObject_methods, (PyObject *)self, name);
- if (res != NULL)
- return res;
- PyErr_Clear();
-
- for (l = _mysql_FieldObject_memberlist; l->name != NULL; l++) {
- if (strcmp(l->name, name) == 0)
- return PyMember_GetOne((char *)self, l);
- }
-
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
-}
-
static int
_mysql_FieldObject_setattr(
_mysql_FieldObject *self,
@@ -224,14 +202,13 @@
}
PyTypeObject _mysql_FieldObject_Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
"_mysql.field",
sizeof(_mysql_FieldObject),
0,
(destructor)_mysql_FieldObject_dealloc, /* tp_dealloc */
0, /*tp_print*/
- (getattrfunc)_mysql_FieldObject_getattr, /* tp_getattr */
+ (getattrfunc)0, /* tp_getattr */
(setattrfunc)_mysql_FieldObject_setattr, /* tp_setattr */
0, /*tp_compare*/
(reprfunc)_mysql_FieldObject_repr, /* tp_repr */
@@ -247,7 +224,7 @@
0, /* (hashfunc) tp_hash */
0, /* (ternaryfunc) tp_call */
0, /* (reprfunc) tp_str */
- 0, /* (getattrofunc) tp_getattro */
+ PyObject_GenericGetAttr, /* (getattrofunc) tp_getattro */
0, /* (setattrofunc) tp_setattro */
/* Functions to access object as input/output buffer */
@@ -291,3 +268,4 @@
0, /* (PyObject *) tp_mro method resolution order */
0, /* (PyObject *) tp_defined */
};
+
Index: MySQLdb/src/mysqlmod.h
===================================================================
--- MySQLdb/src/mysqlmod.h (revision 633)
+++ MySQLdb/src/mysqlmod.h (working copy)
@@ -14,7 +14,7 @@
#include "errmsg.h"
#define MyAlloc(s,t) (s *) t.tp_alloc(&t,0)
-#define MyFree(ob) ob->ob_type->tp_free((PyObject *)ob)
+#define MyFree(ob) Py_TYPE(ob)->tp_free((PyObject *)ob)
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
typedef int Py_ssize_t;
Index: MySQLdb/setup_common.py
===================================================================
--- MySQLdb/setup_common.py (revision 633)
+++ MySQLdb/setup_common.py (working copy)
@@ -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'] = [_f for _f in metadata['py_modules'].split('\n') if _f]
+ metadata['classifiers'] = [_f for _f in metadata['classifiers'].split('\n') if _f]
return metadata, options
Index: MySQLdb/setup_windows.py
===================================================================
--- MySQLdb/setup_windows.py (revision 633)
+++ MySQLdb/setup_windows.py (working copy)
@@ -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,'Location')
extra_objects = []
static = enabled(options, 'static')
@@ -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.""")
Index: MySQLdb/tests/capabilities.py
===================================================================
--- MySQLdb/tests/capabilities.py (revision 633)
+++ MySQLdb/tests/capabilities.py (working copy)
@@ -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(16834)])
+ self.BLOBUText = ''.join([chr(i) for i in range(16834)])
self.BLOBBinary = self.db_module.Binary(''.join([chr(i) for i in range(256)] * 16))
leak_test = True
@@ -85,14 +85,14 @@
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):
@@ -148,7 +148,7 @@
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:
Index: MySQLdb/tests/test_MySQLdb_dbapi20.py
===================================================================
--- MySQLdb/tests/test_MySQLdb_dbapi20.py (revision 633)
+++ MySQLdb/tests/test_MySQLdb_dbapi20.py (working copy)
@@ -202,4 +202,4 @@
if __name__ == '__main__':
unittest.main()
- print '''"Huh-huh, he said 'unit'." -- Butthead'''
+ print('''"Huh-huh, he said 'unit'." -- Butthead''')
Index: MySQLdb/tests/dbapi20.py
===================================================================
--- MySQLdb/tests/dbapi20.py (revision 633)
+++ MySQLdb/tests/dbapi20.py (working copy)
@@ -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)
)
@@ -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()
Index: MySQLdb/tests/test_MySQLdb_capabilities.py
===================================================================
--- MySQLdb/tests/test_MySQLdb_capabilities.py (revision 633)
+++ MySQLdb/tests/test_MySQLdb_capabilities.py (working copy)
@@ -78,32 +78,32 @@
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.assertEqual(msg[0], ER.NO_SUCH_TABLE)
def test_INSERT_VALUES(self):
from MySQLdb.cursors import INSERT_VALUES
query = """INSERT FOO (a, b, c) VALUES (%s, %s, %s)"""
matched = INSERT_VALUES.match(query)
- self.failUnless(matched)
+ self.assertTrue(matched)
start = matched.group('start')
end = matched.group('end')
values = matched.group('values')
- self.failUnless(start == """INSERT FOO (a, b, c) VALUES """)
- self.failUnless(values == "(%s, %s, %s)")
- self.failUnless(end == "")
+ self.assertTrue(start == """INSERT FOO (a, b, c) VALUES """)
+ self.assertTrue(values == "(%s, %s, %s)")
+ self.assertTrue(end == "")
def test_ping(self):
self.connection.ping()
def test_literal_int(self):
- self.failUnless("2" == self.connection.literal(2))
+ self.assertEqual("2", self.connection.literal(2))
def test_literal_float(self):
- self.failUnless("3.1415" == self.connection.literal(3.1415))
+ self.assertEqual("3.1415", self.connection.literal(3.1415))
def test_literal_string(self):
- self.failUnless("'foo'" == self.connection.literal("foo"))
+ self.assertEqual("'foo'", self.connection.literal("foo"))
if __name__ == '__main__':
@@ -112,4 +112,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''')
Index: MySQLdb/setup_posix.py
===================================================================
--- MySQLdb/setup_posix.py (revision 633)
+++ MySQLdb/setup_posix.py (working copy)
@@ -88,4 +88,4 @@
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.""")
Index: MySQLdb/MySQLdb/converters.py
===================================================================
--- MySQLdb/MySQLdb/converters.py (revision 633)
+++ MySQLdb/MySQLdb/converters.py (working copy)
@@ -39,7 +39,6 @@
from MySQLdb.times import datetime_to_sql, timedelta_to_sql, \
timedelta_or_None, datetime_or_None, date_or_None, \
mysql_timestamp_converter
-from types import InstanceType
import array
import datetime
from decimal import Decimal
@@ -90,10 +89,10 @@
"""
if obj.__class__ in conv:
return conv[obj.__class__](obj, conv)
- classes = [ key for key in conv.keys()
+ classes = [ key for key in list(conv.keys())
if isinstance(obj, key) ]
if not classes:
- return conv[types.StringType](obj, conv)
+ return conv[bytes](obj, conv)
conv[obj.__class__] = conv[classes[0]]
return conv[classes[0]](obj, conv)
@@ -102,16 +101,15 @@
simple_type_encoders = {
int: object_to_sql,
- long: object_to_sql,
float: float_to_sql,
type(None): None_to_sql,
- unicode: unicode_to_sql,
+ str: unicode_to_sql,
object: instance_to_sql,
bool: bool_to_sql,
datetime.datetime: datetime_to_sql,
datetime.timedelta: timedelta_to_sql,
set: Set_to_sql,
- str: object_to_quoted_sql, # default
+ bytes: object_to_quoted_sql, # default
}
# This is for MySQL column types that can be converted directly
@@ -145,7 +143,7 @@
# on the stack will be checked.
def default_decoder(field):
- return str
+ return bytes
def default_encoder(value):
return object_to_quoted_sql
@@ -167,13 +165,13 @@
if field.type not in character_types:
return None
if field.charsetnr == 63: # BINARY
- return str
+ return bytes
charset = field.result.connection.character_set_name()
- def char_to_unicode(s):
+ def bytes_to_unicode(s):
return s.decode(charset)
- return char_to_unicode
+ return bytes_to_unicode
default_decoders = [
character_decoder,
Index: MySQLdb/MySQLdb/cursors.py
===================================================================
--- MySQLdb/MySQLdb/cursors.py (revision 633)
+++ MySQLdb/MySQLdb/cursors.py (working copy)
@@ -159,13 +159,13 @@
del self.messages[:]
db = self._get_db()
charset = db.character_set_name()
- if isinstance(query, unicode):
- query = query.encode(charset)
try:
if args is not None:
query = query % tuple(map(self.connection.literal, args))
+ if isinstance(query, str):
+ query = query.encode(charset)
result = self._query(query)
- except TypeError, msg:
+ except TypeError as msg:
if msg.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
self.messages.append((self.ProgrammingError, msg.args[0]))
@@ -208,8 +208,8 @@
if not args:
return
charset = self.connection.character_set_name()
- if isinstance(query, unicode):
- query = query.encode(charset)
+ #if isinstance(query, str):
+ #query = query.encode(charset)
matched = INSERT_VALUES.match(query)
if not matched:
self.rowcount = sum([ self.execute(query, arg) for arg in args ])
@@ -225,7 +225,7 @@
self._executed = multirow_query
self.rowcount = int(self._query(multirow_query))
- except TypeError, msg:
+ except TypeError as msg:
if msg.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
self.messages.append((self.ProgrammingError, msg.args[0]))
@@ -278,7 +278,7 @@
for index, arg in enumerate(args):
query = "SET @_%s_%d=%s" % (procname, index,
self.connection.literal(arg))
- if isinstance(query, unicode):
+ if isinstance(query, str):
query = query.encode(charset)
self._query(query)
self.nextset()
@@ -286,7 +286,7 @@
query = "CALL %s(%s)" % (procname,
','.join(['@_%s_%d' % (procname, i)
for i in range(len(args))]))
- if isinstance(query, unicode):
+ if isinstance(query, str):
query = query.encode(charset)
self._query(query)
self._executed = query
@@ -369,7 +369,7 @@
row = value
else:
self.errorhandler(self, self.ProgrammingError,
- "unknown scroll mode %s" % `mode`)
+ "unknown scroll mode %s" % repr(mode))
if row < 0 or row >= len(self._rows):
self.errorhandler(self, IndexError, "out of range")
self.rownumber = row
Index: MySQLdb/MySQLdb/exceptions.py
===================================================================
--- MySQLdb/MySQLdb/exceptions.py (revision 633)
+++ MySQLdb/MySQLdb/exceptions.py (working copy)
@@ -12,16 +12,13 @@
# It would make things much cleaner for Python-2.5, but breaks older.
try:
- from exceptions import Exception, StandardError, Warning
+ from exceptions import Exception, Exception, Warning
except ImportError:
- import sys
- e = sys.modules['exceptions']
- StandardError = e.StandardError
- Warning = e.Warning
+ pass
from MySQLdb.constants import ER
-class MySQLError(StandardError):
+class MySQLError(Exception):
"""Exception related to operation with MySQL."""
@@ -114,4 +111,4 @@
_map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK,
ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE)
-del StandardError, _map_error, ER
+del _map_error, ER
Index: MySQLdb/MySQLdb/times.py
===================================================================
--- MySQLdb/MySQLdb/times.py (revision 633)
+++ MySQLdb/MySQLdb/times.py (working copy)
@@ -191,7 +191,7 @@
"""
try:
- return date(*map(int, obj.split('-', 2)))
+ return date(*list(map(int, obj.split(b'-', 2))))
except ValueError:
return None
@@ -238,4 +238,4 @@
if __name__ == "__main__":
import doctest
doctest.testmod()
-
\ No newline at end of file
+
Index: MySQLdb/MySQLdb/connections.py
===================================================================
--- MySQLdb/MySQLdb/connections.py (revision 633)
+++ MySQLdb/MySQLdb/connections.py (working copy)
@@ -29,7 +29,7 @@
connection.messages.append(error)
del cursor
del connection
- raise errorclass, errorvalue
+ raise errorclass(errorvalue)
class Connection(object):
_______________________________________________
python-devel mailing list
[email protected]
https://admin.fedoraproject.org/mailman/listinfo/python-devel