Skip to content

Commit 6e4e845

Browse files
committedSep 21, 2016
pyspatialite: port to python3
1 parent 724ea44 commit 6e4e845

File tree

12 files changed

+807
-469
lines changed

12 files changed

+807
-469
lines changed
 

‎python/ext-libs/pyspatialite/src/cache.c

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
* 3. This notice may not be removed or altered from any source distribution.
2222
*/
2323

24-
#include "sqlitecompat.h"
2524
#include "cache.h"
2625
#include <limits.h>
2726

@@ -217,8 +216,6 @@ PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args)
217216
pysqlite_Node* ptr;
218217
PyObject* prevkey;
219218
PyObject* nextkey;
220-
PyObject* fmt_args;
221-
PyObject* template;
222219
PyObject* display_str;
223220

224221
ptr = self->first;
@@ -229,36 +226,21 @@ PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args)
229226
} else {
230227
prevkey = Py_None;
231228
}
232-
Py_INCREF(prevkey);
233229

234230
if (ptr->next) {
235231
nextkey = ptr->next->key;
236232
} else {
237233
nextkey = Py_None;
238234
}
239-
Py_INCREF(nextkey);
240235

241-
fmt_args = Py_BuildValue("OOO", prevkey, ptr->key, nextkey);
242-
if (!fmt_args) {
243-
return NULL;
244-
}
245-
template = PyString_FromString("%s <- %s ->%s\n");
246-
if (!template) {
247-
Py_DECREF(fmt_args);
248-
return NULL;
249-
}
250-
display_str = PyString_Format(template, fmt_args);
251-
Py_DECREF(template);
252-
Py_DECREF(fmt_args);
236+
display_str = PyUnicode_FromFormat("%S <- %S -> %S\n",
237+
prevkey, ptr->key, nextkey);
253238
if (!display_str) {
254239
return NULL;
255240
}
256241
PyObject_Print(display_str, stdout, Py_PRINT_RAW);
257242
Py_DECREF(display_str);
258243

259-
Py_DECREF(prevkey);
260-
Py_DECREF(nextkey);
261-
262244
ptr = ptr->next;
263245
}
264246

