bpo-31843: sqlite3.connect() now accepts PathLike objects as database… · python/cpython@a22a127

5 files changed

lines changed

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
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.

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;

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))