~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/exc.py

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski
  • Date: 2011-08-01 23:18:16 UTC
  • mfrom: (1.4.15 upstream) (16.1.14 experimental)
  • Revision ID: james.westby@ubuntu.com-20110801231816-6lx797pi3q1fpqst
Tags: 0.7.2-1
* New upstream release
* Bump minimum required python-mako version to 0.4.1 (closes: 635898)

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 
13
13
"""
14
14
 
 
15
import traceback
15
16
 
16
17
class SQLAlchemyError(Exception):
17
18
    """Generic error class."""
78
79
class NoReferencedTableError(NoReferenceError):
79
80
    """Raised by ``ForeignKey`` when the referred ``Table`` cannot be located."""
80
81
 
 
82
    def __init__(self, message, tname):
 
83
        NoReferenceError.__init__(self, message)
 
84
        self.table_name = tname
 
85
 
81
86
class NoReferencedColumnError(NoReferenceError):
82
87
    """Raised by ``ForeignKey`` when the referred ``Column`` cannot be located."""
83
88
 
 
89
    def __init__(self, message, tname, cname):
 
90
        NoReferenceError.__init__(self, message)
 
91
        self.table_name = tname
 
92
        self.column_name = cname
 
93
 
84
94
class NoSuchTableError(InvalidRequestError):
85
95
    """Table does not exist or is not visible to a connection."""
86
96
 
89
99
    """SQL was attempted without a database connection to execute it on."""
90
100
 
91
101
 
92
 
# Moved to orm.exc; compatability definition installed by orm import until 0.6
 
102
class DontWrapMixin(object):
 
103
    """A mixin class which, when applied to a user-defined Exception class,
 
104
    will not be wrapped inside of :class:`.StatementError` if the error is
 
105
    emitted within the process of executing a statement.
 
106
    
 
107
    E.g.::
 
108
        from sqlalchemy.exc import DontWrapMixin
 
109
        
 
110
        class MyCustomException(Exception, DontWrapMixin):
 
111
            pass
 
112
        
 
113
        class MySpecialType(TypeDecorator):
 
114
            impl = String
 
115
            
 
116
            def process_bind_param(self, value, dialect):
 
117
                if value == 'invalid':
 
118
                    raise MyCustomException("invalid!")
 
119
            
 
120
    """
 
121
import sys
 
122
if sys.version_info < (2, 5):
 
123
    class DontWrapMixin:
 
124
        pass
 
125
 
 
126
# Moved to orm.exc; compatibility definition installed by orm import until 0.6
93
127
UnmappedColumnError = None
94
128
 
95
 
class DBAPIError(SQLAlchemyError):
 
129
class StatementError(SQLAlchemyError):
 
130
    """An error occurred during execution of a SQL statement.
 
131
    
 
132
    :class:`.StatementError` wraps the exception raised
 
133
    during execution, and features :attr:`.statement`
 
134
    and :attr:`.params` attributes which supply context regarding
 
135
    the specifics of the statement which had an issue.
 
136
 
 
137
    The wrapped exception object is available in 
 
138
    the :attr:`.orig` attribute.
 
139
    
 
140
    """
 
141
 
 
142
    def __init__(self, message, statement, params, orig):
 
143
        SQLAlchemyError.__init__(self, message)
 
144
        self.statement = statement
 
145
        self.params = params
 
146
        self.orig = orig
 
147
 
 
148
    def __str__(self):
 
149
        if isinstance(self.params, (list, tuple)) and \
 
150
            len(self.params) > 10 and \
 
151
            isinstance(self.params[0], (list, dict, tuple)):
 
152
            return ' '.join((SQLAlchemyError.__str__(self),
 
153
                             repr(self.statement),
 
154
                             repr(self.params[:2]),
 
155
                             '... and a total of %i bound parameter sets' % len(self.params)))
 
156
        return ' '.join((SQLAlchemyError.__str__(self),
 
157
                         repr(self.statement), repr(self.params)))
 
158
 
 
159
class DBAPIError(StatementError):
96
160
    """Raised when the execution of a database operation fails.
