Fixed #18003 -- Preserved tracebacks when re-raising errors.

Thanks jrothenbuhler for draft patch, Konark Modi for updates.
This commit is contained in:
konarkmodi 2013-03-19 10:34:59 +05:30 committed by Carl Meyer
parent 1fe90b281b
commit bc4111ba68
15 changed files with 60 additions and 32 deletions

View File

@ -1,4 +1,5 @@
import operator import operator
import sys
import warnings import warnings
from functools import reduce from functools import reduce
@ -173,7 +174,7 @@ class ChangeList(six.with_metaclass(RenameChangeListMethods)):
lookup_needs_distinct(self.lookup_opts, key)) lookup_needs_distinct(self.lookup_opts, key))
return filter_specs, bool(filter_specs), lookup_params, use_distinct return filter_specs, bool(filter_specs), lookup_params, use_distinct
except FieldDoesNotExist as e: except FieldDoesNotExist as e:
raise IncorrectLookupParameters(e) six.reraise(IncorrectLookupParameters, IncorrectLookupParameters(e), sys.exc_info()[2])
def get_query_string(self, new_params=None, remove=None): def get_query_string(self, new_params=None, remove=None):
if new_params is None: new_params = {} if new_params is None: new_params = {}

View File

@ -1,5 +1,7 @@
import cx_Oracle import cx_Oracle
import sys
from django.db.backends.oracle.introspection import DatabaseIntrospection from django.db.backends.oracle.introspection import DatabaseIntrospection
from django.utils import six
class OracleIntrospection(DatabaseIntrospection): class OracleIntrospection(DatabaseIntrospection):
# Associating any OBJECTVAR instances with GeometryField. Of course, # Associating any OBJECTVAR instances with GeometryField. Of course,
@ -17,8 +19,11 @@ class OracleIntrospection(DatabaseIntrospection):
(table_name.upper(), geo_col.upper())) (table_name.upper(), geo_col.upper()))
row = cursor.fetchone() row = cursor.fetchone()
except Exception as msg: except Exception as msg:
raise Exception('Could not find entry in USER_SDO_GEOM_METADATA corresponding to "%s"."%s"\n' new_msg = (
'Error message: %s.' % (table_name, geo_col, msg)) 'Could not find entry in USER_SDO_GEOM_METADATA '
'corresponding to "%s"."%s"\n'
'Error message: %s.') % (table_name, geo_col, msg)
six.reraise(Exception, Exception(new_msg), sys.exc_info()[2])
# TODO: Research way to find a more specific geometry field type for # TODO: Research way to find a more specific geometry field type for
# the column's contents. # the column's contents.

View File

@ -1,3 +1,4 @@
import sys
from ctypes.util import find_library from ctypes.util import find_library
from django.conf import settings from django.conf import settings
@ -8,6 +9,7 @@ from django.contrib.gis.db.backends.spatialite.client import SpatiaLiteClient
from django.contrib.gis.db.backends.spatialite.creation import SpatiaLiteCreation from django.contrib.gis.db.backends.spatialite.creation import SpatiaLiteCreation
from django.contrib.gis.db.backends.spatialite.introspection import SpatiaLiteIntrospection from django.contrib.gis.db.backends.spatialite.introspection import SpatiaLiteIntrospection
from django.contrib.gis.db.backends.spatialite.operations import SpatiaLiteOperations from django.contrib.gis.db.backends.spatialite.operations import SpatiaLiteOperations
from django.utils import six
class DatabaseWrapper(SQLiteDatabaseWrapper): class DatabaseWrapper(SQLiteDatabaseWrapper):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -50,7 +52,9 @@ class DatabaseWrapper(SQLiteDatabaseWrapper):
try: try:
cur.execute("SELECT load_extension(%s)", (self.spatialite_lib,)) cur.execute("SELECT load_extension(%s)", (self.spatialite_lib,))
except Exception as msg: except Exception as msg:
raise ImproperlyConfigured('Unable to load the SpatiaLite library extension ' new_msg = (
'"%s" because: %s' % (self.spatialite_lib, msg)) 'Unable to load the SpatiaLite library extension '
'"%s" because: %s') % (self.spatialite_lib, msg)
six.reraise(ImproperlyConfigured, ImproperlyConfigured(new_msg), sys.exc_info()[2])
cur.close() cur.close()
return conn return conn

View File

