Skip to content

Commit

Permalink
bpo-31843: sqlite3.connect() now accepts PathLike objects as database…
Browse files Browse the repository at this point in the history
… name (#4299)
  • Loading branch information
Phaqui authored and vstinner committed Nov 7, 2017
1 parent edb13ae commit a22a127
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 7 deletions.
13 changes: 10 additions & 3 deletions Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,13 @@ Module functions and constants

.. function:: connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri])

Opens a connection to the SQLite database file *database*. You can use
``":memory:"`` to open a database connection to a database that resides in RAM
instead of on disk.
Opens a connection to the SQLite database file *database*. By default returns a
:class:`Connection` object, unless a custom *factory* is given.

*database* is a :term:`path-like object` giving the pathname (absolute or
relative to the current working directory) of the database file to be opened.
You can use ``":memory:"`` to open a database connection to a database that
resides in RAM instead of on disk.

When a database is accessed by multiple connections, and one of the processes
modifies the database, the SQLite database is locked until that transaction is
Expand Down Expand Up @@ -223,6 +227,9 @@ Module functions and constants
.. versionchanged:: 3.4
Added the *uri* parameter.

.. versionchanged:: 3.7
*database* can now also be a :term:`path-like object`, not only a string.


.. function:: register_converter(typename, callable)

Expand Down
11 changes: 11 additions & 0 deletions Lib/sqlite3/test/dbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ def CheckInTransactionRO(self):
with self.assertRaises(AttributeError):
self.cx.in_transaction = True

def CheckOpenWithPathLikeObject(self):
""" Checks that we can succesfully connect to a database using an object that
is PathLike, i.e. has __fspath__(). """
self.addCleanup(unlink, TESTFN)
class Path:
def __fspath__(self):
return TESTFN
path = Path()
with sqlite.connect(path) as cx:
cx.execute('create table test(id integer)')

def CheckOpenUri(self):
if sqlite.sqlite_version_info < (3, 7, 7):
with self.assertRaises(sqlite.NotSupportedError):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*database* argument of sqlite3.connect() now accepts a
:term:`path-like object`, instead of just a string.
9 changes: 7 additions & 2 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
};

char* database;
PyObject* database_obj;
int detect_types = 0;
PyObject* isolation_level = NULL;
PyObject* factory = NULL;
Expand All @@ -85,14 +86,16 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
double timeout = 5.0;
int rc;

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
&database, &timeout, &detect_types,
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|diOiOip", kwlist,
PyUnicode_FSConverter, &database_obj, &timeout, &detect_types,
&isolation_level, &check_same_thread,
&factory, &cached_statements, &uri))
{
return -1;
}

database = PyBytes_AsString(database_obj);

self->initialized = 1;

self->begin_statement = NULL;
Expand Down Expand Up @@ -124,6 +127,8 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
#endif
Py_END_ALLOW_THREADS

Py_DECREF(database_obj);

if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db, NULL);
return -1;
Expand Down
4 changes: 2 additions & 2 deletions Modules/_sqlite/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
"check_same_thread", "factory", "cached_statements", "uri",
NULL
};
char* database;
PyObject* database;
int detect_types = 0;
PyObject* isolation_level;
PyObject* factory = NULL;
Expand All @@ -66,7 +66,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*

PyObject* result;

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOip", kwlist,
&database, &timeout, &detect_types,
&isolation_level, &check_same_thread,
&factory, &cached_statements, &uri))
Expand Down

0 comments on commit a22a127

Please sign in to comment.