2010-05-07 19:33:49 +02:00
|
|
|
/*
|
|
|
|
processors.c
|
2017-04-15 18:33:29 +02:00
|
|
|
Copyright (C) 2010-2017 the SQLAlchemy authors and contributors <see AUTHORS file>
|
|
|
|
Copyright (C) 2010-2011 Gaetan de Menten gdementen@gmail.com
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
This module is part of SQLAlchemy and is released under
|
|
|
|
the MIT License: http://www.opensource.org/licenses/mit-license.php
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Python.h>
|
|
|
|
#include <datetime.h>
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#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
|
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
static PyObject *
|
|
|
|
int_to_boolean(PyObject *self, PyObject *arg)
|
|
|
|
{
|
2017-04-15 18:33:29 +02:00
|
|
|
int l = 0;
|
2010-05-07 19:33:49 +02:00
|
|
|
PyObject *res;
|
|
|
|
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
l = PyObject_IsTrue(arg);
|
2010-05-07 19:33:49 +02:00
|
|
|
if (l == 0) {
|
|
|
|
res = Py_False;
|
|
|
|
} else if (l == 1) {
|
|
|
|
res = Py_True;
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
to_str(PyObject *self, PyObject *arg)
|
|
|
|
{
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
|
|
|
return PyObject_Str(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
to_float(PyObject *self, PyObject *arg)
|
|
|
|
{
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
|
|
|
return PyNumber_Float(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
str_to_datetime(PyObject *self, PyObject *arg)
|
|
|
|
{
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
PyObject *bytes;
|
|
|
|
PyObject *err_bytes;
|
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
const char *str;
|
2017-04-15 18:33:29 +02:00
|
|
|
int numparsed;
|
2010-05-07 19:33:49 +02:00
|
|
|
unsigned int year, month, day, hour, minute, second, microsecond = 0;
|
2017-04-15 18:33:29 +02:00
|
|
|
PyObject *err_repr;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
bytes = PyUnicode_AsASCIIString(arg);
|
|
|
|
if (bytes == NULL)
|
|
|
|
str = NULL;
|
|
|
|
else
|
|
|
|
str = PyBytes_AS_STRING(bytes);
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
str = PyString_AsString(arg);
|
2017-04-15 18:33:29 +02:00
|
|
|
#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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
2017-04-15 18:33:29 +02:00
|
|
|
}
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
/* microseconds are optional */
|
|
|
|
/*
|
|
|
|
TODO: this is slightly less picky than the Python version which would
|
|
|
|
not accept "2000-01-01 00:00:00.". I don't know which is better, but they
|
|
|
|
should be coherent.
|
|
|
|
*/
|
2017-04-15 18:33:29 +02:00
|
|
|
numparsed = sscanf(str, "%4u-%2u-%2u %2u:%2u:%2u.%6u", &year, &month, &day,
|
|
|
|
&hour, &minute, &second, µsecond);
|
|
|
|
#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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return PyDateTime_FromDateAndTime(year, month, day,
|
|
|
|
hour, minute, second, microsecond);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
str_to_time(PyObject *self, PyObject *arg)
|
|
|
|
{
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
PyObject *bytes;
|
|
|
|
PyObject *err_bytes;
|
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
const char *str;
|
2017-04-15 18:33:29 +02:00
|
|
|
int numparsed;
|
2010-05-07 19:33:49 +02:00
|
|
|
unsigned int hour, minute, second, microsecond = 0;
|
2017-04-15 18:33:29 +02:00
|
|
|
PyObject *err_repr;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
bytes = PyUnicode_AsASCIIString(arg);
|
|
|
|
if (bytes == NULL)
|
|
|
|
str = NULL;
|
|
|
|
else
|
|
|
|
str = PyBytes_AS_STRING(bytes);
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
str = PyString_AsString(arg);
|
2017-04-15 18:33:29 +02:00
|
|
|
#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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
2017-04-15 18:33:29 +02:00
|
|
|
}
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
/* microseconds are optional */
|
|
|
|
/*
|
|
|
|
TODO: this is slightly less picky than the Python version which would
|
|
|
|
not accept "00:00:00.". I don't know which is better, but they should be
|
|
|
|
coherent.
|
|
|
|
*/
|
2017-04-15 18:33:29 +02:00
|
|
|
numparsed = sscanf(str, "%2u:%2u:%2u.%6u", &hour, &minute, &second,
|
|
|
|
µsecond);
|
|
|
|
#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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return PyTime_FromTime(hour, minute, second, microsecond);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
str_to_date(PyObject *self, PyObject *arg)
|
|
|
|
{
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
PyObject *bytes;
|
|
|
|
PyObject *err_bytes;
|
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
const char *str;
|
2017-04-15 18:33:29 +02:00
|
|
|
int numparsed;
|
2010-05-07 19:33:49 +02:00
|
|
|
unsigned int year, month, day;
|
2017-04-15 18:33:29 +02:00
|
|
|
PyObject *err_repr;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
if (arg == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
bytes = PyUnicode_AsASCIIString(arg);
|
|
|
|
if (bytes == NULL)
|
|
|
|
str = NULL;
|
|
|
|
else
|
|
|
|
str = PyBytes_AS_STRING(bytes);
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
str = PyString_AsString(arg);
|
2017-04-15 18:33:29 +02:00
|
|
|
#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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
2017-04-15 18:33:29 +02:00
|
|
|
}
|
2010-05-07 19:33:49 +02:00
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
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);
|
2010-05-07 19:33:49 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return PyDate_FromDate(year, month, day);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********
|
|
|
|
* Structs *
|
|
|
|
***********/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PyObject_HEAD
|
|
|
|
PyObject *encoding;
|
|
|
|
PyObject *errors;
|
|
|
|
} UnicodeResultProcessor;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
PyObject_HEAD
|
|
|
|
PyObject *type;
|
|
|
|
PyObject *format;
|
|
|
|
} DecimalResultProcessor;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* UnicodeResultProcessor *
|
|
|
|
**************************/
|
|
|
|
|
|
|
|
static int
|
|
|
|
UnicodeResultProcessor_init(UnicodeResultProcessor *self, PyObject *args,
|
|
|
|
PyObject *kwds)
|
|
|
|
{
|
|
|
|
PyObject *encoding, *errors = NULL;
|
|
|
|
static char *kwlist[] = {"encoding", "errors", NULL};
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|U:__init__", kwlist,
|
|
|
|
&encoding, &errors))
|
|
|
|
return -1;
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|S:__init__", kwlist,
|
|
|
|
&encoding, &errors))
|
|
|
|
return -1;
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
encoding = PyUnicode_AsASCIIString(encoding);
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
Py_INCREF(encoding);
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
self->encoding = encoding;
|
|
|
|
|
|
|
|
if (errors) {
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
errors = PyUnicode_AsASCIIString(errors);
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
Py_INCREF(errors);
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
} else {
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
errors = PyBytes_FromString("strict");
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
errors = PyString_FromString("strict");
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
if (errors == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
self->errors = errors;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
UnicodeResultProcessor_process(UnicodeResultProcessor *self, PyObject *value)
|
|
|
|
{
|
|
|
|
const char *encoding, *errors;
|
|
|
|
char *str;
|
|
|
|
Py_ssize_t len;
|
|
|
|
|
|
|
|
if (value == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
if (PyString_AsStringAndSize(value, &str, &len))
|
|
|
|
return NULL;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
encoding = PyString_AS_STRING(self->encoding);
|
|
|
|
errors = PyString_AS_STRING(self->errors);
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
return PyUnicode_Decode(str, len, encoding, errors);
|
|
|
|
}
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
static void
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
static PyMethodDef UnicodeResultProcessor_methods[] = {
|
|
|
|
{"process", (PyCFunction)UnicodeResultProcessor_process, METH_O,
|
|
|
|
"The value processor itself."},
|
2017-04-15 18:33:29 +02:00
|
|
|
{"conditional_process", (PyCFunction)UnicodeResultProcessor_conditional_process, METH_O,
|
|
|
|
"Conditional version of the value processor."},
|
2010-05-07 19:33:49 +02:00
|
|
|
{NULL} /* Sentinel */
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyTypeObject UnicodeResultProcessorType = {
|
2017-04-15 18:33:29 +02:00
|
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
2010-05-07 19:33:49 +02:00
|
|
|
"sqlalchemy.cprocessors.UnicodeResultProcessor", /* tp_name */
|
|
|
|
sizeof(UnicodeResultProcessor), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
2017-04-15 18:33:29 +02:00
|
|
|
(destructor)UnicodeResultProcessor_dealloc, /* tp_dealloc */
|
2010-05-07 19:33:49 +02:00
|
|
|
0, /* tp_print */
|
|
|
|
0, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_compare */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
0, /* tp_as_sequence */
|
|
|
|
0, /* tp_as_mapping */
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
0, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
|
|
"UnicodeResultProcessor objects", /* tp_doc */
|
|
|
|
0, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
0, /* tp_iter */
|
|
|
|
0, /* tp_iternext */
|
|
|
|
UnicodeResultProcessor_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
0, /* tp_getset */
|
|
|
|
0, /* tp_base */
|
|
|
|
0, /* tp_dict */
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)UnicodeResultProcessor_init, /* tp_init */
|
|
|
|
0, /* tp_alloc */
|
|
|
|
0, /* tp_new */
|
|
|
|
};
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* DecimalResultProcessor *
|
|
|
|
**************************/
|
|
|
|
|
|
|
|
static int
|
|
|
|
DecimalResultProcessor_init(DecimalResultProcessor *self, PyObject *args,
|
|
|
|
PyObject *kwds)
|
|
|
|
{
|
|
|
|
PyObject *type, *format;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
if (!PyArg_ParseTuple(args, "OU", &type, &format))
|
|
|
|
#else
|
2010-05-07 19:33:49 +02:00
|
|
|
if (!PyArg_ParseTuple(args, "OS", &type, &format))
|
2017-04-15 18:33:29 +02:00
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
Py_INCREF(type);
|
|
|
|
self->type = type;
|
|
|
|
|
|
|
|
Py_INCREF(format);
|
|
|
|
self->format = format;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
DecimalResultProcessor_process(DecimalResultProcessor *self, PyObject *value)
|
|
|
|
{
|
|
|
|
PyObject *str, *result, *args;
|
|
|
|
|
|
|
|
if (value == Py_None)
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
/* 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 */
|
2010-05-07 19:33:49 +02:00
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
args = PyTuple_Pack(1, value);
|
|
|
|
if (args == NULL)
|
|
|
|
return NULL;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#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;
|
|
|
|
|
|
|
|
result = PyObject_CallFunctionObjArgs(self->type, str, NULL);
|
|
|
|
Py_DECREF(str);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
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
|
2010-05-07 19:33:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static PyMethodDef DecimalResultProcessor_methods[] = {
|
|
|
|
{"process", (PyCFunction)DecimalResultProcessor_process, METH_O,
|
|
|
|
"The value processor itself."},
|
|
|
|
{NULL} /* Sentinel */
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyTypeObject DecimalResultProcessorType = {
|
2017-04-15 18:33:29 +02:00
|
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
2010-05-07 19:33:49 +02:00
|
|
|
"sqlalchemy.DecimalResultProcessor", /* tp_name */
|
|
|
|
sizeof(DecimalResultProcessor), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
2017-04-15 18:33:29 +02:00
|
|
|
(destructor)DecimalResultProcessor_dealloc, /* tp_dealloc */
|
2010-05-07 19:33:49 +02:00
|
|
|
0, /* tp_print */
|
|
|
|
0, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_compare */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
0, /* tp_as_sequence */
|
|
|
|
0, /* tp_as_mapping */
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
0, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
|
|
"DecimalResultProcessor objects", /* tp_doc */
|
|
|
|
0, /* tp_traverse */
|
|
|
|
0, /* tp_clear */
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
0, /* tp_iter */
|
|
|
|
0, /* tp_iternext */
|
|
|
|
DecimalResultProcessor_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
0, /* tp_getset */
|
|
|
|
0, /* tp_base */
|
|
|
|
0, /* tp_dict */
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)DecimalResultProcessor_init, /* tp_init */
|
|
|
|
0, /* tp_alloc */
|
|
|
|
0, /* tp_new */
|
|
|
|
};
|
|
|
|
|
|
|
|
static PyMethodDef module_methods[] = {
|
|
|
|
{"int_to_boolean", int_to_boolean, METH_O,
|
|
|
|
"Convert an integer to a boolean."},
|
|
|
|
{"to_str", to_str, METH_O,
|
|
|
|
"Convert any value to its string representation."},
|
|
|
|
{"to_float", to_float, METH_O,
|
|
|
|
"Convert any value to its floating point representation."},
|
|
|
|
{"str_to_datetime", str_to_datetime, METH_O,
|
|
|
|
"Convert an ISO string to a datetime.datetime object."},
|
|
|
|
{"str_to_time", str_to_time, METH_O,
|
|
|
|
"Convert an ISO string to a datetime.time object."},
|
|
|
|
{"str_to_date", str_to_date, METH_O,
|
|
|
|
"Convert an ISO string to a datetime.date object."},
|
|
|
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
|
|
|
};
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#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
|
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
PyMODINIT_FUNC
|
|
|
|
initcprocessors(void)
|
2017-04-15 18:33:29 +02:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-05-07 19:33:49 +02:00
|
|
|
{
|
|
|
|
PyObject *m;
|
|
|
|
|
|
|
|
UnicodeResultProcessorType.tp_new = PyType_GenericNew;
|
|
|
|
if (PyType_Ready(&UnicodeResultProcessorType) < 0)
|
2017-04-15 18:33:29 +02:00
|
|
|
INITERROR;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
DecimalResultProcessorType.tp_new = PyType_GenericNew;
|
|
|
|
if (PyType_Ready(&DecimalResultProcessorType) < 0)
|
2017-04-15 18:33:29 +02:00
|
|
|
INITERROR;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
m = PyModule_Create(&module_def);
|
|
|
|
#else
|
|
|
|
m = Py_InitModule3(MODULE_NAME, module_methods, MODULE_DOC);
|
|
|
|
#endif
|
2010-05-07 19:33:49 +02:00
|
|
|
if (m == NULL)
|
2017-04-15 18:33:29 +02:00
|
|
|
INITERROR;
|
2010-05-07 19:33:49 +02:00
|
|
|
|
|
|
|
PyDateTime_IMPORT;
|
|
|
|
|
|
|
|
Py_INCREF(&UnicodeResultProcessorType);
|
|
|
|
PyModule_AddObject(m, "UnicodeResultProcessor",
|
|
|
|
(PyObject *)&UnicodeResultProcessorType);
|
|
|
|
|
|
|
|
Py_INCREF(&DecimalResultProcessorType);
|
|
|
|
PyModule_AddObject(m, "DecimalResultProcessor",
|
|
|
|
(PyObject *)&DecimalResultProcessorType);
|
|
|
|
|
2017-04-15 18:33:29 +02:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
return m;
|
|
|
|
#endif
|
|
|
|
}
|