summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/cextension
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-01-21 20:10:23 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-01-21 20:10:23 -0500
commit07fb90c6cc14de6d02cf4be592c57d56831f59f7 (patch)
tree050ef65db988559c60f7aa40f2d0bfe24947e548 /lib/sqlalchemy/cextension
parent560fd1d5ed643a1b0f95296f3b840c1963bbe67f (diff)
parentee1f4d21037690ad996c5eacf7e1200e92f2fbaa (diff)
downloadsqlalchemy-ticket_2501.tar.gz
Merge branch 'master' into ticket_2501ticket_2501
Conflicts: lib/sqlalchemy/orm/mapper.py
Diffstat (limited to 'lib/sqlalchemy/cextension')
-rw-r--r--lib/sqlalchemy/cextension/processors.c287
-rw-r--r--lib/sqlalchemy/cextension/resultproxy.c109
-rw-r--r--lib/sqlalchemy/cextension/utils.c48
3 files changed, 396 insertions, 48 deletions
diff --git a/lib/sqlalchemy/cextension/processors.c b/lib/sqlalchemy/cextension/processors.c
index 4e82ffc6b..d56817763 100644
--- a/lib/sqlalchemy/cextension/processors.c
+++ b/lib/sqlalchemy/cextension/processors.c
@@ -1,7 +1,7 @@
/*
processors.c
-Copyright (C) 2010-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
-Copyright (C) 2010 Gaetan de Menten gdementen@gmail.com
+Copyright (C) 2010-2014 the SQLAlchemy authors and contributors <see AUTHORS file>
+Copyright (C) 2010-2011 Gaetan de Menten gdementen@gmail.com
This module is part of SQLAlchemy and is released under
the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -10,13 +10,15 @@ the MIT License: http://www.opensource.org/licenses/mit-license.php
#include <Python.h>
#include <datetime.h>
+#define MODULE_NAME "cprocessors"
+#define MODULE_DOC "Module containing C versions of data processing functions."
+
#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
-
static PyObject *
int_to_boolean(PyObject *self, PyObject *arg)
{
@@ -26,7 +28,12 @@ int_to_boolean(PyObject *self, PyObject *arg)
if (arg == Py_None)
Py_RETURN_NONE;
+
+#if PY_MAJOR_VERSION >= 3
+ l = PyLong_AsLong(arg);
+#else
l = PyInt_AsLong(arg);
+#endif
if (l == 0) {
res = Py_False;
} else if (l == 1) {
@@ -65,23 +72,48 @@ to_float(PyObject *self, PyObject *arg)
static PyObject *
str_to_datetime(PyObject *self, PyObject *arg)
{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+ PyObject *err_bytes;
+#endif
const char *str;
+ int numparsed;
unsigned int year, month, day, hour, minute, second, microsecond = 0;
PyObject *err_repr;
if (arg == Py_None)
Py_RETURN_NONE;
+#if PY_MAJOR_VERSION >= 3
+ bytes = PyUnicode_AsASCIIString(arg);
+ if (bytes == NULL)
+ str = NULL;
+ else
+ str = PyBytes_AS_STRING(bytes);
+#else
str = PyString_AsString(arg);
+#endif
if (str == NULL) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse datetime string '%.200s' "
+ "- value is not a string.",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse datetime string '%.200s' "
"- value is not a string.",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
@@ -92,15 +124,30 @@ str_to_datetime(PyObject *self, PyObject *arg)
not accept "2000-01-01 00:00:00.". I don't know which is better, but they
should be coherent.
*/
- if (sscanf(str, "%4u-%2u-%2u %2u:%2u:%2u.%6u", &year, &month, &day,
- &hour, &minute, &second, &microsecond) < 6) {
+ numparsed = sscanf(str, "%4u-%2u-%2u %2u:%2u:%2u.%6u", &year, &month, &day,
+ &hour, &minute, &second, &microsecond);
+#if PY_MAJOR_VERSION >= 3
+ Py_DECREF(bytes);
+#endif
+ if (numparsed < 6) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse datetime string: %.200s",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse datetime string: %.200s",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
@@ -111,22 +158,47 @@ str_to_datetime(PyObject *self, PyObject *arg)
static PyObject *
str_to_time(PyObject *self, PyObject *arg)
{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+ PyObject *err_bytes;
+#endif
const char *str;
+ int numparsed;
unsigned int hour, minute, second, microsecond = 0;
PyObject *err_repr;
if (arg == Py_None)
Py_RETURN_NONE;
+#if PY_MAJOR_VERSION >= 3
+ bytes = PyUnicode_AsASCIIString(arg);
+ if (bytes == NULL)
+ str = NULL;
+ else
+ str = PyBytes_AS_STRING(bytes);
+#else
str = PyString_AsString(arg);
+#endif
if (str == NULL) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse time string '%.200s' - value is not a string.",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse time string '%.200s' - value is not a string.",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
@@ -137,15 +209,30 @@ str_to_time(PyObject *self, PyObject *arg)
not accept "00:00:00.". I don't know which is better, but they should be
coherent.
*/
- if (sscanf(str, "%2u:%2u:%2u.%6u", &hour, &minute, &second,
- &microsecond) < 3) {
+ numparsed = sscanf(str, "%2u:%2u:%2u.%6u", &hour, &minute, &second,
+ &microsecond);
+#if PY_MAJOR_VERSION >= 3
+ Py_DECREF(bytes);
+#endif
+ if (numparsed < 3) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse time string: %.200s",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse time string: %.200s",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
@@ -155,34 +242,73 @@ str_to_time(PyObject *self, PyObject *arg)
static PyObject *
str_to_date(PyObject *self, PyObject *arg)
{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+ PyObject *err_bytes;
+#endif
const char *str;
+ int numparsed;
unsigned int year, month, day;
PyObject *err_repr;
if (arg == Py_None)
Py_RETURN_NONE;
+#if PY_MAJOR_VERSION >= 3
+ bytes = PyUnicode_AsASCIIString(arg);
+ if (bytes == NULL)
+ str = NULL;
+ else
+ str = PyBytes_AS_STRING(bytes);
+#else
str = PyString_AsString(arg);
+#endif
if (str == NULL) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse date string '%.200s' - value is not a string.",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse date string '%.200s' - value is not a string.",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
- if (sscanf(str, "%4u-%2u-%2u", &year, &month, &day) != 3) {
+ numparsed = sscanf(str, "%4u-%2u-%2u", &year, &month, &day);
+#if PY_MAJOR_VERSION >= 3
+ Py_DECREF(bytes);
+#endif
+ if (numparsed != 3) {
err_repr = PyObject_Repr(arg);
if (err_repr == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(err_repr);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_ValueError,
+ "Couldn't parse date string: %.200s",
+ PyBytes_AS_STRING(err_bytes));
+ Py_DECREF(err_bytes);
+#else
PyErr_Format(
PyExc_ValueError,
"Couldn't parse date string: %.200s",
PyString_AsString(err_repr));
+#endif
Py_DECREF(err_repr);
return NULL;
}
@@ -219,17 +345,35 @@ UnicodeResultProcessor_init(UnicodeResultProcessor *self, PyObject *args,
PyObject *encoding, *errors = NULL;
static char *kwlist[] = {"encoding", "errors", NULL};
+#if PY_MAJOR_VERSION >= 3
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|U:__init__", kwlist,
+ &encoding, &errors))
+ return -1;
+#else
if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|S:__init__", kwlist,
&encoding, &errors))
return -1;
+#endif
+#if PY_MAJOR_VERSION >= 3
+ encoding = PyUnicode_AsASCIIString(encoding);
+#else
Py_INCREF(encoding);
+#endif
self->encoding = encoding;
if (errors) {
+#if PY_MAJOR_VERSION >= 3
+ errors = PyUnicode_AsASCIIString(errors);
+#else
Py_INCREF(errors);
+#endif
} else {
+#if PY_MAJOR_VERSION >= 3
+ errors = PyBytes_FromString("strict");
+#else
errors = PyString_FromString("strict");
+#endif
if (errors == NULL)
return -1;
}
@@ -248,11 +392,58 @@ UnicodeResultProcessor_process(UnicodeResultProcessor *self, PyObject *value)
if (value == Py_None)
Py_RETURN_NONE;
+#if PY_MAJOR_VERSION >= 3
+ if (PyBytes_AsStringAndSize(value, &str, &len))
+ return NULL;
+
+ encoding = PyBytes_AS_STRING(self->encoding);
+ errors = PyBytes_AS_STRING(self->errors);
+#else
+ if (PyString_AsStringAndSize(value, &str, &len))
+ return NULL;
+
+ encoding = PyString_AS_STRING(self->encoding);
+ errors = PyString_AS_STRING(self->errors);
+#endif
+
+ return PyUnicode_Decode(str, len, encoding, errors);
+}
+
+static PyObject *
+UnicodeResultProcessor_conditional_process(UnicodeResultProcessor *self, PyObject *value)
+{
+ const char *encoding, *errors;
+ char *str;
+ Py_ssize_t len;
+
+ if (value == Py_None)
+ Py_RETURN_NONE;
+
+#if PY_MAJOR_VERSION >= 3
+ if (PyUnicode_Check(value) == 1) {
+ Py_INCREF(value);
+ return value;
+ }
+
+ if (PyBytes_AsStringAndSize(value, &str, &len))
+ return NULL;
+
+ encoding = PyBytes_AS_STRING(self->encoding);
+ errors = PyBytes_AS_STRING(self->errors);
+#else
+
+ if (PyUnicode_Check(value) == 1) {
+ Py_INCREF(value);
+ return value;
+ }
+
if (PyString_AsStringAndSize(value, &str, &len))
return NULL;
+
encoding = PyString_AS_STRING(self->encoding);
errors = PyString_AS_STRING(self->errors);
+#endif
return PyUnicode_Decode(str, len, encoding, errors);
}
@@ -262,18 +453,23 @@ UnicodeResultProcessor_dealloc(UnicodeResultProcessor *self)
{
Py_XDECREF(self->encoding);
Py_XDECREF(self->errors);
+#if PY_MAJOR_VERSION >= 3
+ Py_TYPE(self)->tp_free((PyObject*)self);
+#else
self->ob_type->tp_free((PyObject*)self);
+#endif
}
static PyMethodDef UnicodeResultProcessor_methods[] = {
{"process", (PyCFunction)UnicodeResultProcessor_process, METH_O,
"The value processor itself."},
+ {"conditional_process", (PyCFunction)UnicodeResultProcessor_conditional_process, METH_O,
+ "Conditional version of the value processor."},
{NULL} /* Sentinel */
};
static PyTypeObject UnicodeResultProcessorType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
+ PyVarObject_HEAD_INIT(NULL, 0)
"sqlalchemy.cprocessors.UnicodeResultProcessor", /* tp_name */
sizeof(UnicodeResultProcessor), /* tp_basicsize */
0, /* tp_itemsize */
@@ -323,7 +519,11 @@ DecimalResultProcessor_init(DecimalResultProcessor *self, PyObject *args,
{
PyObject *type, *format;
+#if PY_MAJOR_VERSION >= 3
+ if (!PyArg_ParseTuple(args, "OU", &type, &format))
+#else
if (!PyArg_ParseTuple(args, "OS", &type, &format))
+#endif
return -1;
Py_INCREF(type);
@@ -343,11 +543,21 @@ DecimalResultProcessor_process(DecimalResultProcessor *self, PyObject *value)
if (value == Py_None)
Py_RETURN_NONE;
+ /* Decimal does not accept float values directly */
+ /* SQLite can also give us an integer here (see [ticket:2432]) */
+ /* XXX: starting with Python 3.1, we could use Decimal.from_float(f),
+ but the result wouldn't be the same */
+
args = PyTuple_Pack(1, value);
if (args == NULL)
return NULL;
+#if PY_MAJOR_VERSION >= 3
+ str = PyUnicode_Format(self->format, args);
+#else
str = PyString_Format(self->format, args);
+#endif
+
Py_DECREF(args);
if (str == NULL)
return NULL;
@@ -362,7 +572,11 @@ DecimalResultProcessor_dealloc(DecimalResultProcessor *self)
{
Py_XDECREF(self->type);
Py_XDECREF(self->format);
+#if PY_MAJOR_VERSION >= 3
+ Py_TYPE(self)->tp_free((PyObject*)self);
+#else
self->ob_type->tp_free((PyObject*)self);
+#endif
}
static PyMethodDef DecimalResultProcessor_methods[] = {
@@ -372,8 +586,7 @@ static PyMethodDef DecimalResultProcessor_methods[] = {
};
static PyTypeObject DecimalResultProcessorType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
+ PyVarObject_HEAD_INIT(NULL, 0)
"sqlalchemy.DecimalResultProcessor", /* tp_name */
sizeof(DecimalResultProcessor), /* tp_basicsize */
0, /* tp_itemsize */
@@ -413,11 +626,6 @@ static PyTypeObject DecimalResultProcessorType = {
0, /* tp_new */
};
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-
-
static PyMethodDef module_methods[] = {
{"int_to_boolean", int_to_boolean, METH_O,
"Convert an integer to a boolean."},
@@ -434,23 +642,53 @@ static PyMethodDef module_methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef module_def = {
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME,
+ MODULE_DOC,
+ -1,
+ module_methods
+};
+
+#define INITERROR return NULL
+
+PyMODINIT_FUNC
+PyInit_cprocessors(void)
+
+#else
+
+#define INITERROR return
+
PyMODINIT_FUNC
initcprocessors(void)
+
+#endif
+
{
PyObject *m;
UnicodeResultProcessorType.tp_new = PyType_GenericNew;
if (PyType_Ready(&UnicodeResultProcessorType) < 0)
- return;
+ INITERROR;
DecimalResultProcessorType.tp_new = PyType_GenericNew;
if (PyType_Ready(&DecimalResultProcessorType) < 0)
- return;
+ INITERROR;
- m = Py_InitModule3("cprocessors", module_methods,
- "Module containing C versions of data processing functions.");
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&module_def);
+#else
+ m = Py_InitModule3(MODULE_NAME, module_methods, MODULE_DOC);
+#endif
if (m == NULL)
- return;
+ INITERROR;
PyDateTime_IMPORT;
@@ -461,5 +699,8 @@ initcprocessors(void)
Py_INCREF(&DecimalResultProcessorType);
PyModule_AddObject(m, "DecimalResultProcessor",
(PyObject *)&DecimalResultProcessorType);
-}
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
+}
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c
index b70f9c271..218c7b807 100644
--- a/lib/sqlalchemy/cextension/resultproxy.c
+++ b/lib/sqlalchemy/cextension/resultproxy.c
@@ -1,7 +1,7 @@
/*
resultproxy.c
-Copyright (C) 2010-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
-Copyright (C) 2010 Gaetan de Menten gdementen@gmail.com
+Copyright (C) 2010-2014 the SQLAlchemy authors and contributors <see AUTHORS file>
+Copyright (C) 2010-2011 Gaetan de Menten gdementen@gmail.com
This module is part of SQLAlchemy and is released under
the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -9,6 +9,9 @@ the MIT License: http://www.opensource.org/licenses/mit-license.php
#include <Python.h>
+#define MODULE_NAME "cresultproxy"
+#define MODULE_DOC "Module containing C versions of core ResultProxy classes."
+
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
typedef int Py_ssize_t;
#define PY_SSIZE_T_MAX INT_MAX
@@ -150,7 +153,11 @@ BaseRowProxy_dealloc(BaseRowProxy *self)
Py_XDECREF(self->row);
Py_XDECREF(self->processors);
Py_XDECREF(self->keymap);
+#if PY_MAJOR_VERSION >= 3
+ Py_TYPE(self)->tp_free((PyObject *)self);
+#else
self->ob_type->tp_free((PyObject *)self);
+#endif
}
static PyObject *
@@ -245,14 +252,21 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
PyObject *processor, *value, *processed_value;
PyObject *row, *record, *result, *indexobject;
PyObject *exc_module, *exception, *cstr_obj;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *bytes;
+#endif
char *cstr_key;
long index;
int key_fallback = 0;
int tuple_check = 0;
+#if PY_MAJOR_VERSION < 3
if (PyInt_CheckExact(key)) {
index = PyInt_AS_LONG(key);
- } else if (PyLong_CheckExact(key)) {
+ }
+#endif
+
+ if (PyLong_CheckExact(key)) {
index = PyLong_AsLong(key);
if ((index == -1) && PyErr_Occurred())
/* -1 can be either the actual value, or an error flag. */
@@ -305,7 +319,21 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
cstr_obj = PyObject_Str(key);
if (cstr_obj == NULL)
return NULL;
+
+/*
+ FIXME: raise encoding error exception (in both versions below)
+ if the key contains non-ascii chars, instead of an
+ InvalidRequestError without any message like in the
+ python version.
+*/
+#if PY_MAJOR_VERSION >= 3
+ bytes = PyUnicode_AsASCIIString(cstr_obj);
+ if (bytes == NULL)
+ return NULL;
+ cstr_key = PyBytes_AS_STRING(bytes);
+#else
cstr_key = PyString_AsString(cstr_obj);
+#endif
if (cstr_key == NULL) {
Py_DECREF(cstr_obj);
return NULL;
@@ -318,7 +346,11 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
return NULL;
}
+#if PY_MAJOR_VERSION >= 3
+ index = PyLong_AsLong(indexobject);
+#else
index = PyInt_AsLong(indexobject);
+#endif
if ((index == -1) && PyErr_Occurred())
/* -1 can be either the actual value, or an error flag. */
return NULL;
@@ -357,13 +389,23 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
static PyObject *
BaseRowProxy_getitem(PyObject *self, Py_ssize_t i)
{
- return BaseRowProxy_subscript((BaseRowProxy*)self, PyInt_FromSsize_t(i));
+ PyObject *index;
+
+#if PY_MAJOR_VERSION >= 3
+ index = PyLong_FromSsize_t(i);
+#else
+ index = PyInt_FromSsize_t(i);
+#endif
+ return BaseRowProxy_subscript((BaseRowProxy*)self, index);
}
static PyObject *
BaseRowProxy_getattro(BaseRowProxy *self, PyObject *name)
{
PyObject *tmp;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *err_bytes;
+#endif
if (!(tmp = PyObject_GenericGetAttr((PyObject *)self, name))) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
@@ -375,11 +417,23 @@ BaseRowProxy_getattro(BaseRowProxy *self, PyObject *name)
tmp = BaseRowProxy_subscript(self, name);
if (tmp == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
+
+#if PY_MAJOR_VERSION >= 3
+ err_bytes = PyUnicode_AsASCIIString(name);
+ if (err_bytes == NULL)
+ return NULL;
+ PyErr_Format(
+ PyExc_AttributeError,
+ "Could not locate column in row for column '%.200s'",
+ PyBytes_AS_STRING(err_bytes)
+ );
+#else
PyErr_Format(
PyExc_AttributeError,
"Could not locate column in row for column '%.200s'",
PyString_AsString(name)
);
+#endif
return NULL;
}
return tmp;
@@ -565,8 +619,7 @@ static PyMappingMethods BaseRowProxy_as_mapping = {
};
static PyTypeObject BaseRowProxyType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* ob_size */
+ PyVarObject_HEAD_INIT(NULL, 0)
"sqlalchemy.cresultproxy.BaseRowProxy", /* tp_name */
sizeof(BaseRowProxy), /* tp_basicsize */
0, /* tp_itemsize */
@@ -606,34 +659,60 @@ static PyTypeObject BaseRowProxyType = {
0 /* tp_new */
};
+static PyMethodDef module_methods[] = {
+ {"safe_rowproxy_reconstructor", safe_rowproxy_reconstructor, METH_VARARGS,
+ "reconstruct a RowProxy instance from its pickled form."},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
-static PyMethodDef module_methods[] = {
- {"safe_rowproxy_reconstructor", safe_rowproxy_reconstructor, METH_VARARGS,
- "reconstruct a RowProxy instance from its pickled form."},
- {NULL, NULL, 0, NULL} /* Sentinel */
+#if PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef module_def = {
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME,
+ MODULE_DOC,
+ -1,
+ module_methods
};
+#define INITERROR return NULL
+
+PyMODINIT_FUNC
+PyInit_cresultproxy(void)
+
+#else
+
+#define INITERROR return
+
PyMODINIT_FUNC
initcresultproxy(void)
+
+#endif
+
{
PyObject *m;
BaseRowProxyType.tp_new = PyType_GenericNew;
if (PyType_Ready(&BaseRowProxyType) < 0)
- return;
+ INITERROR;
- m = Py_InitModule3("cresultproxy", module_methods,
- "Module containing C versions of core ResultProxy classes.");
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&module_def);
+#else
+ m = Py_InitModule3(MODULE_NAME, module_methods, MODULE_DOC);
+#endif
if (m == NULL)
- return;
+ INITERROR;
Py_INCREF(&BaseRowProxyType);
PyModule_AddObject(m, "BaseRowProxy", (PyObject *)&BaseRowProxyType);
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
}
-
diff --git a/lib/sqlalchemy/cextension/utils.c b/lib/sqlalchemy/cextension/utils.c
index 5928c4103..377ba8a8d 100644
--- a/lib/sqlalchemy/cextension/utils.c
+++ b/lib/sqlalchemy/cextension/utils.c
@@ -1,6 +1,6 @@
/*
utils.c
-Copyright (C) 2012-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
+Copyright (C) 2012-2014 the SQLAlchemy authors and contributors <see AUTHORS file>
This module is part of SQLAlchemy and is released under
the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -8,6 +8,9 @@ the MIT License: http://www.opensource.org/licenses/mit-license.php
#include <Python.h>
+#define MODULE_NAME "cutils"
+#define MODULE_DOC "Module containing C versions of utility functions."
+
/*
Given arguments from the calling form *multiparams, **params,
return a list of bind parameter structures, usually a list of
@@ -172,26 +175,51 @@ distill_params(PyObject *self, PyObject *args)
}
}
-#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
-#define PyMODINIT_FUNC void
-#endif
-
-
static PyMethodDef module_methods[] = {
{"_distill_params", distill_params, METH_VARARGS,
"Distill an execute() parameter structure."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+
+static struct PyModuleDef module_def = {
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME,
+ MODULE_DOC,
+ -1,
+ module_methods
+ };
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+PyMODINIT_FUNC
+PyInit_cutils(void)
+#else
PyMODINIT_FUNC
initcutils(void)
+#endif
{
PyObject *m;
- m = Py_InitModule3("cutils", module_methods,
- "Internal utility functions.");
- if (m == NULL)
- return;
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&module_def);
+#else
+ m = Py_InitModule3(MODULE_NAME, module_methods, MODULE_DOC);
+#endif
+#if PY_MAJOR_VERSION >= 3
+ if (m == NULL)
+ return NULL;
+ return m;
+#else
+ if (m == NULL)
+ return;
+#endif
}