@ -1,4 +1,5 @@
import re import re
import sys
from decimal import Decimal from decimal import Decimal
from django.contrib.gis.db.backends.base import BaseSpatialOperations from django.contrib.gis.db.backends.base import BaseSpatialOperations
@ -126,10 +127,11 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
try: try:
version = self.spatialite_version_tuple()[1:] version = self.spatialite_version_tuple()[1:]
except Exception as msg: except Exception as msg:
raise ImproperlyConfigured('Cannot determine the SpatiaLite version for the "%s" ' new_msg = (
'database (error was "%s"). Was the SpatiaLite initialization ' 'Cannot determine the SpatiaLite version for the "%s" '
'SQL loaded on this database?' % 'database (error was "%s"). Was the SpatiaLite initialization '
(self.connection.settings_dict['NAME'], msg)) 'SQL loaded on this database?') % (self.connection.settings_dict['NAME'], msg)
six.reraise(ImproperlyConfigured, ImproperlyConfigured(new_msg), sys.exc_info()[2])
if version < (2, 3, 0): if version < (2, 3, 0):
raise ImproperlyConfigured('GeoDjango only supports SpatiaLite versions ' raise ImproperlyConfigured('GeoDjango only supports SpatiaLite versions '
'2.3.0 and above') '2.3.0 and above')

View File

@ -429,7 +429,8 @@ class LayerMapping(object):
# Creating the CoordTransform object # Creating the CoordTransform object
return CoordTransform(self.source_srs, target_srs) return CoordTransform(self.source_srs, target_srs)
except Exception as msg: except Exception as msg:
raise LayerMapError('Could not translate between the data source and model geometry: %s' % msg) new_msg = 'Could not translate between the data source and model geometry: %s' % msg
six.reraise(LayerMapError, LayerMapError(new_msg), sys.exc_info()[2])
def geometry_field(self): def geometry_field(self):
"Returns the GeometryField instance associated with the geographic column." "Returns the GeometryField instance associated with the geographic column."

View File

@ -1,3 +1,4 @@
import sys
from optparse import make_option from optparse import make_option
from django.conf import settings from django.conf import settings
@ -8,6 +9,7 @@ from django.core.management.color import no_style
from django.core.management.sql import sql_flush, emit_post_sync_signal from django.core.management.sql import sql_flush, emit_post_sync_signal
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.utils.six.moves import input from django.utils.six.moves import input
from django.utils import six
class Command(NoArgsCommand): class Command(NoArgsCommand):
@ -62,13 +64,14 @@ Are you sure you want to do this?
for sql in sql_list: for sql in sql_list:
cursor.execute(sql) cursor.execute(sql)
except Exception as e: except Exception as e:
raise CommandError("""Database %s couldn't be flushed. Possible reasons: new_msg = (
* The database isn't running or isn't configured correctly. "Database %s couldn't be flushed. Possible reasons:\n"
* At least one of the expected database tables doesn't exist. " * The database isn't running or isn't configured correctly.\n"
* The SQL was invalid. " * At least one of the expected database tables doesn't exist.\n"
Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. " * The SQL was invalid.\n"
The full error: %s""" % (connection.settings_dict['NAME'], e)) "Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run.\n"
"The full error: %s") % (connection.settings_dict['NAME'], e)
six.reraise(CommandError, CommandError(new_msg), sys.exc_info()[2])
# Emit the post sync signal. This allows individual # Emit the post sync signal. This allows individual
# applications to respond as if the database had been # applications to respond as if the database had been
# sync'd from scratch. # sync'd from scratch.

View File

@ -8,6 +8,7 @@ from __future__ import absolute_import
import datetime import datetime
import decimal import decimal
import json import json
import sys
from django.core.serializers.base import DeserializationError from django.core.serializers.base import DeserializationError
from django.core.serializers.python import Serializer as PythonSerializer from django.core.serializers.python import Serializer as PythonSerializer
@ -72,7 +73,7 @@ def Deserializer(stream_or_string, **options):
raise raise
except Exception as e: except Exception as e:
# Map to deserializer error # Map to deserializer error
raise DeserializationError(e) six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])
class DjangoJSONEncoder(json.JSONEncoder): class DjangoJSONEncoder(json.JSONEncoder):

View File

@ -6,6 +6,7 @@ Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
import decimal import decimal
import yaml import yaml
import sys
from io import StringIO from io import StringIO
from django.db import models from django.db import models
@ -71,4 +72,4 @@ def Deserializer(stream_or_string, **options):
raise raise
except Exception as e: except Exception as e:
# Map to deserializer error # Map to deserializer error
raise DeserializationError(e) six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])

View File

@ -24,6 +24,7 @@ from wsgiref.util import FileWrapper # for backwards compatibility
from django.core.management.color import color_style from django.core.management.color import color_style
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
from django.utils.module_loading import import_by_path from django.utils.module_loading import import_by_path
from django.utils import six
__all__ = ['WSGIServer', 'WSGIRequestHandler'] __all__ = ['WSGIServer', 'WSGIRequestHandler']
@ -121,7 +122,7 @@ class WSGIServer(simple_server.WSGIServer, object):
try: try:
super(WSGIServer, self).server_bind() super(WSGIServer, self).server_bind()
except Exception as e: except Exception as e:
raise WSGIServerException(e) six.reraise(WSGIServerException, WSGIServerException(e), sys.exc_info()[2])
self.setup_environ() self.setup_environ()