@@ -283,7 +265,7 @@ PyTypeObject pysqlite_NodeType = {
283265
0, /* tp_print */
284266
0, /* tp_getattr */
285267
0, /* tp_setattr */
286-
0, /* tp_compare */
268+
0, /* tp_reserved */
287269
0, /* tp_repr */
288270
0, /* tp_as_number */
289271
0, /* tp_as_sequence */
@@ -325,7 +307,7 @@ PyTypeObject pysqlite_CacheType = {
325307
0, /* tp_print */
326308
0, /* tp_getattr */
327309
0, /* tp_setattr */
328-
0, /* tp_compare */
310+
0, /* tp_reserved */
329311
0, /* tp_repr */
330312
0, /* tp_as_number */
331313
0, /* tp_as_sequence */

‎python/ext-libs/pyspatialite/src/connection.c

Lines changed: 346 additions & 186 deletions
Large diffs are not rendered by default.

‎python/ext-libs/pyspatialite/src/connection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ typedef struct
3737
{
3838
PyObject_HEAD
3939
sqlite3* db;
40+
#if defined(SPATIALITE_HAS_INIT_EX)
4041
void *slconn;
42+
#endif
4143

4244
/* 1 if we are currently within a transaction, i. e. if a BEGIN has been
4345
* issued */

‎python/ext-libs/pyspatialite/src/cursor.c

Lines changed: 140 additions & 136 deletions
Large diffs are not rendered by default.

‎python/ext-libs/pyspatialite/src/cursor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ typedef struct
4242
pysqlite_Statement* statement;
4343
int closed;
4444
int reset;
45+
int locked;
4546
int initialized;
4647

4748
/* the next row to be returned, NULL if no next row available */

‎python/ext-libs/pyspatialite/src/microprotocols.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,13 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
9595

9696
/* try to have the protocol adapt this object*/
9797
if (PyObject_HasAttrString(proto, "__adapt__")) {
98+
#if PY_MAJOR_VERSION < 3
9899
PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj);
100+
#else
101+
_Py_IDENTIFIER(__adapt__);
102+
PyObject *adapted = _PyObject_CallMethodId(proto, &PyId___adapt__, "O", obj);
103+
#endif
104+
99105
if (adapted) {
100106
if (adapted != Py_None) {
101107
return adapted;
@@ -110,7 +116,13 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
110116

111117
/* and finally try to have the object adapt itself */
112118
if (PyObject_HasAttrString(obj, "__conform__")) {
119+
#if PY_MAJOR_VERSION < 3
113120
PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
121+
#else
122+
_Py_IDENTIFIER(__conform__);
123+
PyObject *adapted = _PyObject_CallMethodId(obj, &PyId___conform__,"O", proto);
124+
#endif
125+
114126
if (adapted) {
115127
if (adapted != Py_None) {
116128
return adapted;

‎python/ext-libs/pyspatialite/src/module.c

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError,
3939
*pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError,
40-
*pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError, *pysqlite_OptimizedUnicode;
40+
*pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError;
4141

4242
PyObject* converters;
4343
int _enable_callback_tracebacks;
@@ -50,21 +50,28 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
5050
* C-level, so this code is redundant with the one in connection_init in
5151
* connection.c and must always be copied from there ... */
5252

53-
static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
54-
PyObject* database;
53+
static char *kwlist[] = {
54+
"database", "timeout", "detect_types", "isolation_level",
55+
"check_same_thread", "factory", "cached_statements", "uri",
56+
NULL
57+
};
58+
char* database;
5559
int detect_types = 0;
5660
PyObject* isolation_level;
5761
PyObject* factory = NULL;
5862
int check_same_thread = 1;
5963
int cached_statements;
64+
int uri = 0;
6065
double timeout = 5.0;
6166

6267
PyObject* result;
6368

64-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOi", kwlist,
65-
&database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
69+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
70+
&database, &timeout, &detect_types,
71+
&isolation_level, &check_same_thread,
72+
&factory, &cached_statements, &uri))
6673
{
67-
return NULL;
74+
return NULL;
6875
}
6976

7077
if (factory == NULL) {
@@ -77,7 +84,8 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
7784
}
7885

7986
PyDoc_STRVAR(module_connect_doc,
80-
"connect(database[, timeout, isolation_level, detect_types, factory])\n\
87+
"connect(database[, timeout, detect_types, isolation_level,\n\
88+
check_same_thread, factory, cached_statements, uri])\n\
8189
\n\
8290
Opens a connection to the SQLite database file *database*. You can use\n\
8391
\":memory:\" to open a database connection to a database that resides in\n\
@@ -93,7 +101,7 @@ static PyObject* module_complete(PyObject* self, PyObject* args, PyObject*
93101

94102
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement))
95103
{
96-
return NULL;
104+
return NULL;
97105
}
98106

99107
if (sqlite3_complete(statement)) {
@@ -122,7 +130,7 @@ static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyOb
122130

123131
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable))
124132
{
125-
return NULL;
133+
return NULL;
126134
}
127135

128136
rc = sqlite3_enable_shared_cache(do_enable);
@@ -155,8 +163,8 @@ static PyObject* module_register_adapter(PyObject* self, PyObject* args)
155163

156164
/* a basic type is adapted; there's a performance optimization if that's not the case
157165
* (99 % of all usages) */
158-
if (type == &PyInt_Type || type == &PyLong_Type || type == &PyFloat_Type
159-
|| type == &PyString_Type || type == &PyUnicode_Type || type == &PyBuffer_Type) {
166+
if (type == &PyLong_Type || type == &PyFloat_Type
167+
|| type == &PyUnicode_Type || type == &PyByteArray_Type) {
160168
pysqlite_BaseTypeAdapted = 1;
161169
}
162170

@@ -179,13 +187,20 @@ static PyObject* module_register_converter(PyObject* self, PyObject* args)
179187
PyObject* name = NULL;
180188
PyObject* callable;
181189
PyObject* retval = NULL;
190+
#if PY_MAJOR_VERSION >= 3
191+
_Py_IDENTIFIER(upper);
192+
#endif
182193

183-
if (!PyArg_ParseTuple(args, "SO", &orig_name, &callable)) {
194+
if (!PyArg_ParseTuple(args, "UO", &orig_name, &callable)) {
184195
return NULL;
185196
}
186197

187198
/* convert the name to upper case */
199+
#if PY_MAJOR_VERSION < 3
188200
name = PyObject_CallMethod(orig_name, "upper", "");
201+
#else
202+
name = _PyObject_CallMethodId(orig_name, &PyId_upper, "");
203+
#endif
189204
if (!name) {
190205
goto error;
191206
}
@@ -300,13 +315,31 @@ static IntConstantPair _int_constants[] = {
300315
{(char*)NULL, 0}
301316
};
302317

318+
#if PY_MAJOR_VERSION >= 3
319+
static struct PyModuleDef _sqlite3module = {
320+
PyModuleDef_HEAD_INIT,
321+
"_spatialite",
322+
NULL,
323+
-1,
324+
module_methods,
325+
NULL,
326+
NULL,
327+
NULL,
328+
NULL
329+
};
330+
#endif
331+
303332
PyMODINIT_FUNC init_spatialite(void)
304333
{
305334
PyObject *module, *dict;
306335
PyObject *tmp_obj;
307336
int i;
308337

338+
#if PY_MAJOR_VERSION < 3
309339
module = Py_InitModule("pyspatialite._spatialite", module_methods);
340+
#else
341+
module = PyModule_Create(&_sqlite3module);
342+
#endif
310343

311344
if (!module ||
312345
(pysqlite_row_setup_types() < 0) ||
@@ -316,7 +349,8 @@ PyMODINIT_FUNC init_spatialite(void)
316349
(pysqlite_statement_setup_types() < 0) ||
317350
(pysqlite_prepare_protocol_setup_types() < 0)
318351
) {
319-
return;
352+
Py_XDECREF(module);
353+
return NULL;
320354
}
321355

322356
Py_INCREF(&pysqlite_ConnectionType);
@@ -338,12 +372,12 @@ PyMODINIT_FUNC init_spatialite(void)
338372

339373
/*** Create DB-API Exception hierarchy */
340374

341-
if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_StandardError, NULL))) {
375+
if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_Exception, NULL))) {
342376
goto error;
343377
}
344378
PyDict_SetItemString(dict, "Error", pysqlite_Error);
345379

