summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lamb <chris@chris-lamb.co.uk>2017-03-08 08:54:17 +0000
committerTim Graham <timograham@gmail.com>2017-05-27 09:00:06 -0400
commit2f09a285582cb475a9d27067808d9beefa7f9fba (patch)
treea53b600fa4f242dcb9626c12535b19bb50d46e37
parentaf1fa5e7da21c57a4037e67f93493af4e78d454a (diff)
Fixed #27881 -- Added diffsettings --output option.
Thanks Haris Ibrahim K. V. for writng docs.
-rw-r--r--django/core/management/commands/diffsettings.py40
-rw-r--r--docs/ref/django-admin.txt10
-rw-r--r--docs/releases/2.0.txt3
-rw-r--r--tests/admin_scripts/tests.py26
4 files changed, 74 insertions, 5 deletions
diff --git a/django/core/management/commands/diffsettings.py b/django/core/management/commands/diffsettings.py
index cc3e32b6a5..5d1621eb08 100644
--- a/django/core/management/commands/diffsettings.py
+++ b/django/core/management/commands/diffsettings.py
@@ -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
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 68fb762623..7f120c28b3 100644
--- a/docs/ref/django-admin.txt
+++ b/docs/ref/django-admin.txt
@@ -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``
------------
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index de5b38a098..ee9ae181b4 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -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
~~~~~~~~~~
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py
index fa7f9e060e..f52eac6761 100644
--- a/tests/admin_scripts/tests.py
+++ b/tests/admin_scripts/tests.py
@@ -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."""