View File

@ -8,6 +8,7 @@ import copy
import datetime import datetime
import os import os
import re import re
import sys
try: try:
from urllib.parse import urlsplit, urlunsplit from urllib.parse import urlsplit, urlunsplit
except ImportError: # Python 2 except ImportError: # Python 2
@ -619,7 +620,7 @@ class ImageField(FileField):
# raised. Catch and re-raise. # raised. Catch and re-raise.
raise raise
except Exception: # Python Imaging Library doesn't recognize it as an image except Exception: # Python Imaging Library doesn't recognize it as an image
raise ValidationError(self.error_messages['invalid_image']) six.reraise(ValidationError, ValidationError(self.error_messages['invalid_image']), sys.exc_info()[2])
if hasattr(f, 'seek') and callable(f.seek): if hasattr(f, 'seek') and callable(f.seek):
f.seek(0) f.seek(0)
return f return f

View File

@ -6,6 +6,8 @@ from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils import six
import sys
# Import ValidationError so that it can be imported from this # Import ValidationError so that it can be imported from this
# module to maintain backwards compatibility. # module to maintain backwards compatibility.
@ -78,11 +80,12 @@ def from_current_timezone(value):
try: try:
return timezone.make_aware(value, current_timezone) return timezone.make_aware(value, current_timezone)
except Exception: except Exception:
raise ValidationError(_('%(datetime)s couldn\'t be interpreted ' msg = _(
'in time zone %(current_timezone)s; it ' '%(datetime)s couldn\'t be interpreted '
'may be ambiguous or it may not exist.') 'in time zone %(current_timezone)s; it '
% {'datetime': value, 'may be ambiguous or it may not exist.') % {'datetime': value, 'current_timezone':
'current_timezone': current_timezone}) current_timezone}
six.reraise(ValidationError, ValidationError(msg), sys.exc_info()[2])
return value return value
def to_current_timezone(value): def to_current_timezone(value):

View File

@ -8,6 +8,7 @@ from __future__ import unicode_literals
import base64 import base64
import cgi import cgi
import sys
from django.conf import settings from django.conf import settings
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
@ -209,7 +210,8 @@ class MultiPartParser(object):
chunk = base64.b64decode(chunk) chunk = base64.b64decode(chunk)
except Exception as e: except Exception as e:
# Since this is only a chunk, any error is an unfixable error. # Since this is only a chunk, any error is an unfixable error.
raise MultiPartParserError("Could not decode base64 data: %r" % e) msg = "Could not decode base64 data: %r" % e
six.reraise(MultiPartParserError, MultiPartParserError(msg), sys.exc_info()[2])
for i, handler in enumerate(handlers): for i, handler in enumerate(handlers):
chunk_length = len(chunk) chunk_length = len(chunk)

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import re import re
import sys
from django.conf import settings from django.conf import settings
from django.template import (Node, Variable, TemplateSyntaxError, from django.template import (Node, Variable, TemplateSyntaxError,
@ -424,8 +425,10 @@ def do_block_translate(parser, token):
value = remaining_bits.pop(0) value = remaining_bits.pop(0)
value = parser.compile_filter(value) value = parser.compile_filter(value)
except Exception: except Exception:
raise TemplateSyntaxError('"context" in %r tag expected ' msg = (
'exactly one argument.' % bits[0]) '"context" in %r tag expected '
'exactly one argument.') % bits[0]
six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
else: else:
raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
(bits[0], option)) (bits[0], option))

View File

@ -1119,8 +1119,8 @@ class LiveServerTestCase(TransactionTestCase):
for port in range(extremes[0], extremes[1] + 1): for port in range(extremes[0], extremes[1] + 1):
possible_ports.append(port) possible_ports.append(port)
except Exception: except Exception:
raise ImproperlyConfigured('Invalid address ("%s") for live ' msg = 'Invalid address ("%s") for live server.' % specified_address
'server.' % specified_address) six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg), sys.exc_info()[2])
cls.server_thread = LiveServerThread( cls.server_thread = LiveServerThread(
host, possible_ports, connections_override) host, possible_ports, connections_override)
cls.server_thread.daemon = True cls.server_thread.daemon = True

View File

@ -144,7 +144,7 @@ def parse_http_date(date):
result = datetime.datetime(year, month, day, hour, min, sec) result = datetime.datetime(year, month, day, hour, min, sec)
return calendar.timegm(result.utctimetuple()) return calendar.timegm(result.utctimetuple())
except Exception: except Exception:
raise ValueError("%r is not a valid date" % date) six.reraise(ValueError, ValueError("%r is not a valid date" % date), sys.exc_info()[2])
def parse_http_date_safe(date): def parse_http_date_safe(date):
""" """