346-
if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_StandardError, NULL))) {
380+
if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_Exception, NULL))) {
347381
goto error;
348382
}
349383
PyDict_SetItemString(dict, "Warning", pysqlite_Warning);
@@ -392,31 +426,31 @@ PyMODINIT_FUNC init_spatialite(void)
392426
}
393427
PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError);
394428

395-
/* We just need "something" unique for pysqlite_OptimizedUnicode. It does not really
396-
* need to be a string subclass. Just anything that can act as a special
397-
* marker for us. So I pulled PyCell_Type out of my magic hat.
398-
*/
399-
Py_INCREF((PyObject*)&PyCell_Type);
400-
pysqlite_OptimizedUnicode = (PyObject*)&PyCell_Type;
401-
PyDict_SetItemString(dict, "OptimizedUnicode", pysqlite_OptimizedUnicode);
429+
/* In Python 2.x, setting Connection.text_factory to
430+
OptimizedUnicode caused Unicode objects to be returned for
431+
non-ASCII data and bytestrings to be returned for ASCII data.
432+
Now OptimizedUnicode is an alias for str, so it has no
433+
effect. */
434+
Py_INCREF((PyObject*)&PyUnicode_Type);
435+
PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type);
402436

403437
/* Set integer constants */
404438
for (i = 0; _int_constants[i].constant_name != 0; i++) {
405-
tmp_obj = PyInt_FromLong(_int_constants[i].constant_value);
439+
tmp_obj = PyLong_FromLong(_int_constants[i].constant_value);
406440
if (!tmp_obj) {
407441
goto error;
408442
}
409443
PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj);
410444
Py_DECREF(tmp_obj);
411445
}
412446

413-
if (!(tmp_obj = PyString_FromString(PYSPATIALITE_VERSION))) {
447+
if (!(tmp_obj = PyUnicode_FromString(PYSPATIALITE_VERSION))) {
414448
goto error;
415449
}
416450
PyDict_SetItemString(dict, "version", tmp_obj);
417451
Py_DECREF(tmp_obj);
418452

419-
if (!(tmp_obj = PyString_FromString(sqlite3_libversion()))) {
453+
if (!(tmp_obj = PyUnicode_FromString(sqlite3_libversion()))) {
420454
goto error;
421455
}
422456
PyDict_SetItemString(dict, "sqlite_version", tmp_obj);
@@ -434,7 +468,7 @@ PyMODINIT_FUNC init_spatialite(void)
434468

435469
/* Original comment from _bsddb.c in the Python core. This is also still
436470
* needed nowadays for Python 2.3/2.4.
437-
*
471+
*
438472
* PyEval_InitThreads is called here due to a quirk in python 1.5
439473
* - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
440474
* The global interpreter lock is not initialized until the first
@@ -452,6 +486,9 @@ PyMODINIT_FUNC init_spatialite(void)
452486
error:
453487
if (PyErr_Occurred())
454488
{
455-
PyErr_SetString(PyExc_ImportError, "pyspatialite._spatialite: init failed");
489+
PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed");
490+
Py_DECREF(module);
491+
module = NULL;
456492
}
493+
return module;
457494
}

‎python/ext-libs/pyspatialite/src/prepare_protocol.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
* 3. This notice may not be removed or altered from any source distribution.
2222
*/
2323

24-
#include "sqlitecompat.h"
2524
#include "prepare_protocol.h"
2625

2726
int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs)
@@ -43,7 +42,7 @@ PyTypeObject pysqlite_PrepareProtocolType= {
4342
0, /* tp_print */
4443
0, /* tp_getattr */
4544
0, /* tp_setattr */
46-
0, /* tp_compare */
45+
0, /* tp_reserved */
4746
0, /* tp_repr */
4847
0, /* tp_as_number */
4948
0, /* tp_as_sequence */

‎python/ext-libs/pyspatialite/src/row.c

Lines changed: 73 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include "row.h"
2525
#include "cursor.h"
26-
#include "sqlitecompat.h"
2726

2827
void pysqlite_row_dealloc(pysqlite_Row* self)
2928
{
@@ -33,66 +32,92 @@ void pysqlite_row_dealloc(pysqlite_Row* self)
3332
Py_TYPE(self)->tp_free((PyObject*)self);
3433
}
3534

36-
int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
35+
static PyObject *
36+
pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3737
{
38+
pysqlite_Row *self;
3839
PyObject* data;
3940
pysqlite_Cursor* cursor;
4041

41-
self->data = 0;
42-
self->description = 0;
42+
assert(type != NULL && type->tp_alloc != NULL);
4343

44-
if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) {
45-
return -1;
46-
}
44+
if (!_PyArg_NoKeywords("Row()", kwargs))
45+
return NULL;
46+
if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
47+
return NULL;
4748

48-
if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) {
49+
if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) {
4950
PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
50-
return -1;
51+
return NULL;
5152
}
5253

5354
if (!PyTuple_Check(data)) {
5455
PyErr_SetString(PyExc_TypeError, "tuple required for second argument");
55-
return -1;
56+
return NULL;
5657
}
5758

59+
self = (pysqlite_Row *) type->tp_alloc(type, 0);
60+
if (self == NULL)
61+
return NULL;
62+
5863
Py_INCREF(data);
5964
self->data = data;
6065

6166
Py_INCREF(cursor->description);
6267
self->description = cursor->description;
6368

64-
return 0;
69+
return (PyObject *) self;
70+
}
71+
72+
PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx)
73+
{
74+
PyObject* item = PyTuple_GetItem(self->data, idx);
75+
Py_XINCREF(item);
76+
return item;
6577
}
6678

