From ba9cf9596bb07d30614257a755f3e4fea426d2e2 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Mon, 14 Oct 2013 20:24:57 +0200 Subject: [PATCH] [1.6.x] Fixed #21269 -- Don't crash when CommandError contains non-ascii Thanks kontakt@eikefoken.de for the report. Backport of 42a67ec1cd from master. --- django/core/management/base.py | 2 ++ tests/admin_scripts/tests.py | 54 ++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/django/core/management/base.py b/django/core/management/base.py index af040288d0..74f3913836 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -3,6 +3,8 @@ Base classes for writing management commands (named commands which can be executed through ``django-admin.py`` or ``manage.py``). """ +from __future__ import unicode_literals + import os import sys diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 67cb3343f6..a6f7845b20 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -20,6 +20,7 @@ from django.conf import settings from django.core.management import BaseCommand, CommandError from django.db import connection from django.test.runner import DiscoverRunner +from django.test.utils import str_prefix from django.utils import unittest from django.utils.encoding import force_text from django.utils._os import upath @@ -921,14 +922,14 @@ class ManageAlternateSettings(AdminScriptTestCase): "alternate: manage.py can execute user commands if settings are provided as argument" args = ['noargs_command', '--settings=alternate_settings'] out, err = self.run_manage(args) - self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) self.assertNoOutput(err) def test_custom_command_with_environment(self): "alternate: manage.py can execute user commands if settings are provided in environment" args = ['noargs_command'] out, err = self.run_manage(args, 'alternate_settings') - self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) self.assertNoOutput(err) @@ -1277,35 +1278,35 @@ class CommandTypes(AdminScriptTestCase): args = ['base_command', 'testlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_base_command_no_label(self): "User BaseCommands can execute when no labels are provided" args = ['base_command'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=(), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=(), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_base_command_multiple_label(self): "User BaseCommands can execute when no labels are provided" args = ['base_command', 'testlabel', 'anotherlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel', 'anotherlabel'), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel', 'anotherlabel'), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_base_command_with_option(self): "User BaseCommands can execute with options when a label is provided" args = ['base_command', 'testlabel', '--option_a=x'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_base_command_with_options(self): "User BaseCommands can execute with multiple options when a label is provided" args = ['base_command', 'testlabel', '-a', 'x', '--option_b=y'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_base_run_from_argv(self): """ @@ -1346,12 +1347,27 @@ class CommandTypes(AdminScriptTestCase): finally: sys.stderr = old_stderr + def test_run_from_argv_non_ascii_error(self): + """ + Test that non-ascii message of CommandError does not raise any + UnicodeDecodeError in run_from_argv. + """ + def raise_command_error(*args, **kwargs): + raise CommandError("Erreur personnalisée") + + command = BaseCommand() + command.execute = raise_command_error + command.stderr = StringIO() + + with self.assertRaises(SystemExit): + command.run_from_argv(['', '']) + def test_noargs(self): "NoArg Commands can be executed" args = ['noargs_command'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_noargs_with_args(self): "NoArg Commands raise an error if an argument is provided" @@ -1366,7 +1382,7 @@ class CommandTypes(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:AppCommand app=, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("'>, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_app_command_no_apps(self): "User AppCommands raise an error when no app name is provided" @@ -1381,10 +1397,10 @@ class CommandTypes(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:AppCommand app=, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("'>, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) self.assertOutput(out, "EXECUTE:AppCommand app=, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("'>, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_app_command_invalid_appname(self): "User AppCommands can execute when a single app name is provided" @@ -1403,7 +1419,7 @@ class CommandTypes(AdminScriptTestCase): args = ['label_command', 'testlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=testlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_label_command_no_label(self): "User LabelCommands raise an error if no label is provided" @@ -1416,8 +1432,8 @@ class CommandTypes(AdminScriptTestCase): args = ['label_command', 'testlabel', 'anotherlabel'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") - self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=testlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) + self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=anotherlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) class ArgumentOrder(AdminScriptTestCase): """Tests for 2-stage argument parsing scheme. @@ -1441,35 +1457,35 @@ class ArgumentOrder(AdminScriptTestCase): args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_setting_then_short_option(self): "Short options passed after settings are correctly handled" args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_option_then_setting(self): "Options passed before settings are correctly handled" args = ['base_command', 'testlabel', '--option_a=x', '--settings=alternate_settings'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_short_option_then_setting(self): "Short options passed before settings are correctly handled" args = ['base_command', 'testlabel', '-a', 'x', '--settings=alternate_settings'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) def test_option_then_setting_then_option(self): "Options are correctly handled when they are passed before and after a setting" args = ['base_command', 'testlabel', '--option_a=x', '--settings=alternate_settings', '--option_b=y'] out, err = self.run_manage(args) self.assertNoOutput(err) - self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") + self.assertOutput(out, str_prefix("EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) class StartProject(LiveServerTestCase, AdminScriptTestCase):