Commit 6a91b638 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #19923 -- Display tracebacks for non-CommandError exceptions

By default, show tracebacks for management command errors when the
exception is not a CommandError.
Thanks Jacob Radford for the report.
parent 5e80571b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -241,7 +241,7 @@ class BaseCommand(object):
        except Exception as e:
            # self.stderr is not guaranteed to be set here
            stderr = getattr(self, 'stderr', OutputWrapper(sys.stderr, self.style.ERROR))
            if options.traceback:
            if options.traceback or not isinstance(e, CommandError):
                stderr.write(traceback.format_exc())
            else:
                stderr.write('%s: %s' % (e.__class__.__name__, e))
+7 −2
Original line number Diff line number Diff line
@@ -1342,8 +1342,13 @@ Example usage::
    django-admin.py syncdb --traceback

By default, ``django-admin.py`` will show a simple error message whenever an
error occurs. If you specify ``--traceback``, ``django-admin.py``  will
output a full stack trace whenever an exception is raised.
:class:`~django.core.management.CommandError` occurs, but a full stack trace
for any other exception. If you specify ``--traceback``, ``django-admin.py``
will also output a full stack trace when a ``CommandError`` is raised.

.. versionchanged:: 1.6
    Previously, Django didn't show a full stack trace by default for exceptions
    other than ``CommandError``.

.. django-admin-option:: --verbosity

+16 −4
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ import codecs

from django import conf, bin, get_version
from django.conf import settings
from django.core.management import BaseCommand
from django.core.management import BaseCommand, CommandError
from django.db import connection
from django.test.simple import DjangoTestSuiteRunner
from django.utils import unittest
@@ -1297,22 +1297,34 @@ class CommandTypes(AdminScriptTestCase):
        Also test proper traceback display.
        """
        command = BaseCommand()
        command.execute = lambda args: args  # This will trigger TypeError
        def raise_command_error(*args, **kwargs):
            raise CommandError("Custom error")

        old_stderr = sys.stderr
        sys.stderr = err = StringIO()
        try:
            command.execute = lambda args: args  # This will trigger TypeError
            with self.assertRaises(SystemExit):
                command.run_from_argv(['', ''])
            err_message = err.getvalue()
            self.assertNotIn("Traceback", err_message)
            # Exceptions other than CommandError automatically output the traceback
            self.assertIn("Traceback", err_message)
            self.assertIn("TypeError", err_message)

            command.execute = raise_command_error
            err.truncate(0)
            with self.assertRaises(SystemExit):
                command.run_from_argv(['', ''])
            err_message = err.getvalue()
            self.assertNotIn("Traceback", err_message)
            self.assertIn("CommandError", err_message)

            err.truncate(0)
            with self.assertRaises(SystemExit):
                command.run_from_argv(['', '', '--traceback'])
            err_message = err.getvalue()
            self.assertIn("Traceback (most recent call last)", err_message)
            self.assertIn("TypeError", err_message)
            self.assertIn("CommandError", err_message)
        finally:
            sys.stderr = old_stderr