6779
PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
6880
{
69-
long _idx;
81+
Py_ssize_t _idx;
7082
char* key;
71-
int nitems, i;
83+
Py_ssize_t nitems, i;
7284
char* compare_key;
7385

7486
char* p1;
7587
char* p2;
7688

7789
PyObject* item;
7890

79-
if (PyInt_Check(idx)) {
80-
_idx = PyInt_AsLong(idx);
81-
item = PyTuple_GetItem(self->data, _idx);
82-
Py_XINCREF(item);
83-
return item;
84-
} else if (PyLong_Check(idx)) {
85-
_idx = PyLong_AsLong(idx);
91+
if (PyLong_Check(idx)) {
92+
_idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
93+
if (_idx == -1 && PyErr_Occurred())
94+
return NULL;
95+
if (_idx < 0)
96+
_idx += PyTuple_GET_SIZE(self->data);
8697
item = PyTuple_GetItem(self->data, _idx);
8798
Py_XINCREF(item);
8899
return item;
100+
#if PY_MAJOR_VERSION < 3
89101
} else if (PyString_Check(idx)) {
90102
key = PyString_AsString(idx);
103+
#else
104+
} else if (PyUnicode_Check(idx)) {
105+
key = _PyUnicode_AsString(idx);
106+
#endif
107+
if (key == NULL)
108+
return NULL;
91109

92110
nitems = PyTuple_Size(self->description);
93111

94112
for (i = 0; i < nitems; i++) {
95-
compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0));
113+
PyObject *obj;
114+
obj = PyTuple_GET_ITEM(self->description, i);
115+
obj = PyTuple_GET_ITEM(obj, 0);
116+
#if PY_MAJOR_VERSION < 3
117+
compare_key = PyString_AsString(obj);
118+
#else
119+
compare_key = _PyUnicode_AsString(obj);
120+
#endif
96121
if (!compare_key) {
97122
return NULL;
98123
}
@@ -125,8 +150,7 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
125150
PyErr_SetString(PyExc_IndexError, "No item with that key");
126151
return NULL;
127152
} else if (PySlice_Check(idx)) {
128-
PyErr_SetString(PyExc_ValueError, "slices not implemented, yet");
129-
return NULL;
153+
return PyObject_GetItem(self->data, idx);
130154
} else {
131155
PyErr_SetString(PyExc_IndexError, "Index must be int or string");
132156
return NULL;
@@ -141,7 +165,7 @@ Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwa
141165
PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
142166
{
143167
PyObject* list;
144-
int nitems, i;
168+
Py_ssize_t nitems, i;
145169

146170
list = PyList_New(0);
147171
if (!list) {
@@ -169,16 +193,24 @@ static PyObject* pysqlite_iter(pysqlite_Row* self)
169193
return PyObject_GetIter(self->data);
170194
}
171195

172-
static long pysqlite_row_hash(pysqlite_Row *self)
196+
#if PY_MAJOR_VERSION < 3
197+
#define Py_hash_t long
198+
#endif
199+
200+
static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
173201
{
174202
return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
175203
}
176204

177205
static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
178206
{
179207
if (opid != Py_EQ && opid != Py_NE) {
208+
#if PY_MAJOR_VERSION < 3
180209
Py_INCREF(Py_NotImplemented);
181210
return Py_NotImplemented;
211+
#else
212+
Py_RETURN_NOTIMPLEMENTED;
213+
#endif
182214
}
183215
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
184216
pysqlite_Row *other = (pysqlite_Row *)_other;
@@ -189,8 +221,12 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
189221
return PyObject_RichCompare(self->data, other->data, opid);
190222
}
191223
}
224+
#if PY_MAJOR_VERSION < 3
192225
Py_INCREF(Py_NotImplemented);
193226
return Py_NotImplemented;
227+
#else
228+
Py_RETURN_NOTIMPLEMENTED;
229+
#endif
194230
}
195231

196232
PyMappingMethods pysqlite_row_as_mapping = {
@@ -199,6 +235,14 @@ PyMappingMethods pysqlite_row_as_mapping = {
199235
/* mp_ass_subscript */ (objobjargproc)0,
200236
};
201237

238+
static PySequenceMethods pysqlite_row_as_sequence = {
239+
/* sq_length */ (lenfunc)pysqlite_row_length,
240+
/* sq_concat */ 0,
241+
/* sq_repeat */ 0,
242+
/* sq_item */ (ssizeargfunc)pysqlite_row_item,
243+
};
244+
245+
202246
static PyMethodDef pysqlite_row_methods[] = {
203247
{"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
204248
PyDoc_STR("Returns the keys of the row.")},
@@ -215,7 +259,7 @@ PyTypeObject pysqlite_RowType = {
215259
(printfunc)pysqlite_row_print, /* tp_print */
216260
0, /* tp_getattr */
217261
0, /* tp_setattr */
218-
0, /* tp_compare */
262+
0, /* tp_reserved */
219263
0, /* tp_repr */
220264
0, /* tp_as_number */
221265
0, /* tp_as_sequence */
@@ -242,15 +286,16 @@ PyTypeObject pysqlite_RowType = {
242286
0, /* tp_descr_get */
243287
0, /* tp_descr_set */
244288
0, /* tp_dictoffset */
245-
(initproc)pysqlite_row_init, /* tp_init */
289+
0, /* tp_init */
246290
0, /* tp_alloc */
247291
0, /* tp_new */
248292
0 /* tp_free */
249293
};
250294

251295
extern int pysqlite_row_setup_types(void)
252296
{
253-
pysqlite_RowType.tp_new = PyType_GenericNew;
297+
pysqlite_RowType.tp_new = pysqlite_row_new;
254298
pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping;
299+
pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence;
255300
return PyType_Ready(&pysqlite_RowType);
256301
}

‎python/ext-libs/pyspatialite/src/statement.c

Lines changed: 96 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "connection.h"
2727
#include "microprotocols.h"
2828
#include "prepare_protocol.h"
29-
#include "sqlitecompat.h"
29+
#include "util.h"
3030

3131
/* prototypes */
3232
static int pysqlite_check_remaining_sql(const char* tail);
@@ -41,10 +41,14 @@ typedef enum {
4141
} parse_remaining_sql_state;
4242

4343
typedef enum {
44+
#if PY_MAJOR_VERSION < 3
4445
TYPE_INT,
46+
#endif
4547
TYPE_LONG,
4648
TYPE_FLOAT,
49+
#if PY_MAJOR_VERSION < 3
4750
TYPE_STRING,
51+
#endif
4852
TYPE_UNICODE,
4953
TYPE_BUFFER,
5054
TYPE_UNKNOWN
@@ -54,30 +58,41 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
5458
{
5559
const char* tail;
5660
int rc;
57-
PyObject* sql_str;
58-
char* sql_cstr;
61+
Py_ssize_t sql_cstr_len;
62+
const char *sql_cstr;
5963

6064
self->st = NULL;
6165
self->in_use = 0;
6266

67+
#if PY_MAJOR_VERSION < 3
6368
if (PyString_Check(sql)) {
64-
sql_str = sql;
65-
Py_INCREF(sql_str);
69+
sql_cstr = PyString_AsString(sql);
6670
} else if (PyUnicode_Check(sql)) {
67-
sql_str = PyUnicode_AsUTF8String(sql);
68-
if (!sql_str) {
71+
sql = PyUnicode_AsUTF8String(sql);
72+
if (!sql) {
6973
rc = PYSQLITE_SQL_WRONG_TYPE;
7074
return rc;
7175
}
76+
sql_cstr = PyString_AsString(sql);
7277
} else {
7378
rc = PYSQLITE_SQL_WRONG_TYPE;
7479
return rc;
7580
}
81+
#else
82+
sql_cstr = _PyUnicode_AsString(sql);
83+
if (!sql_cstr) {
84+
rc = PYSQLITE_SQL_WRONG_TYPE;
85+
return rc;
86+
}
87+
#endif
88+
if (strlen(sql_cstr) != (size_t)sql_cstr_len) {

Comment on line R88

mhugo commented on Jul 4, 2017

@mhugo

@jef-n Hi. I am debugging qgis3's pyspatialite (see https://issues.qgis.org/issues/16720).
I am not sure to understand the original intent here.
sql_cstr_len is not initialized ...
Could xxx_AsString() functions return malformed C strings ?

jef-n replied on Jul 4, 2017

@jef-n
MemberAuthor

Um, been a while. This is the result of a "simple" merge between pysqlite from py2 to py3 and the changes between py2' pysqlite and pyspatialite - and I think master was still py2/3 back then. So hard to tell now.

mhugo replied on Jul 4, 2017

@mhugo

Ok. Thanks. I tried to comment out this part. It seems better, but crashes a bit further ...

Code has comments. Press enter to view.
89+
PyErr_SetString(PyExc_ValueError, "the query contains a null character");
90+
return PYSQLITE_SQL_WRONG_TYPE;
91+
}
7692

7793
self->in_weakreflist = NULL;
78-
self->sql = sql_str;
79-
80-
sql_cstr = PyString_AsString(sql_str);
94+
Py_INCREF(sql);
95+
self->sql = sql;
8196

8297
Py_BEGIN_ALLOW_THREADS
8398
rc = sqlite3_prepare(connection->db,
@@ -98,91 +113,96 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con
98113
return rc;
99114
}
100115

101-
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars)
116+
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter)
102117
{
103118
int rc = SQLITE_OK;
104-
long longval;
105-
PY_LONG_LONG longlongval;
106-
const char* buffer;
107119
char* string;
108120
Py_ssize_t buflen;
109-
PyObject* stringval;
110121
parameter_type paramtype;
111-
char* c;
112122

113123
if (parameter == Py_None) {
114124
rc = sqlite3_bind_null(self->st, pos);
115125
goto final;
116126
}
117127

118-
if (PyInt_CheckExact(parameter)) {
119-
paramtype = TYPE_INT;
120-
} else if (PyLong_CheckExact(parameter)) {
128+
if (PyLong_CheckExact(parameter)) {
121129
paramtype = TYPE_LONG;
122130
} else if (PyFloat_CheckExact(parameter)) {
123131
paramtype = TYPE_FLOAT;
124-
} else if (PyString_CheckExact(parameter)) {
125-
paramtype = TYPE_STRING;
126132
} else if (PyUnicode_CheckExact(parameter)) {
127133
paramtype = TYPE_UNICODE;
128-
} else if (PyBuffer_Check(parameter)) {
129-
paramtype = TYPE_BUFFER;
130-
} else if (PyInt_Check(parameter)) {
131-
paramtype = TYPE_INT;
132134
} else if (PyLong_Check(parameter)) {
133135
paramtype = TYPE_LONG;
134136
} else if (PyFloat_Check(parameter)) {
135137
paramtype = TYPE_FLOAT;
136-
} else if (PyString_Check(parameter)) {
137-
paramtype = TYPE_STRING;
138138
} else if (PyUnicode_Check(parameter)) {
139139
paramtype = TYPE_UNICODE;
140+
} else if (PyObject_CheckBuffer(parameter)) {
141+
paramtype = TYPE_BUFFER;
140142
} else {
141143
paramtype = TYPE_UNKNOWN;
142144
}
143145

144-
if (paramtype == TYPE_STRING && !allow_8bit_chars) {
145-
string = PyString_AS_STRING(parameter);
146-
for (c = string; *c != 0; c++) {
147-
if (*c & 0x80) {
148-
PyErr_SetString(pysqlite_ProgrammingError, "You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.");
149-
rc = -1;
150-
goto final;
151-
}
152-
}
153-
}
154-
155146
switch (paramtype) {
156-
case TYPE_INT:
157-
longval = PyInt_AsLong(parameter);
147+
#if PY_MAJOR_VERSION < 3
148+
case TYPE_INT: {
149+
long longval = PyInt_AsLong(parameter);
158150
rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval);
159151
break;
160-
case TYPE_LONG:
161-
longlongval = PyLong_AsLongLong(parameter);
162-
/* in the overflow error case, longlongval is -1, and an exception is set */
163-
rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval);
152+
}
153+
#endif
154+
case TYPE_LONG: {
155+
sqlite_int64 value = _pysqlite_long_as_int64(parameter);
156+
if (value == -1 && PyErr_Occurred())
157+
rc = -1;
158+
else
159+
rc = sqlite3_bind_int64(self->st, pos, value);
164160
break;
161+
}
165162
case TYPE_FLOAT:
166163
rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter));
167164
break;
165+
#if PY_MAJOR_VERSION < 3
168166
case TYPE_STRING:
169167
string = PyString_AS_STRING(parameter);
170168
rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
171169
break;
172-
case TYPE_UNICODE:
173-
stringval = PyUnicode_AsUTF8String(parameter);
170+
#endif
171+
case TYPE_UNICODE: {
172+
#if PY_MAJOR_VERSION < 3
173+
PyObject* stringval = PyUnicode_AsUTF8String(parameter);
174174
string = PyString_AsString(stringval);
175175
rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
176176
Py_DECREF(stringval);
177+
#else
178+
string = _PyUnicode_AsStringAndSize(parameter, &buflen);
179+
if (string == NULL)
180+
return -1;
181+
if (buflen > INT_MAX) {
182+
PyErr_SetString(PyExc_OverflowError,
183+
"string longer than INT_MAX bytes");
184+
return -1;
185+
}
186+
rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT);
187+
#endif
188+
}
177189
break;
178-
case TYPE_BUFFER:
179-
if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) {
180-
rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
181-
} else {
190+
case TYPE_BUFFER: {
191+
Py_buffer view;
192+
if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) {
182193
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
183-
rc = -1;
194+
return -1;
184195
}
196+
if (view.len > INT_MAX) {
197+
PyErr_SetString(PyExc_OverflowError,
198+
"BLOB longer than INT_MAX bytes");
199+
PyBuffer_Release(&view);
200+
return -1;
201+
}
202+
rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT);
203+
PyBuffer_Release(&view);
185204
break;
205+
}
186206
case TYPE_UNKNOWN:
187207
rc = -1;
188208
}
@@ -198,24 +218,23 @@ static int _need_adapt(PyObject* obj)
198218
return 1;
199219
}
200220

201-
if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)
202-
|| PyFloat_CheckExact(obj) || PyString_CheckExact(obj)
203-
|| PyUnicode_CheckExact(obj) || PyBuffer_Check(obj)) {
221+
if (PyLong_CheckExact(obj) || PyFloat_CheckExact(obj)
222+
|| PyUnicode_CheckExact(obj) || PyByteArray_CheckExact(obj)) {
204223
return 0;
205224
} else {
206225
return 1;
207226
}
208227
}
209228

210-
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars)
229+
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters)
211230
{
212231
PyObject* current_param;
213232
PyObject* adapted;
214233
const char* binding_name;
215234
int i;
216235
int rc;
217236
int num_params_needed;
218-
int num_params;
237+
Py_ssize_t num_params;
219238

220239
Py_BEGIN_ALLOW_THREADS
221240
num_params_needed = sqlite3_bind_parameter_count(self->st);
@@ -231,7 +250,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
231250
num_params = PySequence_Size(parameters);
232251
}
233252
if (num_params != num_params_needed) {
234-
PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.",
253+
PyErr_Format(pysqlite_ProgrammingError,
254+
"Incorrect number of bindings supplied. The current "
255+
"statement uses %d, and there are %zd supplied.",
235256
num_params_needed, num_params);
236257
return;
237258
}
@@ -261,7 +282,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
261282
}
262283
}
263284

