diff -ruN pysqlite-2.6.3-OLDER/doc/default.css pysqlite-2.6.3/doc/default.css --- pysqlite-2.6.3-OLDER/doc/default.css 1969-12-31 19:00:00.000000000 -0500 +++ pysqlite-2.6.3/doc/default.css 2013-10-18 04:32:34.000000000 -0400 @@ -0,0 +1,10 @@ +@import url(docutils.css); +@import url(silvercity.css); + +div.code-block{ +margin-left: 2em ; +margin-right: 2em ; +background-color: #eeeeee; +font-family: "Courier New", Courier, monospace; +font-size: 10pt; +} diff -ruN pysqlite-2.6.3-OLDER/doc/docutils.css pysqlite-2.6.3/doc/docutils.css --- pysqlite-2.6.3-OLDER/doc/docutils.css 1969-12-31 19:00:00.000000000 -0500 +++ pysqlite-2.6.3/doc/docutils.css 2013-10-18 04:32:34.000000000 -0400 @@ -0,0 +1,260 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:Date: $Date: 2005-04-25 22:24:49 +0200 (Mon, 25 Apr 2005) $ +:Version: $Revision: 3256 $ +:Copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +/* "! important" is used here to override other ``margin-top`` and + ``margin-bottom`` styles that are later in the stylesheet or + more specific. See http://www.w3.org/TR/CSS1#the-cascade */ +.first { + margin-top: 0 ! important } + +.last { + margin-bottom: 0 ! important } + +.hidden { + display: none } + +a.toc-backref { + text-decoration: none ; + color: black } + +blockquote.epigraph { + margin: 2em 5em ; } + +dl.docutils dd { + margin-bottom: 0.5em } + +/* Uncomment (and remove this text!) to get bold-faced definition list terms +dl.docutils dt { + font-weight: bold } +*/ + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.admonition, div.attention, div.caution, div.danger, div.error, +div.hint, div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.admonition p.admonition-title, div.hint p.admonition-title, +div.important p.admonition-title, div.note p.admonition-title, +div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +/* Uncomment (and remove this text!) to get reduced vertical space in + compound paragraphs. +div.compound .compound-first, div.compound .compound-middle { + margin-bottom: 0.5em } + +div.compound .compound-last, div.compound .compound-middle { + margin-top: 0.5em } +*/ + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.line-block { + display: block ; + margin-top: 1em ; + margin-bottom: 1em } + +div.line-block div.line-block { + margin-top: 0 ; + margin-bottom: 0 ; + margin-left: 1.5em } + +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr.docutils { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table.citation { + border-left: solid thin gray } + +table.docinfo { + margin: 2em 4em } + +table.docutils { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.footnote { + border-left: solid thin black } + +table.docutils td, table.docutils th, +table.docinfo td, table.docinfo th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +table.docutils th.field-name, table.docinfo th.docinfo-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap ; + padding-left: 0 } + +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, +h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { + font-size: 100% } + +tt.docutils { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } + +body { + background-color: #eeeeff; + font-family: Verdana, Arial, Helvetica, sans-serif; +} diff -ruN pysqlite-2.6.3-OLDER/lib/test/regression.py pysqlite-2.6.3/lib/test/regression.py --- pysqlite-2.6.3-OLDER/lib/test/regression.py 2010-03-04 07:36:28.000000000 -0500 +++ pysqlite-2.6.3/lib/test/regression.py 2013-10-18 04:32:34.000000000 -0400 @@ -259,6 +259,29 @@ self.assertRaises(TypeError, con.set_authorizer, var) self.assertRaises(TypeError, con.set_progress_handler, var) + def CheckRecursiveCursorUse(self): + """ + http://bugs.python.org/issue10811 + + Recursively using a cursor, such as when reusing it from a generator led to segfaults. + Now we catch recursive cursor usage and raise a ProgrammingError. + """ + con = sqlite.connect(":memory:") + + cur = con.cursor() + cur.execute("create table a (bar)") + cur.execute("create table b (baz)") + + def foo(): + cur.execute("insert into a (bar) values (?)", (1,)) + yield 1 + + try: + cur.executemany("insert into b (baz) values (?)", ((i,) for i in foo())) + self.fail("should have raised ProgrammingError") + except sqlite.ProgrammingError: + pass + def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") return unittest.TestSuite((regression_suite,)) diff -ruN pysqlite-2.6.3-OLDER/lib/test/types.py pysqlite-2.6.3/lib/test/types.py --- pysqlite-2.6.3-OLDER/lib/test/types.py 2010-03-04 11:09:40.000000000 -0500 +++ pysqlite-2.6.3/lib/test/types.py 2013-10-28 05:55:04.000000000 -0400 @@ -102,6 +102,16 @@ finally: self.con.text_factory = orig_text_factory + def CheckBinaryString(self): + bin_string = u"foo\x00bar" + self.cur.execute("select ?", (bin_string,)) + self.assertEqual(self.cur.fetchone()[0], bin_string) + + def CheckBinaryByteString(self): + bin_string = "bla\x00bla" + self.cur.execute("select ?", (bin_string,)) + self.assertEqual(self.cur.fetchone()[0], bin_string) + class DeclTypesTests(unittest.TestCase): class Foo: def __init__(self, _val): @@ -137,6 +147,7 @@ sqlite.converters["FOO"] = DeclTypesTests.Foo sqlite.converters["WRONG"] = lambda x: "WRONG" sqlite.converters["NUMBER"] = float + sqlite.converters["TEXT"] = str def tearDown(self): del sqlite.converters["FLOAT"] @@ -153,6 +164,19 @@ row = self.cur.fetchone() self.assertEqual(row[0], "foo") + def CheckTextEmptyString(self): + """ + Make sure that empty strings are converted to empty strings and not to None. + """ + self.cur.execute("insert into test(s) values (?)", ("",)) + self.cur.execute("insert into test(s) values (?)", (None,)) + self.cur.execute('select s as "s [TEXT]" from test') + row = self.cur.fetchone() + self.assertEqual(row[0], "") + row = self.cur.fetchone() + self.assertEqual(row[0], None) + + def CheckSmallInt(self): # default self.cur.execute("insert into test(i) values (?)", (42,)) diff -ruN pysqlite-2.6.3-OLDER/LICENSE pysqlite-2.6.3/LICENSE --- pysqlite-2.6.3-OLDER/LICENSE 2009-10-19 05:19:27.000000000 -0400 +++ pysqlite-2.6.3/LICENSE 2013-10-18 04:32:34.000000000 -0400 @@ -1,4 +1,4 @@ -Copyright (c) 2004-2007 Gerhard Häring +Copyright (c) 2004-2013 Gerhard Häring This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use diff -ruN pysqlite-2.6.3-OLDER/PKG-INFO pysqlite-2.6.3/PKG-INFO --- pysqlite-2.6.3-OLDER/PKG-INFO 2011-02-16 06:10:37.000000000 -0500 +++ pysqlite-2.6.3/PKG-INFO 2013-10-28 05:56:05.000000000 -0400 @@ -1,12 +1,11 @@ -Metadata-Version: 1.0 +Metadata-Version: 1.1 Name: pysqlite Version: 2.6.3 Summary: DB-API 2.0 interface for SQLite 3.x -Home-page: http://pysqlite.googlecode.com/ +Home-page: http://github.com/ghaering/pysqlite Author: Gerhard Haering Author-email: gh@ghaering.de License: zlib/libpng license -Download-URL: http://code.google.com/p/pysqlite/downloads/list Description: Python interface to SQLite 3 pysqlite is an interface to the SQLite 3.x embedded relational database engine. diff -ruN pysqlite-2.6.3-OLDER/setup.py pysqlite-2.6.3/setup.py --- pysqlite-2.6.3-OLDER/setup.py 2011-02-16 06:08:57.000000000 -0500 +++ pysqlite-2.6.3/setup.py 2013-10-28 05:55:54.000000000 -0400 @@ -1,7 +1,7 @@ #-*- coding: ISO-8859-1 -*- # setup.py: the distutils script # -# Copyright (C) 2004-2007 Gerhard Häring +# Copyright (C) 2004-2013 Gerhard Häring # # This file is part of pysqlite. # @@ -84,35 +84,6 @@ if rc != 0: print "Is sphinx installed? If not, try 'sudo easy_install sphinx'." -AMALGAMATION_ROOT = "amalgamation" - -def get_amalgamation(): - """Download the SQLite amalgamation if it isn't there, already.""" - if os.path.exists(AMALGAMATION_ROOT): - return - os.mkdir(AMALGAMATION_ROOT) - print "Downloading amalgation." - - # find out what's current amalgamation ZIP file - download_page = urllib.urlopen("http://sqlite.org/download.html").read() - pattern = re.compile("(sqlite-amalgamation.*?\.zip)") - download_file = pattern.findall(download_page)[0] - amalgamation_url = "http://sqlite.org/" + download_file - - # and download it - urllib.urlretrieve(amalgamation_url, "tmp.zip") - - zf = zipfile.ZipFile("tmp.zip") - files = ["sqlite3.c", "sqlite3.h"] - directory = zf.namelist()[0] - for fn in files: - print "Extracting", fn - outf = open(AMALGAMATION_ROOT + os.sep + fn, "wb") - outf.write(zf.read(directory + fn)) - outf.close() - zf.close() - os.unlink("tmp.zip") - class AmalgamationBuilder(build): description = "Build a statically built pysqlite using the amalgamtion." @@ -125,11 +96,9 @@ def build_extension(self, ext): if self.amalgamation: - get_amalgamation() ext.define_macros.append(("SQLITE_ENABLE_FTS3", "1")) # build with fulltext search enabled ext.define_macros.append(("SQLITE_ENABLE_RTREE", "1")) # build with fulltext search enabled - ext.sources.append(os.path.join(AMALGAMATION_ROOT, "sqlite3.c")) - ext.include_dirs.append(AMALGAMATION_ROOT) + ext.sources.append("sqlite3.c") build_ext.build_extension(self, ext) def __setattr__(self, k, v): @@ -173,8 +142,7 @@ author_email = "gh@ghaering.de", license = "zlib/libpng license", platforms = "ALL", - url = "http://pysqlite.googlecode.com/", - download_url = "http://code.google.com/p/pysqlite/downloads/list", + url = "http://github.com/ghaering/pysqlite", # Description of the modules and packages in the distribution package_dir = {"pysqlite2": "lib"}, diff -ruN pysqlite-2.6.3-OLDER/src/cursor.c pysqlite-2.6.3/src/cursor.c --- pysqlite-2.6.3-OLDER/src/cursor.c 2010-03-04 07:55:00.000000000 -0500 +++ pysqlite-2.6.3/src/cursor.c 2013-10-28 05:55:04.000000000 -0400 @@ -268,29 +268,26 @@ } } -PyObject* pysqlite_unicode_from_string(const char* val_str, int optimize) +static PyObject* pysqlite_unicode_from_string(const char* val_str, Py_ssize_t nbytes, int optimize) { - const char* check; int is_ascii = 0; + int i; if (optimize) { is_ascii = 1; - check = val_str; - while (*check) { - if (*check & 0x80) { + for (i = 0; i < nbytes; i++) { + if (val_str[i] & 0x80) { is_ascii = 0; break; } - - check++; } } if (is_ascii) { - return PyString_FromString(val_str); + return PyString_FromStringAndSize(val_str, nbytes); } else { - return PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL); + return PyUnicode_DecodeUTF8(val_str, nbytes, NULL); } } @@ -331,6 +328,8 @@ } for (i = 0; i < numcols; i++) { + nbytes = sqlite3_column_bytes(self->statement->st, i); + if (self->connection->detect_types) { converter = PyList_GetItem(self->row_cast_map, i); if (!converter) { @@ -341,20 +340,24 @@ } if (converter != Py_None) { - nbytes = sqlite3_column_bytes(self->statement->st, i); - val_str = (const char*)sqlite3_column_blob(self->statement->st, i); - if (!val_str) { + if (sqlite3_column_type(self->statement->st, i) == SQLITE_NULL) { Py_INCREF(Py_None); converted = Py_None; } else { - item = PyString_FromStringAndSize(val_str, nbytes); - if (!item) { - return NULL; - } - converted = PyObject_CallFunction(converter, "O", item); - Py_DECREF(item); - if (!converted) { - break; + val_str = (const char*)sqlite3_column_blob(self->statement->st, i); + if (!val_str) { + Py_INCREF(Py_None); + converted = Py_None; + } else { + item = PyString_FromStringAndSize(val_str, nbytes); + if (!item) { + return NULL; + } + converted = PyObject_CallFunction(converter, "O", item); + Py_DECREF(item); + if (!converted) { + break; + } } } } else { @@ -378,7 +381,7 @@ if ((self->connection->text_factory == (PyObject*)&PyUnicode_Type) || (self->connection->text_factory == pysqlite_OptimizedUnicode)) { - converted = pysqlite_unicode_from_string(val_str, + converted = pysqlite_unicode_from_string(val_str, nbytes, self->connection->text_factory == pysqlite_OptimizedUnicode ? 1 : 0); if (!converted) { @@ -391,7 +394,7 @@ PyErr_SetString(pysqlite_OperationalError, buf); } } else if (self->connection->text_factory == (PyObject*)&PyString_Type) { - converted = PyString_FromString(val_str); + converted = PyString_FromStringAndSize(val_str, nbytes); } else { converted = PyObject_CallFunction(self->connection->text_factory, "s", val_str); } @@ -441,9 +444,14 @@ if (cur->closed) { PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor."); return 0; - } else { - return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection); } + + if (cur->locked) { + PyErr_SetString(pysqlite_ProgrammingError, "Recursive use of cursors not allowed."); + return 0; + } + + return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection); } PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) @@ -466,9 +474,10 @@ int allow_8bit_chars; if (!check_cursor(self)) { - return NULL; + goto error; } + self->locked = 1; self->reset = 0; /* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */ @@ -481,12 +490,12 @@ if (multiple) { /* executemany() */ if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) { - return NULL; + goto error; } if (!PyString_Check(operation) && !PyUnicode_Check(operation)) { PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode"); - return NULL; + goto error; } if (PyIter_Check(second_argument)) { @@ -497,23 +506,23 @@ /* sequence */ parameters_iter = PyObject_GetIter(second_argument); if (!parameters_iter) { - return NULL; + goto error; } } } else { /* execute() */ if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) { - return NULL; + goto error; } if (!PyString_Check(operation) && !PyUnicode_Check(operation)) { PyErr_SetString(PyExc_ValueError, "operation parameter must be str or unicode"); - return NULL; + goto error; } parameters_list = PyList_New(0); if (!parameters_list) { - return NULL; + goto error; } if (second_argument == NULL) { @@ -759,7 +768,8 @@ * ROLLBACK could have happened */ #ifdef SQLITE_VERSION_NUMBER #if SQLITE_VERSION_NUMBER >= 3002002 - self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db); + if (self->connection && self->connection->db) + self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db); #endif #endif @@ -768,6 +778,8 @@ Py_XDECREF(parameters_iter); Py_XDECREF(parameters_list); + self->locked = 0; + if (PyErr_Occurred()) { self->rowcount = -1L; return NULL; diff -ruN pysqlite-2.6.3-OLDER/src/cursor.h pysqlite-2.6.3/src/cursor.h --- pysqlite-2.6.3-OLDER/src/cursor.h 2010-03-04 07:59:39.000000000 -0500 +++ pysqlite-2.6.3/src/cursor.h 2013-10-18 04:32:34.000000000 -0400 @@ -42,6 +42,7 @@ pysqlite_Statement* statement; int closed; int reset; + int locked; int initialized; /* the next row to be returned, NULL if no next row available */ diff -ruN pysqlite-2.6.3-OLDER/src/statement.c pysqlite-2.6.3/src/statement.c --- pysqlite-2.6.3-OLDER/src/statement.c 2010-03-04 09:56:48.000000000 -0500 +++ pysqlite-2.6.3/src/statement.c 2013-10-18 04:32:34.000000000 -0400 @@ -167,12 +167,14 @@ break; case TYPE_STRING: string = PyString_AS_STRING(parameter); - rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); + buflen = PyString_Size(parameter); + rc = sqlite3_bind_text(self->st, pos, string, buflen, SQLITE_TRANSIENT); break; case TYPE_UNICODE: stringval = PyUnicode_AsUTF8String(parameter); string = PyString_AsString(stringval); - rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); + buflen = PyString_Size(stringval); + rc = sqlite3_bind_text(self->st, pos, string, buflen, SQLITE_TRANSIENT); Py_DECREF(stringval); break; case TYPE_BUFFER: