]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
ensure pysqlite dialect enumerates correct isolation levels
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 30 Aug 2021 02:17:13 +0000 (22:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 30 Aug 2021 15:35:10 +0000 (11:35 -0400)
Fixed bug where the error message for SQLite invalid isolation level on the
pysqlite driver would fail to indicate that "AUTOCOMMIT" is one of the
valid isolation levels.

Change-Id: Icbceab9a28af6a560859761fa92320b5473269a9
References: #6959

doc/build/changelog/unreleased_14/sqlite_autocommit.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/sqlite/base.py
lib/sqlalchemy/dialects/sqlite/pysqlite.py
lib/sqlalchemy/testing/requirements.py
test/dialect/test_sqlite.py

diff --git a/doc/build/changelog/unreleased_14/sqlite_autocommit.rst b/doc/build/changelog/unreleased_14/sqlite_autocommit.rst
new file mode 100644 (file)
index 0000000..183e0ee
--- /dev/null
@@ -0,0 +1,6 @@
+.. change::
+    :tags: bug, sqlite
+
+    Fixed bug where the error message for SQLite invalid isolation level on the
+    pysqlite driver would fail to indicate that "AUTOCOMMIT" is one of the
+    valid isolation levels.
index dc5ebc3f0ccc6b9a738b49612dae05415e8bd72a..c4a6bf8e9e7c5206f83487469f5bb2bfbd287170 100644 (file)
@@ -1915,7 +1915,9 @@ class SQLiteDialect(default.DefaultDialect):
                 14,
             )
 
-    _isolation_lookup = {"READ UNCOMMITTED": 1, "SERIALIZABLE": 0}
+    _isolation_lookup = util.immutabledict(
+        {"READ UNCOMMITTED": 1, "SERIALIZABLE": 0}
+    )
 
     def set_isolation_level(self, connection, level):
         try:
@@ -1925,7 +1927,11 @@ class SQLiteDialect(default.DefaultDialect):
                 exc.ArgumentError(
                     "Invalid value '%s' for isolation_level. "
                     "Valid isolation levels for %s are %s"
-                    % (level, self.name, ", ".join(self._isolation_lookup))
+                    % (
+                        level,
+                        self.name,
+                        ", ".join(self._isolation_lookup),
+                    )
                 ),
                 replace_context=err,
             )
index 96a5351daed0e4f7bfd8182aa20acaf5f5578550..0f96e88303f957beb2588bcfdf16b4ae19a9ab14 100644 (file)
@@ -492,6 +492,12 @@ class SQLiteDialect_pysqlite(SQLiteDialect):
     def _get_server_version_info(self, connection):
         return self.dbapi.sqlite_version_info
 
+    _isolation_lookup = SQLiteDialect._isolation_lookup.union(
+        {
+            "AUTOCOMMIT": None,
+        }
+    )
+
     def set_isolation_level(self, connection, level):
         if hasattr(connection, "connection"):
             dbapi_connection = connection.connection
index 742a9a1f81f51ce306b67f4bbdebb05175396f77..e6e5db774ff7882b5f2c14b7a7187d45942cba22 100644 (file)
@@ -1226,6 +1226,10 @@ class SuiteRequirements(Requirements):
     def pep520(self):
         return self.python36
 
+    @property
+    def insert_order_dicts(self):
+        return self.python37
+
     @property
     def python36(self):
         return exclusions.skip_if(
index b5ce291eb10c3c5352bcb5409d41e5a558ca4a3e..ed0f11907cfe62da32e2f2752ce619493b285d9b 100644 (file)
@@ -54,6 +54,7 @@ from sqlalchemy.testing import expect_warnings
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing import is_
 from sqlalchemy.testing import mock
+from sqlalchemy.testing.assertions import expect_raises_message
 from sqlalchemy.types import Boolean
 from sqlalchemy.types import Date
 from sqlalchemy.types import DateTime
@@ -596,6 +597,22 @@ class DialectTest(
                 )
             )
 
+    @testing.requires.insert_order_dicts
+    @testing.only_on("sqlite+pysqlite")
+    def test_isolation_level_message(self):
+        # needs to test that all three words are present and we also
+        # dont want to default all isolation level messages to use
+        # sorted(), so rely on python 3.7 for ordering of keywords
+        # in the message
+        with expect_raises_message(
+            exc.ArgumentError,
+            "Invalid value 'invalid' for "
+            "isolation_level. Valid isolation levels for "
+            "sqlite are READ UNCOMMITTED, SERIALIZABLE, AUTOCOMMIT",
+        ):
+            with testing.db.connect() as conn:
+                conn.execution_options(isolation_level="invalid")
+
     @testing.only_on("sqlite+pysqlcipher")
     def test_pysqlcipher_connects(self):
         """test #6586"""