Skip to content

Commit a22a127

Browse files
Phaquivstinner
authored andcommitted
bpo-31843: sqlite3.connect() now accepts PathLike objects as database name (#4299)
1 parent edb13ae commit a22a127

File tree

5 files changed

+32
-7
lines changed

5 files changed

+32
-7
lines changed

Doc/library/sqlite3.rst

+10-3
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,13 @@ Module functions and constants
172172

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

175-
Opens a connection to the SQLite database file *database*. You can use
176-
``":memory:"`` to open a database connection to a database that resides in RAM
177-
instead of on disk.
175+
Opens a connection to the SQLite database file *database*. By default returns a
176+
:class:`Connection` object, unless a custom *factory* is given.
177+
178+
*database* is a :term:`path-like object` giving the pathname (absolute or
179+
relative to the current working directory) of the database file to be opened.
180+
You can use ``":memory:"`` to open a database connection to a database that
181+
resides in RAM instead of on disk.
178182

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

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

227234
.. function:: register_converter(typename, callable)
228235

Lib/sqlite3/test/dbapi.py

+11
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ def CheckInTransactionRO(self):
160160
with self.assertRaises(AttributeError):
161161
self.cx.in_transaction = True
162162

163+
def CheckOpenWithPathLikeObject(self):
164+
""" Checks that we can succesfully connect to a database using an object that
165+
is PathLike, i.e. has __fspath__(). """
166+
self.addCleanup(unlink, TESTFN)
167+
class Path:
168+
def __fspath__(self):
169+
return TESTFN
170+
path = Path()
171+
with sqlite.connect(path) as cx:
172+
cx.execute('create table test(id integer)')
173+
163174
def CheckOpenUri(self):
164175
if sqlite.sqlite_version_info < (3, 7, 7):
165176
with self.assertRaises(sqlite.NotSupportedError):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*database* argument of sqlite3.connect() now accepts a
2+
:term:`path-like object`, instead of just a string.

Modules/_sqlite/connection.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
7676
};
7777

7878
char* database;
79+
PyObject* database_obj;
7980
int detect_types = 0;
8081
PyObject* isolation_level = NULL;
8182
PyObject* factory = NULL;
@@ -85,14 +86,16 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
8586
double timeout = 5.0;
8687
int rc;
8788

88-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
89-
&database, &timeout, &detect_types,
89+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|diOiOip", kwlist,
90+
PyUnicode_FSConverter, &database_obj, &timeout, &detect_types,
9091
&isolation_level, &check_same_thread,
9192
&factory, &cached_statements, &uri))
9293
{
9394
return -1;
9495
}
9596

97+
database = PyBytes_AsString(database_obj);
98+
9699
self->initialized = 1;
97100

98101
self->begin_statement = NULL;
@@ -124,6 +127,8 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
124127
#endif
125128
Py_END_ALLOW_THREADS
126129

130+
Py_DECREF(database_obj);
131+
127132
if (rc != SQLITE_OK) {
128133
_pysqlite_seterror(self->db, NULL);
129134
return -1;

Modules/_sqlite/module.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
5555
"check_same_thread", "factory", "cached_statements", "uri",
5656
NULL
5757
};
58-
char* database;
58+
PyObject* database;
5959
int detect_types = 0;
6060
PyObject* isolation_level;
6161
PyObject* factory = NULL;
@@ -66,7 +66,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
6666

6767
PyObject* result;
6868

69-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist,
69+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOip", kwlist,
7070
&database, &timeout, &detect_types,
7171
&isolation_level, &check_same_thread,
7272
&factory, &cached_statements, &uri))

0 commit comments

Comments
 (0)