Kaydet (Commit) a22a1274 authored tarafından Anders Lorentsen's avatar Anders Lorentsen Kaydeden (comit) Victor Stinner

bpo-31843: sqlite3.connect() now accepts PathLike objects as database name (#4299)

üst edb13ae4
...@@ -172,9 +172,13 @@ Module functions and constants ...@@ -172,9 +172,13 @@ Module functions and constants
.. function:: connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements, uri]) .. 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 Opens a connection to the SQLite database file *database*. By default returns a
``":memory:"`` to open a database connection to a database that resides in RAM :class:`Connection` object, unless a custom *factory* is given.
instead of on disk.
*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 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 modifies the database, the SQLite database is locked until that transaction is
...@@ -223,6 +227,9 @@ Module functions and constants ...@@ -223,6 +227,9 @@ Module functions and constants
.. versionchanged:: 3.4 .. versionchanged:: 3.4
Added the *uri* parameter. 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) .. function:: register_converter(typename, callable)
......
...@@ -160,6 +160,17 @@ class ConnectionTests(unittest.TestCase): ...@@ -160,6 +160,17 @@ class ConnectionTests(unittest.TestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
self.cx.in_transaction = True 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): def CheckOpenUri(self):
if sqlite.sqlite_version_info < (3, 7, 7): if sqlite.sqlite_version_info < (3, 7, 7):
with self.assertRaises(sqlite.NotSupportedError): with self.assertRaises(sqlite.NotSupportedError):
......
*database* argument of sqlite3.connect() now accepts a
:term:`path-like object`, instead of just a string.
...@@ -76,6 +76,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject ...@@ -76,6 +76,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
}; };
char* database; char* database;
PyObject* database_obj;
int detect_types = 0; int detect_types = 0;
PyObject* isolation_level = NULL; PyObject* isolation_level = NULL;
PyObject* factory = NULL; PyObject* factory = NULL;
...@@ -85,14 +86,16 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject ...@@ -85,14 +86,16 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
double timeout = 5.0; double timeout = 5.0;
int rc; int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|diOiOip", kwlist,
&database, &timeout, &detect_types, PyUnicode_FSConverter, &database_obj, &timeout, &detect_types,
&isolation_level, &check_same_thread, &isolation_level, &check_same_thread,
&factory, &cached_statements, &uri)) &factory, &cached_statements, &uri))
{ {
return -1; return -1;
} }
database = PyBytes_AsString(database_obj);
self->initialized = 1; self->initialized = 1;
self->begin_statement = NULL; self->begin_statement = NULL;
...@@ -124,6 +127,8 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject ...@@ -124,6 +127,8 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject
#endif #endif
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
Py_DECREF(database_obj);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
_pysqlite_seterror(self->db, NULL); _pysqlite_seterror(self->db, NULL);
return -1; return -1;
......
...@@ -55,7 +55,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* ...@@ -55,7 +55,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
"check_same_thread", "factory", "cached_statements", "uri", "check_same_thread", "factory", "cached_statements", "uri",
NULL NULL
}; };
char* database; PyObject* database;
int detect_types = 0; int detect_types = 0;
PyObject* isolation_level; PyObject* isolation_level;
PyObject* factory = NULL; PyObject* factory = NULL;
...@@ -66,7 +66,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* ...@@ -66,7 +66,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
PyObject* result; PyObject* result;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOip", kwlist,
&database, &timeout, &detect_types, &database, &timeout, &detect_types,
&isolation_level, &check_same_thread, &isolation_level, &check_same_thread,
&factory, &cached_statements, &uri)) &factory, &cached_statements, &uri))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment