Ticket #16948: db-backend-exceptions.patch

File db-backend-exceptions.patch, 6.8 KB (added by James Henstridge, 13 years ago)

Sample implementation of idea for the postgresql, mysql and sqlite backends.

  • django/db/utils.py

     
    1717    pass
    1818
    1919
     20def patch_exceptions(db_module):
     21    """Patch a DB-API module's exceptions so that they derrive from
     22    the backend independent Django exceptions."""
     23    for django_exception in [DatabaseError, IntegrityError]:
     24        db_exception = getattr(db_module, django_exception.__name__, None)
     25        if not (db_exception is None or
     26                issubclass(db_exception, django_exception)):
     27            db_exception.__bases__ += (django_exception,)
     28
     29
    2030def load_backend(backend_name):
    2131    # Look for a fully qualified database backend name
    2232    try:
  • django/db/backends/sqlite3/base.py

     
    3030
    3131DatabaseError = Database.DatabaseError
    3232IntegrityError = Database.IntegrityError
     33utils.patch_exceptions(Database)
    3334
    3435Database.register_converter("bool", lambda s: str(s) == '1')
    3536Database.register_converter("time", util.typecast_time)
     
    267268    """
    268269    def execute(self, query, params=()):
    269270        query = self.convert_query(query)
    270         try:
    271             return Database.Cursor.execute(self, query, params)
    272         except Database.IntegrityError, e:
    273             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    274         except Database.DatabaseError, e:
    275             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     271        return Database.Cursor.execute(self, query, params)
    276272
    277273    def executemany(self, query, param_list):
    278274        query = self.convert_query(query)
    279         try:
    280             return Database.Cursor.executemany(self, query, param_list)
    281         except Database.IntegrityError, e:
    282             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    283         except Database.DatabaseError, e:
    284             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     275        return Database.Cursor.executemany(self, query, param_list)
    285276
    286277    def convert_query(self, query):
    287278        return FORMAT_QMARK_REGEX.sub('?', query).replace('%%','%')
  • django/db/backends/mysql/base.py

     
    4242
    4343DatabaseError = Database.DatabaseError
    4444IntegrityError = Database.IntegrityError
     45utils.patch_exceptions(Database)
    4546
    4647# MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
    4748# timedelta in terms of actual behavior as they are signed and include days --
     
    8485    def execute(self, query, args=None):
    8586        try:
    8687            return self.cursor.execute(query, args)
    87         except Database.IntegrityError, e:
    88             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    8988        except Database.OperationalError, e:
    9089            # Map some error codes to IntegrityError, since they seem to be
    9190            # misclassified and Django would prefer the more logical place.
    9291            if e[0] in self.codes_for_integrityerror:
    93                 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     92                raise Database.IntegrityError, Database.IntegrityError(*tuple(e)), sys.exc_info()[2]
    9493            raise
    95         except Database.DatabaseError, e:
    96             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    9794
    9895    def executemany(self, query, args):
    9996        try:
    10097            return self.cursor.executemany(query, args)
    101         except Database.IntegrityError, e:
    102             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    10398        except Database.OperationalError, e:
    10499            # Map some error codes to IntegrityError, since they seem to be
    105100            # misclassified and Django would prefer the more logical place.
    106101            if e[0] in self.codes_for_integrityerror:
    107                 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     102                raise Database.IntegrityError, Database.IntegrityError(*tuple(e)), sys.exc_info()[2]
    108103            raise
    109         except Database.DatabaseError, e:
    110             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    111104
    112105    def __getattr__(self, attr):
    113106        if attr in self.__dict__:
  • django/db/backends/postgresql_psycopg2/base.py

     
    2929psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
    3030psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
    3131psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)
     32utils.patch_exceptions(Database)
    3233
    3334logger = getLogger('django.db.backends')
    3435
    35 class CursorWrapper(object):
    36     """
    37     A thin wrapper around psycopg2's normal cursor class so that we can catch
    38     particular exception instances and reraise them with the right types.
    39     """
    40 
    41     def __init__(self, cursor):
    42         self.cursor = cursor
    43 
    44     def execute(self, query, args=None):
    45         try:
    46             return self.cursor.execute(query, args)
    47         except Database.IntegrityError, e:
    48             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    49         except Database.DatabaseError, e:
    50             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    51 
    52     def executemany(self, query, args):
    53         try:
    54             return self.cursor.executemany(query, args)
    55         except Database.IntegrityError, e:
    56             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    57         except Database.DatabaseError, e:
    58             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    59 
    60     def __getattr__(self, attr):
    61         if attr in self.__dict__:
    62             return self.__dict__[attr]
    63         else:
    64             return getattr(self.cursor, attr)
    65 
    66     def __iter__(self):
    67         return iter(self.cursor)
    68 
    6936class DatabaseFeatures(BaseDatabaseFeatures):
    7037    needs_datetime_string_cast = False
    7138    can_return_id_from_insert = True
     
    176143            if set_tz:
    177144                cursor.execute("SET TIME ZONE %s", [settings_dict['TIME_ZONE']])
    178145            self._get_pg_version()
    179         return CursorWrapper(cursor)
     146        return cursor
    180147
    181148    def _enter_transaction_management(self, managed):
    182149        """
Back to Top