summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/engine/base.py3
-rw-r--r--lib/sqlalchemy/engine/default.py3
-rw-r--r--lib/sqlalchemy/engine/strategies.py2
-rw-r--r--lib/sqlalchemy/exceptions.py110
-rw-r--r--lib/sqlalchemy/pool.py11
5 files changed, 90 insertions, 39 deletions
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 78eb0922e..a4e41e996 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -1183,7 +1183,8 @@ class ResultProxy(object):
rec = (type, type.dialect_impl(self.dialect), i)
if rec[0] is None:
- raise exceptions.DBAPIError("None for metadata " + colname)
+ raise exceptions.InvalidRequestError(
+ "None for metadata " + colname)
if self.__props.setdefault(colname.lower(), rec) is not rec:
self.__props[colname.lower()] = (type, ResultProxy.AmbiguousColumn(colname), 0)
self.__keys.append(colname)
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py
index a9ee02c1c..f7410bb0f 100644
--- a/lib/sqlalchemy/engine/default.py
+++ b/lib/sqlalchemy/engine/default.py
@@ -136,7 +136,8 @@ class DefaultDialect(base.Dialect):
# to appropriate character upon compilation
self.positional = True
else:
- raise exceptions.DBAPIError("Unsupported paramstyle '%s'" % self._paramstyle)
+ raise exceptions.InvalidRequestError(
+ "Unsupported paramstyle '%s'" % self._paramstyle)
def _get_ischema(self):
if self._ischema is None:
diff --git a/lib/sqlalchemy/engine/strategies.py b/lib/sqlalchemy/engine/strategies.py
index ed9422d15..168a9c4ab 100644
--- a/lib/sqlalchemy/engine/strategies.py
+++ b/lib/sqlalchemy/engine/strategies.py
@@ -71,7 +71,7 @@ class DefaultEngineStrategy(EngineStrategy):
try:
return dbapi.connect(*cargs, **cparams)
except Exception, e:
- raise exceptions.DBAPIError("Connection failed", e)
+ raise exceptions.DBAPIError(None, None, e)
creator = kwargs.pop('creator', connect)
poolclass = (kwargs.pop('poolclass', None) or
diff --git a/lib/sqlalchemy/exceptions.py b/lib/sqlalchemy/exceptions.py
index 7fe5cf518..28e32eeb4 100644
--- a/lib/sqlalchemy/exceptions.py
+++ b/lib/sqlalchemy/exceptions.py
@@ -8,23 +8,6 @@
class SQLAlchemyError(Exception):
"""Generic error class."""
- pass
-
-class SQLError(SQLAlchemyError):
- """Raised when the execution of a SQL statement fails.
-
- Includes accessors for the underlying exception, as well as the
- SQL and bind parameters.
- """
-
- def __init__(self, statement, params, orig):
- SQLAlchemyError.__init__(self, "(%s) %s"% (orig.__class__.__name__, str(orig)))
- self.statement = statement
- self.params = params
- self.orig = orig
-
- def __str__(self):
- return SQLAlchemyError.__str__(self) + " " + repr(self.statement) + " " + repr(self.params)
class ArgumentError(SQLAlchemyError):
"""Raised for all those conditions where invalid arguments are
@@ -32,30 +15,26 @@ class ArgumentError(SQLAlchemyError):
construction time state errors.
"""
- pass
class CompileError(SQLAlchemyError):
"""Raised when an error occurs during SQL compilation"""
-
- pass
-
+
+
class TimeoutError(SQLAlchemyError):
"""Raised when a connection pool times out on getting a connection."""
- pass
class ConcurrentModificationError(SQLAlchemyError):
"""Raised when a concurrent modification condition is detected."""
- pass
class CircularDependencyError(SQLAlchemyError):
"""Raised by topological sorts when a circular dependency is detected"""
- pass
+
class FlushError(SQLAlchemyError):
"""Raised when an invalid condition is detected upon a ``flush()``."""
- pass
+
class InvalidRequestError(SQLAlchemyError):
"""SQLAlchemy was asked to do something it can't do, return
@@ -64,32 +43,93 @@ class InvalidRequestError(SQLAlchemyError):
This error generally corresponds to runtime state errors.
"""
- pass
class NoSuchTableError(InvalidRequestError):
"""SQLAlchemy was asked to load a table's definition from the
database, but the table doesn't exist.
"""
- pass
class AssertionError(SQLAlchemyError):
"""Corresponds to internal state being detected in an invalid state."""
- pass
class NoSuchColumnError(KeyError, SQLAlchemyError):
"""Raised by ``RowProxy`` when a nonexistent column is requested from a row."""
- pass
+
+class DisconnectionError(SQLAlchemyError):
+ """Raised within ``Pool`` when a disconnect is detected on a raw DBAPI connection."""
+
class DBAPIError(SQLAlchemyError):
- """Something weird happened with a particular DBAPI version."""
+ """Raised when the execution of a database operation fails.
+
+ ``DBAPIError`` wraps exceptions raised by the DB-API underlying the
+ database operation. Driver-specific implementations of the standard
+ DB-API exception types are wrapped by matching sub-types of SQLAlchemy's
+ ``DBAPIError`` when possible. DB-API's ``Error`` type maps to
+ ``DBAPIError`` in SQLAlchemy, otherwise the names are identical. Note
+ that there is no guarantee that different DB-API implementations will
+ raise the same exception type for any given error condition.
+
+ If the error-raising operation occured in the execution of a SQL
+ statement, that statement and its parameters will be available on
+ the exception object in the ``statement`` and ``params`` attributes.
+
+ The wrapped exception object is available in the ``orig`` attribute.
+ Its type and properties are DB-API implementation specific.
+ """
+
+ def __new__(cls, statement, params, orig, *args, **kw):
+ # Don't ever wrap these, just return them directly as if
+ # DBAPIError didn't exist.
+ if isinstance(orig, (KeyboardInterrupt, SystemExit)):
+ return orig
+
+ if orig is not None:
+ name, glob = type(orig).__name__, globals()
+ if name in glob and issubclass(glob[name], DBAPIError):
+ cls = glob[name]
+
+ return SQLAlchemyError.__new__(cls, statement, params, orig,
+ *args, **kw)
- def __init__(self, message, orig):
- SQLAlchemyError.__init__(self, "(%s) (%s) %s"% (message, orig.__class__.__name__, str(orig)))
+ def __init__(self, statement, params, orig):
+ SQLAlchemyError.__init__(self, "(%s) %s" %
+ (orig.__class__.__name__, str(orig)))
+ self.statement = statement
+ self.params = params
self.orig = orig
-class DisconnectionError(SQLAlchemyError):
- """Raised within ``Pool`` when a disconnect is detected on a raw DBAPI connection."""
- pass
+ def __str__(self):
+ return ' '.join([SQLAlchemyError.__str__(self),
+ repr(self.statement), repr(self.params)])
+
+
+# As of 0.4, SQLError is now DBAPIError
+SQLError = DBAPIError
+
+class InterfaceError(DBAPIError):
+ """Wraps a DB-API InterfaceError."""
+
+class DatabaseError(DBAPIError):
+ """Wraps a DB-API DatabaseError."""
+
+class DataError(DatabaseError):
+ """Wraps a DB-API DataError."""
+
+class OperationalError(DatabaseError):
+ """Wraps a DB-API OperationalError."""
+
+class IntegrityError(DatabaseError):
+ """Wraps a DB-API IntegrityError."""
+
+class InterfaceError(DatabaseError):
+ """Wraps a DB-API InterfaceError."""
+
+class ProgrammingError(DatabaseError):
+ """Wraps a DB-API ProgrammingError."""
+
+class NotSupportedError(DatabaseError):
+ """Wraps a DB-API NotSupportedError."""
diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py
index f6965495f..526abe81c 100644
--- a/lib/sqlalchemy/pool.py
+++ b/lib/sqlalchemy/pool.py
@@ -241,6 +241,8 @@ class _ConnectionRecord(object):
self.connection.close()
except Exception, e:
self.__pool.log("Connection %s threw an error on close: %s" % (repr(self.connection), str(e)))
+ if isinstance(e, (SystemExit, KeyboardInterrupt)):
+ raise
def __connect(self):
try:
@@ -371,6 +373,8 @@ class _ConnectionFairy(object):
except Exception, e:
if self._connection_record is not None:
self._connection_record.invalidate(e=e)
+ if isinstance(e, (SystemExit, KeyboardInterrupt)):
+ raise
if self._connection_record is not None:
if self._pool.echo:
self._pool.log("Connection %s being returned to pool" % repr(self.connection))
@@ -394,6 +398,8 @@ class _CursorFairy(object):
self.cursor.close()
except Exception, e:
self.__parent._logger.warn("Error closing cursor: " + str(e))
+ if isinstance(e, (SystemExit, KeyboardInterrupt)):
+ raise
def __getattr__(self, key):
return getattr(self.cursor, key)
@@ -432,8 +438,11 @@ class SingletonThreadPool(Pool):
for key, conn in self._conns.items():
try:
conn.close()
+ except (SystemExit, KeyboardInterrupt):
+ raise
except:
- # sqlite won't even let you close a conn from a thread that didn't create it
+ # sqlite won't even let you close a conn from a thread
+ # that didn't create it
pass
del self._conns[key]