mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #21269 -- Don't crash when CommandError contains non-ascii
Thanks kontakt@eikefoken.de for the report.
This commit is contained in:
		| @@ -3,6 +3,8 @@ Base classes for writing management commands (named commands which can | |||||||
| be executed through ``django-admin.py`` or ``manage.py``). | be executed through ``django-admin.py`` or ``manage.py``). | ||||||
|  |  | ||||||
| """ | """ | ||||||
|  | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ from django.conf import settings | |||||||
| from django.core.management import BaseCommand, CommandError, call_command | from django.core.management import BaseCommand, CommandError, call_command | ||||||
| from django.db import connection | from django.db import connection | ||||||
| from django.test.runner import DiscoverRunner | from django.test.runner import DiscoverRunner | ||||||
|  | from django.test.utils import str_prefix | ||||||
| from django.utils.encoding import force_text | from django.utils.encoding import force_text | ||||||
| from django.utils._os import upath | from django.utils._os import upath | ||||||
| from django.utils.six import StringIO | from django.utils.six import StringIO | ||||||
| @@ -921,21 +922,21 @@ class ManageAlternateSettings(AdminScriptTestCase): | |||||||
|         "alternate: manage.py can execute user commands if settings are provided as argument" |         "alternate: manage.py can execute user commands if settings are provided as argument" | ||||||
|         args = ['noargs_command', '--settings=alternate_settings'] |         args = ['noargs_command', '--settings=alternate_settings'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|  |  | ||||||
|     def test_custom_command_with_environment(self): |     def test_custom_command_with_environment(self): | ||||||
|         "alternate: manage.py can execute user commands if settings are provided in environment" |         "alternate: manage.py can execute user commands if settings are provided in environment" | ||||||
|         args = ['noargs_command'] |         args = ['noargs_command'] | ||||||
|         out, err = self.run_manage(args, 'alternate_settings') |         out, err = self.run_manage(args, 'alternate_settings') | ||||||
|         self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|  |  | ||||||
|     def test_custom_command_output_color(self): |     def test_custom_command_output_color(self): | ||||||
|         "alternate: manage.py output syntax color can be deactivated with the `--no-color` option" |         "alternate: manage.py output syntax color can be deactivated with the `--no-color` option" | ||||||
|         args = ['noargs_command', '--no-color', '--settings=alternate_settings'] |         args = ['noargs_command', '--no-color', '--settings=alternate_settings'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', True), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('no_color', True), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1290,35 +1291,35 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         args = ['base_command', 'testlabel'] |         args = ['base_command', 'testlabel'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_base_command_no_label(self): | ||||||
|         "User BaseCommands can execute when no labels are provided" |         "User BaseCommands can execute when no labels are provided" | ||||||
|         args = ['base_command'] |         args = ['base_command'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=(), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_base_command_multiple_label(self): | ||||||
|         "User BaseCommands can execute when no labels are provided" |         "User BaseCommands can execute when no labels are provided" | ||||||
|         args = ['base_command', 'testlabel', 'anotherlabel'] |         args = ['base_command', 'testlabel', 'anotherlabel'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel', 'anotherlabel'), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_base_command_with_option(self): | ||||||
|         "User BaseCommands can execute with options when a label is provided" |         "User BaseCommands can execute with options when a label is provided" | ||||||
|         args = ['base_command', 'testlabel', '--option_a=x'] |         args = ['base_command', 'testlabel', '--option_a=x'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_base_command_with_options(self): | ||||||
|         "User BaseCommands can execute with multiple options when a label is provided" |         "User BaseCommands can execute with multiple options when a label is provided" | ||||||
|         args = ['base_command', 'testlabel', '-a', 'x', '--option_b=y'] |         args = ['base_command', 'testlabel', '-a', 'x', '--option_b=y'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_base_run_from_argv(self): | ||||||
|         """ |         """ | ||||||
| @@ -1359,12 +1360,27 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         finally: |         finally: | ||||||
|             sys.stderr = old_stderr |             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): |     def test_noargs(self): | ||||||
|         "NoArg Commands can be executed" |         "NoArg Commands can be executed" | ||||||
|         args = ['noargs_command'] |         args = ['noargs_command'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
|     def test_noargs_with_args(self): |     def test_noargs_with_args(self): | ||||||
|         "NoArg Commands raise an error if an argument is provided" |         "NoArg Commands raise an error if an argument is provided" | ||||||
| @@ -1379,7 +1395,7 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.auth.models'") |         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.auth.models'") | ||||||
|         self.assertOutput(out, os.sep.join(['django', 'contrib', 'auth', 'models.py'])) |         self.assertOutput(out, os.sep.join(['django', 'contrib', 'auth', 'models.py'])) | ||||||
|         self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
|     def test_app_command_no_apps(self): |     def test_app_command_no_apps(self): | ||||||
|         "User AppCommands raise an error when no app name is provided" |         "User AppCommands raise an error when no app name is provided" | ||||||
| @@ -1394,10 +1410,10 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.auth.models'") |         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.auth.models'") | ||||||
|         self.assertOutput(out, os.sep.join(['django', 'contrib', 'auth', 'models.py'])) |         self.assertOutput(out, os.sep.join(['django', 'contrib', 'auth', 'models.py'])) | ||||||
|         self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.contenttypes.models'") |         self.assertOutput(out, "EXECUTE:AppCommand app=<module 'django.contrib.contenttypes.models'") | ||||||
|         self.assertOutput(out, os.sep.join(['django', 'contrib', 'contenttypes', 'models.py'])) |         self.assertOutput(out, os.sep.join(['django', 'contrib', 'contenttypes', 'models.py'])) | ||||||
|         self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
|     def test_app_command_invalid_appname(self): |     def test_app_command_invalid_appname(self): | ||||||
|         "User AppCommands can execute when a single app name is provided" |         "User AppCommands can execute when a single app name is provided" | ||||||
| @@ -1416,7 +1432,7 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         args = ['label_command', 'testlabel'] |         args = ['label_command', 'testlabel'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
|     def test_label_command_no_label(self): |     def test_label_command_no_label(self): | ||||||
|         "User LabelCommands raise an error if no label is provided" |         "User LabelCommands raise an error if no label is provided" | ||||||
| @@ -1429,8 +1445,8 @@ class CommandTypes(AdminScriptTestCase): | |||||||
|         args = ['label_command', 'testlabel', 'anotherlabel'] |         args = ['label_command', 'testlabel', 'anotherlabel'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|         self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") |         self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
| class ArgumentOrder(AdminScriptTestCase): | class ArgumentOrder(AdminScriptTestCase): | ||||||
|     """Tests for 2-stage argument parsing scheme. |     """Tests for 2-stage argument parsing scheme. | ||||||
| @@ -1454,35 +1470,35 @@ class ArgumentOrder(AdminScriptTestCase): | |||||||
|         args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] |         args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_setting_then_short_option(self): | ||||||
|         "Short options passed after settings are correctly handled" |         "Short options passed after settings are correctly handled" | ||||||
|         args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] |         args = ['base_command', 'testlabel', '--settings=alternate_settings', '--option_a=x'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_option_then_setting(self): | ||||||
|         "Options passed before settings are correctly handled" |         "Options passed before settings are correctly handled" | ||||||
|         args = ['base_command', 'testlabel', '--option_a=x', '--settings=alternate_settings'] |         args = ['base_command', 'testlabel', '--option_a=x', '--settings=alternate_settings'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_short_option_then_setting(self): | ||||||
|         "Short options passed before settings are correctly handled" |         "Short options passed before settings are correctly handled" | ||||||
|         args = ['base_command', 'testlabel', '-a', 'x', '--settings=alternate_settings'] |         args = ['base_command', 'testlabel', '-a', 'x', '--settings=alternate_settings'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('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): |     def test_option_then_setting_then_option(self): | ||||||
|         "Options are correctly handled when they are passed before and after a setting" |         "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'] |         args = ['base_command', 'testlabel', '--option_a=x', '--settings=alternate_settings', '--option_b=y'] | ||||||
|         out, err = self.run_manage(args) |         out, err = self.run_manage(args) | ||||||
|         self.assertNoOutput(err) |         self.assertNoOutput(err) | ||||||
|         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('no_color', False), ('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=[('no_color', False), ('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', %(_)s'1')]")) | ||||||
|  |  | ||||||
|  |  | ||||||
| class StartProject(LiveServerTestCase, AdminScriptTestCase): | class StartProject(LiveServerTestCase, AdminScriptTestCase): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user