From 888c86dcf30defe533451bcefc6e09a6e181389f Mon Sep 17 00:00:00 2001 From: Jorge Bastida <me@jorgebastida.com> Date: Sat, 18 May 2013 18:04:45 +0200 Subject: [PATCH] Fixed #20445 -- Raised original exception after command error --- django/core/management/base.py | 14 +++++++------- tests/admin_scripts/tests.py | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/django/core/management/base.py b/django/core/management/base.py index ba6ad8f4c0..af040288d0 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -7,7 +7,6 @@ import os import sys from optparse import make_option, OptionParser -import traceback import django from django.core.exceptions import ImproperlyConfigured @@ -171,7 +170,7 @@ class BaseCommand(object): make_option('--pythonpath', help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'), make_option('--traceback', action='store_true', - help='Print traceback on exception'), + help='Raise on exception'), ) help = '' args = '' @@ -231,7 +230,8 @@ class BaseCommand(object): Set up any environment changes requested (e.g., Python path and Django settings), then run this command. If the command raises a ``CommandError``, intercept it and print it sensibly - to stderr. + to stderr. If the ``--traceback`` option is present or the raised + ``Exception`` is not ``CommandError``, raise it. """ parser = self.create_parser(argv[0], argv[1]) options, args = parser.parse_args(argv[2:]) @@ -239,12 +239,12 @@ class BaseCommand(object): try: self.execute(*args, **options.__dict__) except Exception as e: + if options.traceback or not isinstance(e, CommandError): + raise + # self.stderr is not guaranteed to be set here stderr = getattr(self, 'stderr', OutputWrapper(sys.stderr, self.style.ERROR)) - if options.traceback or not isinstance(e, CommandError): - stderr.write(traceback.format_exc()) - else: - stderr.write('%s: %s' % (e.__class__.__name__, e)) + stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1) def execute(self, *args, **options): diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index c8986770f3..f0ef0fb293 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -1305,13 +1305,15 @@ class CommandTypes(AdminScriptTestCase): 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() - # Exceptions other than CommandError automatically output the traceback - self.assertIn("Traceback", err_message) - self.assertIn("TypeError", err_message) + # If the Exception is not CommandError it should always + # raise the original exception. + with self.assertRaises(TypeError): + command.run_from_argv(['', '']) + + # If the Exception is CommandError and --traceback is not present + # this command should raise a SystemExit and don't print any + # traceback to the stderr. command.execute = raise_command_error err.truncate(0) with self.assertRaises(SystemExit): @@ -1320,12 +1322,12 @@ class CommandTypes(AdminScriptTestCase): self.assertNotIn("Traceback", err_message) self.assertIn("CommandError", err_message) + # If the Exception is CommandError and --traceback is present + # this command should raise the original CommandError as if it + # were not a CommandError. err.truncate(0) - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): command.run_from_argv(['', '', '--traceback']) - err_message = err.getvalue() - self.assertIn("Traceback (most recent call last)", err_message) - self.assertIn("CommandError", err_message) finally: sys.stderr = old_stderr