264-
rc = pysqlite_statement_bind_parameter(self, i + 1, adapted, allow_8bit_chars);
285+
rc = pysqlite_statement_bind_parameter(self, i + 1, adapted);
265286
Py_DECREF(adapted);
266287

267288
if (rc != SQLITE_OK) {
@@ -287,7 +308,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
287308
current_param = PyDict_GetItemString(parameters, binding_name);
288309
Py_XINCREF(current_param);
289310
} else {
290-
current_param = PyMapping_GetItemString(parameters, (char*)binding_name);
311+
current_param = PyMapping_GetItemString(parameters, binding_name);
291312
}
292313
if (!current_param) {
293314
PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i);
@@ -306,7 +327,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
306327
}
307328
}
308329

309-
rc = pysqlite_statement_bind_parameter(self, i, adapted, allow_8bit_chars);
330+
rc = pysqlite_statement_bind_parameter(self, i, adapted);
310331
Py_DECREF(adapted);
311332

312333
if (rc != SQLITE_OK) {
@@ -325,10 +346,19 @@ int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params)
325346
{
326347
const char* tail;
327348
int rc;
328-
char* sql_cstr;
349+
const char* sql_cstr;
350+
Py_ssize_t sql_len;
329351
sqlite3_stmt* new_st;
330352

353+
#if PY_MAJOR_VERSION < 3
331354
sql_cstr = PyString_AsString(self->sql);
355+
#else
356+
sql_cstr = _PyUnicode_AsStringAndSize(self->sql, &sql_len);
357+
#endif
358+
if (sql_cstr == NULL) {
359+
rc = PYSQLITE_SQL_WRONG_TYPE;
360+
return rc;
361+
}
332362

333363
Py_BEGIN_ALLOW_THREADS
334364
rc = sqlite3_prepare(self->db,
@@ -405,11 +435,9 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self)
405435

406436
void pysqlite_statement_dealloc(pysqlite_Statement* self)
407437
{
408-
int rc;
409-
410438
if (self->st) {
411439
Py_BEGIN_ALLOW_THREADS
412-
rc = sqlite3_finalize(self->st);
440+
sqlite3_finalize(self->st);
413441
Py_END_ALLOW_THREADS
414442
}
415443

@@ -490,6 +518,8 @@ static int pysqlite_check_remaining_sql(const char* tail)
490518

491519
pos++;
492520
}
521+
522+
return 0;
493523
}
494524

