#15901: Django should wrap all PEP 249 exceptions in db.utils
-------------------------------------+-------------------------------------
     Reporter:  xiaket               |                    Owner:  nobody
         Type:  New feature          |                   Status:  new
    Component:  Database layer       |                  Version:  1.3
  (models, ORM)                      |               Resolution:
     Severity:  Normal               |             Triage Stage:  Accepted
     Keywords:                       |      Needs documentation:  0
    Has patch:  1                    |  Patch needs improvement:  0
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------

Comment (by gcbirzan):

 Replying to [comment:12 jamesh]:
 > Both of your suggestions prevent users from writing standard Python
 "except" clauses to catch particular classes of database errors, which
 seems to be one of the goals of this ticket.
 >
 > And for some database adapters like psycopg2, there is more useful
 information in the exception than you'll find in `e.args` (e.g. the
 `pgcode` attribute holding the SQL error code).

 I don't understand what you mean. Your confusion might stem from the fact
 that I use code as would be in the database backend, where you have import
 psycopg2 as Database. With the first one:

 {{{
 try:
     do_stuff()
 except util.DatabaseError as e:
     if isinstance(e.args[0], psycopg2.ProgrammingError):
         print e.args[0].pgcode
 }}}

 second:
 {{{
 try:
     do_stuff()
 except psycopg2.ProgrammingError as e:
     pass
 }}}

 Granted, you cannot access pgcode, but that could be hanlded either in a
 backend specific manner, or, you could just put the exception's dictionary
 in the new type (ugly, I know.). But either way, you're better off than
 now.

 I personally am leaning towards the first method, to be honest, since it's
 the closest to pep3134. The original doesn't have to be put in the args,
 it can be:

 {{{
 try:
     do_stuff()
 except Database.DatabaseError as e:
     exc = util.DatabaseError(*e.args)
     exc.__cause__ = e
     raise util.DatabaseError, exc, sys.exc_info()[2]
 }}}

 You can even combine the two:

 {{{
 try:
     do_stuff()
 except Database.DatabaseError as e:
     exc_type = type('DatabaseError', (Database.DatabaseError,
 util.DatabaseError), {})
     raise exc_type, exc_type(e), sys.exc_info()[2]
 }}}
 or
 {{{
 try:
     do_stuff()
 except Database.DatabaseError as e:
     exc_type = type('DatabaseError', (Database.DatabaseError,
 util.DatabaseError), {})
     exc = exc_type(*e.args)
     exc.__cause__ = e
     raise exc_type, exc, sys.exc_info()[2]
 }}}


 Now you can catch it with both psycopg2.DatabaseError, and
 util.DatabaseError. In the first, you will have e.args[0] for the
 original, in the second, e.__cause__.

 > If your concern is about not being able to distinguish exceptions that
 come directly from the database adapter and exceptions from the Django
 backend, what do you see as the consequences of not being able to do this?
 >
 > Django used to let the adapter exceptions bubble up through the
 backends.  It only changed when support for multiple databases were added
 and it was necessary to have some backend independent exceptions to catch.
 If we let the adapter exceptions bubble up but keep the ability to catch
 backend independent exceptions, what do we lose?

 The fact that it will violate the principle of least astonishment, like
 all monkey patching.

 As for your ABC suggestion, it won't work.
 http://bugs.python.org/issue12029

-- 
Ticket URL: <https://code.djangoproject.com/ticket/15901#comment:17>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to