Fixed #19877 -- Added `--no-color` option to `BaseCommand` to avoid using output styles.

This commit is contained in:
Jose L. Patino 2013-02-23 16:28:45 +01:00 committed by Tim Graham
parent d4dd55e78c
commit 7b57e575c9
5 changed files with 67 additions and 23 deletions

View File

@ -10,7 +10,7 @@ from optparse import make_option, OptionParser
import django import django
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style from django.core.management.color import color_style, no_style
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.six import StringIO from django.utils.six import StringIO
@ -171,6 +171,8 @@ class BaseCommand(object):
help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'), help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
make_option('--traceback', action='store_true', make_option('--traceback', action='store_true',
help='Raise on exception'), help='Raise on exception'),
make_option('--no-color', action='store_true', dest='no_color', default=False,
help="Don't colorize the command output."),
) )
help = '' help = ''
args = '' args = ''
@ -254,6 +256,10 @@ class BaseCommand(object):
``self.requires_model_validation``, except if force-skipped). ``self.requires_model_validation``, except if force-skipped).
""" """
self.stdout = OutputWrapper(options.get('stdout', sys.stdout)) self.stdout = OutputWrapper(options.get('stdout', sys.stdout))
if options.get('no_color'):
self.style = no_style()
self.stderr = OutputWrapper(options.get('stderr', sys.stderr))
else:
self.stderr = OutputWrapper(options.get('stderr', sys.stderr), self.style.ERROR) self.stderr = OutputWrapper(options.get('stderr', sys.stderr), self.style.ERROR)
if self.can_import_settings: if self.can_import_settings:

View File

@ -30,7 +30,7 @@ def color_style():
class dummy: pass class dummy: pass
style = dummy() style = dummy()
# The nocolor palette has all available roles. # The nocolor palette has all available roles.
# Use that pallete as the basis for populating # Use that palette as the basis for populating
# the palette as defined in the environment. # the palette as defined in the environment.
for role in termcolors.PALETTES[termcolors.NOCOLOR_PALETTE]: for role in termcolors.PALETTES[termcolors.NOCOLOR_PALETTE]:
format = color_settings.get(role,{}) format = color_settings.get(role,{})

View File

@ -1429,6 +1429,19 @@ that ``django-admin.py`` should print to the console.
* ``2`` means verbose output. * ``2`` means verbose output.
* ``3`` means *very* verbose output. * ``3`` means *very* verbose output.
.. django-admin-option:: --no-color
.. versionadded:: 1.7
Example usage::
django-admin.py sqlall --no-color
By default, ``django-admin.py`` will format the output to be colorized. For
example, errors will be printed to the console in red and SQL statements will
be syntax highlighted. To prevent this and have a plain text output, pass the
``--no-color`` option when running your command.
Common options Common options
============== ==============

View File

@ -92,6 +92,9 @@ Minor features
* :func:`~django.core.mail.send_mail` now accepts an ``html_message`` * :func:`~django.core.mail.send_mail` now accepts an ``html_message``
parameter for sending a multipart ``text/plain`` and ``text/html`` email. parameter for sending a multipart ``text/plain`` and ``text/html`` email.
* The :djadminopt:`--no-color` option for ``django-admin.py`` allows you to
disable the colorization of management command output.
Backwards incompatible changes in 1.7 Backwards incompatible changes in 1.7
===================================== =====================================

View File

@ -18,7 +18,7 @@ import unittest
import django import django
from django import conf, get_version from django import conf, get_version
from django.conf import settings from django.conf import settings
from django.core.management import BaseCommand, CommandError 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.utils.encoding import force_text from django.utils.encoding import force_text
@ -922,14 +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=[('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]")
self.assertNoOutput(err)
def test_custom_command_output_color(self):
"alternate: manage.py output syntax color can be deactivated with the `--no-color` option"
args = ['noargs_command', '--no-color', '--settings=alternate_settings']
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.assertNoOutput(err) self.assertNoOutput(err)
@ -1272,40 +1279,55 @@ class CommandTypes(AdminScriptTestCase):
self.assertNoOutput(err) self.assertNoOutput(err)
self.assertOutput(out, "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s).") self.assertOutput(out, "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s).")
def test_no_color(self):
"--no-color prevent colorization of the output"
out = StringIO()
call_command("sqlall", "admin_scripts", no_color=True, stdout=out)
self.assertEqual(out.getvalue(), """BEGIN;
CREATE TABLE "admin_scripts_article" (
"id" integer NOT NULL PRIMARY KEY,
"headline" varchar(100) NOT NULL,
"pub_date" datetime NOT NULL
)
;
COMMIT;
""")
def test_base_command(self): def test_base_command(self):
"User BaseCommands can execute when a label is provided" "User BaseCommands can execute when a label is provided"
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=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") 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')]")
def test_base_run_from_argv(self): def test_base_run_from_argv(self):
""" """
@ -1351,7 +1373,7 @@ class CommandTypes(AdminScriptTestCase):
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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "EXECUTE:NoArgsCommand options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '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"
@ -1366,7 +1388,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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '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"
@ -1381,10 +1403,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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "'>, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '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"
@ -1403,7 +1425,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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '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"
@ -1416,8 +1438,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=[('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]") self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('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, "EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', '1')]")
class ArgumentOrder(AdminScriptTestCase): class ArgumentOrder(AdminScriptTestCase):
"""Tests for 2-stage argument parsing scheme. """Tests for 2-stage argument parsing scheme.
@ -1441,35 +1463,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=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") 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')]")
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=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]") 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')]")
class StartProject(LiveServerTestCase, AdminScriptTestCase): class StartProject(LiveServerTestCase, AdminScriptTestCase):