Fixed #27881 -- Added diffsettings --output option.

Thanks Haris Ibrahim K. V. for writng docs.
This commit is contained in:
Chris Lamb 2017-03-08 08:54:17 +00:00 committed by Tim Graham
parent af1fa5e7da
commit 2f09a28558
4 changed files with 74 additions and 5 deletions

View File

@ -8,15 +8,17 @@ def module_to_dict(module, omittable=lambda k: k.startswith('_')):
class Command(BaseCommand):
help = """Displays differences between the current settings.py and Django's
default settings. Settings that don't appear in the defaults are
followed by "###"."""
default settings."""
requires_system_checks = False
def add_arguments(self, parser):
parser.add_argument(
'--all', action='store_true', dest='all',
help='Display all settings, regardless of their value. Default values are prefixed by "###".',
help=(
'Display all settings, regardless of their value. In "hash" '
'mode, default values are prefixed by "###".'
),
)
parser.add_argument(
'--default', dest='default', metavar='MODULE', default=None,
@ -25,9 +27,18 @@ class Command(BaseCommand):
"compare against Django's default settings."
),
)
parser.add_argument(
'--output', default='hash', choices=('hash', 'unified'), dest='output',
help=(
"Selects the output format. 'hash' mode displays each changed "
"setting, with the settings that don't appear in the defaults "
"followed by ###. 'unified' mode prefixes the default setting "
"with a minus sign, followed by the changed setting prefixed "
"with a plus sign."
),
)
def handle(self, **options):
# Inspired by Postfix's "postconf -n".
from django.conf import settings, Settings, global_settings
# Because settings are imported lazily, we need to explicitly load them.
@ -36,7 +47,14 @@ class Command(BaseCommand):
user_settings = module_to_dict(settings._wrapped)
default = options['default']
default_settings = module_to_dict(Settings(default) if default else global_settings)
output_func = {
'hash': self.output_hash,
'unified': self.output_unified,
}[options['output']]
return '\n'.join(output_func(user_settings, default_settings, **options))
def output_hash(self, user_settings, default_settings, **options):
# Inspired by Postfix's "postconf -n".
output = []
for key in sorted(user_settings):
if key not in default_settings:
@ -45,4 +63,16 @@ class Command(BaseCommand):
output.append("%s = %s" % (key, user_settings[key]))
elif options['all']:
output.append("### %s = %s" % (key, user_settings[key]))
return '\n'.join(output)
return output
def output_unified(self, user_settings, default_settings, **options):
output = []
for key in sorted(user_settings):
if key not in default_settings:
output.append(self.style.SUCCESS("+ %s = %s" % (key, user_settings[key])))
elif user_settings[key] != default_settings[key]:
output.append(self.style.ERROR("- %s = %s" % (key, default_settings[key])))
output.append(self.style.SUCCESS("+ %s = %s" % (key, user_settings[key])))
elif options['all']:
output.append(" %s = %s" % (key, user_settings[key]))
return output

View File

@ -240,6 +240,16 @@ are prefixed by ``"###"``.
The settings module to compare the current settings against. Leave empty to
compare against Django's default settings.
.. django-admin-option:: --output {hash,unified}
.. versionadded:: 2.0
Specifies the output format. Available values are ``hash`` and ``unified``.
``hash`` is the default mode that displays the output that's described above.
``unified`` displays the output similar to ``diff -u``. Default settings are
prefixed with a minus sign, followed by the changed setting prefixed with a
plus sign.
``dumpdata``
------------

View File

@ -187,6 +187,9 @@ Management Commands
* :djadmin:`loaddata` can now :ref:`read from stdin <loading-fixtures-stdin>`.
* The new :option:`diffsettings --output` option allows formatting the output
in a unified diff format.
Migrations
~~~~~~~~~~

View File

@ -2120,6 +2120,32 @@ class DiffSettings(AdminScriptTestCase):
self.assertNotInOutput(out, "FOO")
self.assertOutput(out, "BAR = 'bar2'")
def test_unified(self):
"""--output=unified emits settings diff in unified mode."""
self.write_settings('settings_to_diff.py', sdict={'FOO': '"bar"'})
self.addCleanup(self.remove_settings, 'settings_to_diff.py')
args = ['diffsettings', '--settings=settings_to_diff', '--output=unified']
out, err = self.run_manage(args)
self.assertNoOutput(err)
self.assertOutput(out, "+ FOO = 'bar'")
self.assertOutput(out, "- SECRET_KEY = ''")
self.assertOutput(out, "+ SECRET_KEY = 'django_tests_secret_key'")
self.assertNotInOutput(out, " APPEND_SLASH = True")
def test_unified_all(self):
"""
--output=unified --all emits settings diff in unified mode and includes
settings with the default value.
"""
self.write_settings('settings_to_diff.py', sdict={'FOO': '"bar"'})
self.addCleanup(self.remove_settings, 'settings_to_diff.py')
args = ['diffsettings', '--settings=settings_to_diff', '--output=unified', '--all']
out, err = self.run_manage(args)
self.assertNoOutput(err)
self.assertOutput(out, " APPEND_SLASH = True")
self.assertOutput(out, "+ FOO = 'bar'")
self.assertOutput(out, "- SECRET_KEY = ''")
class Dumpdata(AdminScriptTestCase):
"""Tests for dumpdata management command."""