]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Now guarding against broken DB-APIs when wrapping their exceptions.
authorJason Kirtland <jek@discorporate.us>
Mon, 22 Oct 2007 19:24:02 +0000 (19:24 +0000)
committerJason Kirtland <jek@discorporate.us>
Mon, 22 Oct 2007 19:24:02 +0000 (19:24 +0000)
- Added an explicit test for exception wrapping.

lib/sqlalchemy/exceptions.py
test/base/alltests.py
test/base/except.py [new file with mode: 0644]

index 9c7caedd03e45888b46a7ea56196a73718a6a7d0..decde0efacfc6a821cb3b3767487873b44774463 100644 (file)
@@ -96,8 +96,14 @@ class DBAPIError(SQLAlchemyError):
     instance = classmethod(instance)
     
     def __init__(self, statement, params, orig):
-        SQLAlchemyError.__init__(self, "(%s) %s" %
-                                 (orig.__class__.__name__, str(orig)))
+        try:
+            text = str(orig)
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except Exception, e:
+            text = 'Error in str() of DB-API-generated exception: ' + str(e)
+        SQLAlchemyError.__init__(
+            self, "(%s) %s" % (orig.__class__.__name__, text))
         self.statement = statement
         self.params = params
         self.orig = orig
index 44fa9b2ecfb361e5fc317865756f462d79c98743..d14b694cba3aa25d47bc97cc44e0c073deb88035 100644 (file)
@@ -6,6 +6,7 @@ def suite():
         # core utilities
         'base.dependency',
         'base.utils',
+        'base.except',
         )
     alltests = unittest.TestSuite()
     for name in modules_to_test:
diff --git a/test/base/except.py b/test/base/except.py
new file mode 100644 (file)
index 0000000..671597b
--- /dev/null
@@ -0,0 +1,78 @@
+"""Tests exceptions and DB-API exception wrapping."""
+
+import testbase
+import sys, unittest
+import exceptions as stdlib_exceptions
+from sqlalchemy import exceptions as sa_exceptions
+from testlib import *
+
+
+class Error(stdlib_exceptions.StandardError):
+    """This class will be old-style on <= 2.4 and new-style on >= 2.5."""
+class DatabaseError(Error):
+    pass
+class OperationalError(DatabaseError):
+    pass
+class ProgrammingError(DatabaseError):
+    def __str__(self):
+        return "<%s>" % self.bogus
+class OutOfSpec(DatabaseError):
+    pass
+
+
+class WrapTest(unittest.TestCase):
+    def test_db_error_normal(self):
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], OperationalError())
+        except sa_exceptions.DBAPIError:
+            self.assert_(True)
+
+    def test_db_error_busted_dbapi(self):
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], ProgrammingError())
+        except sa_exceptions.DBAPIError, e:
+            self.assert_(True)
+            self.assert_('Error in str() of DB-API' in e.args[0])
+
+    def test_db_error_noncompliant_dbapi(self):
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], OutOfSpec())
+        except sa_exceptions.DBAPIError, e:
+            self.assert_(e.__class__ is sa_exceptions.DBAPIError)
+        except OutOfSpec:
+            self.assert_(False)
+
+        # Make sure the DatabaseError recognition logic is limited to
+        # subclasses of sqlalchemy.exceptions.DBAPIError
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], sa_exceptions.AssertionError())
+        except sa_exceptions.DBAPIError, e:
+            self.assert_(e.__class__ is sa_exceptions.DBAPIError)
+        except sa_exceptions.AssertionError:
+            self.assert_(False)
+
+    def test_db_error_keyboard_interrupt(self):
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], stdlib_exceptions.KeyboardInterrupt())
+        except sa_exceptions.DBAPIError:
+            self.assert_(False)
+        except stdlib_exceptions.KeyboardInterrupt:
+            self.assert_(True)
+
+    def test_db_error_system_exit(self):
+        try:
+            raise sa_exceptions.DBAPIError.instance(
+                '', [], stdlib_exceptions.SystemExit())
+        except sa_exceptions.DBAPIError:
+            self.assert_(False)
+        except stdlib_exceptions.SystemExit:
+            self.assert_(True)
+
+
+if __name__ == "__main__":
+    testbase.main()