495525
PyTypeObject pysqlite_StatementType = {
@@ -501,7 +531,7 @@ PyTypeObject pysqlite_StatementType = {
501531
0, /* tp_print */
502532
0, /* tp_getattr */
503533
0, /* tp_setattr */
504-
0, /* tp_compare */
534+
0, /* tp_reserved */
505535
0, /* tp_repr */
506536
0, /* tp_as_number */
507537
0, /* tp_as_sequence */
@@ -512,7 +542,7 @@ PyTypeObject pysqlite_StatementType = {
512542
0, /* tp_getattro */
513543
0, /* tp_setattro */
514544
0, /* tp_as_buffer */
515-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
545+
Py_TPFLAGS_DEFAULT, /* tp_flags */
516546
0, /* tp_doc */
517547
0, /* tp_traverse */
518548
0, /* tp_clear */

‎python/ext-libs/pyspatialite/src/statement.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ extern PyTypeObject pysqlite_StatementType;
4646
int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql);
4747
void pysqlite_statement_dealloc(pysqlite_Statement* self);
4848

49-
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars);
50-
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars);
49+
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter);
50+
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters);
5151

5252
int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters);
5353
int pysqlite_statement_finalize(pysqlite_Statement* self);

‎python/ext-libs/pyspatialite/src/util.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,69 @@ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st)
104104
return errorcode;
105105
}
106106

107+
#ifdef WORDS_BIGENDIAN
108+
# define IS_LITTLE_ENDIAN 0
109+
#else
110+
# define IS_LITTLE_ENDIAN 1
111+
#endif
112+
113+
PyObject *
114+
_pysqlite_long_from_int64(sqlite_int64 value)
115+
{
116+
#ifdef HAVE_LONG_LONG
117+
# if SIZEOF_LONG_LONG < 8
118+
if (value > PY_LLONG_MAX || value < PY_LLONG_MIN) {
119+
return _PyLong_FromByteArray(&value, sizeof(value),
120+
IS_LITTLE_ENDIAN, 1 /* signed */);
121+
}
122+
# endif
123+
# if SIZEOF_LONG < SIZEOF_LONG_LONG
124+
if (value > LONG_MAX || value < LONG_MIN)
125+
return PyLong_FromLongLong(value);
126+
# endif
127+
#else
128+
# if SIZEOF_LONG < 8
129+
if (value > LONG_MAX || value < LONG_MIN) {
130+
return _PyLong_FromByteArray(&value, sizeof(value),
131+
IS_LITTLE_ENDIAN, 1 /* signed */);
132+
}
133+
# endif
134+
#endif
135+
return PyLong_FromLong(Py_SAFE_DOWNCAST(value, sqlite_int64, long));
136+
}
137+
138+
sqlite_int64
139+
_pysqlite_long_as_int64(PyObject * py_val)
140+
{
141+
int overflow;
142+
#ifdef HAVE_LONG_LONG
143+
PY_LONG_LONG value = PyLong_AsLongLongAndOverflow(py_val, &overflow);
144+
#else
145+
long value = PyLong_AsLongAndOverflow(py_val, &overflow);
146+
#endif
147+
if (value == -1 && PyErr_Occurred())
148+
return -1;
149+
if (!overflow) {
150+
#ifdef HAVE_LONG_LONG
151+
# if SIZEOF_LONG_LONG > 8
152+
if (-0x8000000000000000LL <= value && value <= 0x7FFFFFFFFFFFFFFFLL)
153+
# endif
154+
#else
155+
# if SIZEOF_LONG > 8
156+
if (-0x8000000000000000L <= value && value <= 0x7FFFFFFFFFFFFFFFL)
157+
# endif
158+
#endif
159+
return value;
160+
}
161+
else if (sizeof(value) < sizeof(sqlite_int64)) {
162+
sqlite_int64 int64val;
163+
if (_PyLong_AsByteArray((PyLongObject *)py_val,
164+
(unsigned char *)&int64val, sizeof(int64val),
165+
IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) {
166+
return int64val;
167+
}
168+
}
169+
PyErr_SetString(PyExc_OverflowError,
170+
"Python int too large to convert to SQLite INTEGER");
171+
return -1;
172+
}

0 commit comments

Comments
 (0)
Please sign in to comment.