97
161
 
98
162
    ``DBAPIError`` wraps exceptions raised by the DB-API underlying the
103
167
    that there is no guarantee that different DB-API implementations will
104
168
    raise the same exception type for any given error condition.
105
169
 
106
 
    If the error-raising operation occured in the execution of a SQL
107
 
    statement, that statement and its parameters will be available on
108
 
    the exception object in the ``statement`` and ``params`` attributes.
 
170
    :class:`.DBAPIError` features :attr:`.statement`
 
171
    and :attr:`.params` attributes which supply context regarding
 
172
    the specifics of the statement which had an issue, for the 
 
173
    typical case when the error was raised within the context of
 
174
    emitting a SQL statement.
109
175
 
110
 
    The wrapped exception object is available in the ``orig`` attribute.
 
176
    The wrapped exception object is available in the :attr:`.orig` attribute.
111
177
    Its type and properties are DB-API implementation specific.
112
178
 
113
179
    """
114
180
 
115
181
    @classmethod
116
 
    def instance(cls, statement, params, orig, connection_invalidated=False):
 
182
    def instance(cls, statement, params, 
 
183
                        orig, 
 
184
                        dbapi_base_err,
 
185
                        connection_invalidated=False):
117
186
        # Don't ever wrap these, just return them directly as if
118
187
        # DBAPIError didn't exist.
119
 
        if isinstance(orig, (KeyboardInterrupt, SystemExit)):
 
188
        if isinstance(orig, (KeyboardInterrupt, SystemExit, DontWrapMixin)):
120
189
            return orig
121
190
 
122
191
        if orig is not None:
 
192
            # not a DBAPI error, statement is present.
 
193
            # raise a StatementError
 
194
            if not isinstance(orig, dbapi_base_err) and statement:
 
195
                return StatementError(
 
196
                            "%s (original cause: %s)" % (
 
197
                                str(orig), 
 
198
                                traceback.format_exception_only(orig.__class__, orig)[-1].strip()
 
199
                            ), statement, params, orig)
 
200
 
123
201
            name, glob = orig.__class__.__name__, globals()
124
202
            if name in glob and issubclass(glob[name], DBAPIError):
125
203
                cls = glob[name]
133
211
            raise
134
212
        except Exception, e:
135
213
            text = 'Error in str() of DB-API-generated exception: ' + str(e)
136
 
        SQLAlchemyError.__init__(
137
 
            self, '(%s) %s' % (orig.__class__.__name__, text))
138
 
        self.statement = statement
139
 
        self.params = params
140
 
        self.orig = orig
 
214
        StatementError.__init__(
 
215
                self, 
 
216
                '(%s) %s' % (orig.__class__.__name__, text),
 
217
                statement,
 
218
                params,
 
219
                orig
 
220
        )
141
221
        self.connection_invalidated = connection_invalidated
142
222
 
143
 
    def __str__(self):
144
 
        if isinstance(self.params, (list, tuple)) and len(self.params) > 10 and isinstance(self.params[0], (list, dict, tuple)):
145
 
            return ' '.join((SQLAlchemyError.__str__(self),
146
 
                             repr(self.statement),
147
 
                             repr(self.params[:2]),
148
 
                             '... and a total of %i bound parameter sets' % len(self.params)))
149
 
        return ' '.join((SQLAlchemyError.__str__(self),
150
 
                         repr(self.statement), repr(self.params)))
151
 
 
152
 
 
153
 
# As of 0.4, SQLError is now DBAPIError.
154
 
# SQLError alias will be removed in 0.6.
155
 
SQLError = DBAPIError
156
223
 
157
224
class InterfaceError(DBAPIError):
158
225
    """Wraps a DB-API InterfaceError."""