From 80d8e3cff9c05d24346620f2d2f77539c347775f Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Sun, 12 Jul 2020 18:45:13 -0300 Subject: [PATCH 1/6] Add constants and a method to set defaults --- .../management/commands/print_settings.py | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index d02340067..a4be2340d 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -8,11 +8,14 @@ import json -from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django_extensions.management.utils import signalcommand +DEFAULT_FORMAT = 'simple' +DEFAULT_INDENT = 4 +DEFAULT_SECRETS = False + class Command(BaseCommand): help = "Print the active Django settings." @@ -26,34 +29,37 @@ def add_arguments(self, parser): ) parser.add_argument( '--format', - default='simple', + default=DEFAULT_FORMAT, dest='format', help='Specifies output format.' ) parser.add_argument( '--indent', - default=4, + default=DEFAULT_INDENT, dest='indent', type=int, help='Specifies indent level for JSON and YAML' ) + parser.add_argument( + '--show-secrets', + default=DEFAULT_SECRETS, + dest='show secrets', + type=bool, + help='Specifies if should be reveald the value of secrets' + ) @signalcommand def handle(self, *args, **options): + + show_secrets, output_format, indent = self.get_defaults(options) + a_dict = {} - for attr in dir(settings): - if self.include_attr(attr, options['setting']): - value = getattr(settings, attr) - a_dict[attr] = value for setting in args: if setting not in a_dict: raise CommandError('%s not found in settings.' % setting) - output_format = options['format'] - indent = options['indent'] - if output_format == 'json': print(json.dumps(a_dict, indent=indent)) elif output_format == 'yaml': @@ -71,6 +77,15 @@ def handle(self, *args, **options): else: self.print_simple(a_dict) + @staticmethod + def get_defaults(options): + a_options = [ + options.get('show secrets', DEFAULT_SECRETS), + options.get('format', DEFAULT_FORMAT), + options.get('indent', DEFAULT_INDENT) + ] + return a_options + @staticmethod def include_attr(attr, settings): if attr.startswith('__'): From b940a1dfbeeed8b2840b2de366ec0bfe76bb951b Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Sun, 12 Jul 2020 18:45:54 -0300 Subject: [PATCH 2/6] Add method to hide secrets --- .../management/commands/print_settings.py | 12 ++++++++++++ tests/management/commands/test_print_settings.py | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index a4be2340d..65c501e6c 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -8,9 +8,11 @@ import json +from django.conf import settings as default_settings from django.core.management.base import BaseCommand, CommandError from django_extensions.management.utils import signalcommand +from django.views.debug import SafeExceptionReporterFilter DEFAULT_FORMAT = 'simple' DEFAULT_INDENT = 4 @@ -55,6 +57,16 @@ def handle(self, *args, **options): a_dict = {} + if show_secrets: + for attr in dir(default_settings): + if self.include_attr(attr, options['setting']): + value = getattr(default_settings, attr) + a_dict[attr] = value + else: + settings = SafeExceptionReporterFilter().get_safe_settings() + for key in settings.keys(): + if key in options['setting'] or not options['setting']: + a_dict[key] = settings.get(key) for setting in args: if setting not in a_dict: diff --git a/tests/management/commands/test_print_settings.py b/tests/management/commands/test_print_settings.py index 47bce8d9f..907010eb3 100644 --- a/tests/management/commands/test_print_settings.py +++ b/tests/management/commands/test_print_settings.py @@ -26,6 +26,7 @@ def test_with_multiple_setting_args(capsys): 'SECRET_KEY', 'DATABASES', 'INSTALLED_APPS', + '--show-secrets=True' ) out, err = capsys.readouterr() @@ -34,6 +35,16 @@ def test_with_multiple_setting_args(capsys): assert 'DATABASES' in out assert 'INSTALLED_APPS' in out +def test_with_not_show_secrets(capsys): + call_command( + 'print_settings', + 'SECRET_KEY', + ) + + out, err = capsys.readouterr() + + assert '*******' in out + def test_format(capsys): call_command( From 10132b8dfe0801bfd47c3921eb6c637679da98bf Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Sun, 12 Jul 2020 18:48:27 -0300 Subject: [PATCH 3/6] Run black and isort --- .../management/commands/print_settings.py | 54 +++++++++---------- .../commands/test_print_settings.py | 47 ++++++++-------- 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index 65c501e6c..0328f3cd4 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -10,11 +10,11 @@ from django.conf import settings as default_settings from django.core.management.base import BaseCommand, CommandError +from django.views.debug import SafeExceptionReporterFilter from django_extensions.management.utils import signalcommand -from django.views.debug import SafeExceptionReporterFilter -DEFAULT_FORMAT = 'simple' +DEFAULT_FORMAT = "simple" DEFAULT_INDENT = 4 DEFAULT_SECRETS = False @@ -25,29 +25,27 @@ class Command(BaseCommand): def add_arguments(self, parser): super().add_arguments(parser) parser.add_argument( - 'setting', - nargs='*', - help='Specifies setting to be printed.' + "setting", nargs="*", help="Specifies setting to be printed." ) parser.add_argument( - '--format', + "--format", default=DEFAULT_FORMAT, - dest='format', - help='Specifies output format.' + dest="format", + help="Specifies output format.", ) parser.add_argument( - '--indent', + "--indent", default=DEFAULT_INDENT, - dest='indent', + dest="indent", type=int, - help='Specifies indent level for JSON and YAML' + help="Specifies indent level for JSON and YAML", ) parser.add_argument( - '--show-secrets', + "--show-secrets", default=DEFAULT_SECRETS, - dest='show secrets', + dest="show secrets", type=bool, - help='Specifies if should be reveald the value of secrets' + help="Specifies if should be reveald the value of secrets", ) @signalcommand @@ -59,31 +57,33 @@ def handle(self, *args, **options): if show_secrets: for attr in dir(default_settings): - if self.include_attr(attr, options['setting']): + if self.include_attr(attr, options["setting"]): value = getattr(default_settings, attr) a_dict[attr] = value else: settings = SafeExceptionReporterFilter().get_safe_settings() for key in settings.keys(): - if key in options['setting'] or not options['setting']: + if key in options["setting"] or not options["setting"]: a_dict[key] = settings.get(key) for setting in args: if setting not in a_dict: - raise CommandError('%s not found in settings.' % setting) + raise CommandError("%s not found in settings." % setting) - if output_format == 'json': + if output_format == "json": print(json.dumps(a_dict, indent=indent)) - elif output_format == 'yaml': + elif output_format == "yaml": import yaml # requires PyYAML + print(yaml.dump(a_dict, indent=indent)) - elif output_format == 'pprint': + elif output_format == "pprint": from pprint import pprint + pprint(a_dict) - elif output_format == 'text': + elif output_format == "text": for key, value in a_dict.items(): print("%s = %s" % (key, value)) - elif output_format == 'value': + elif output_format == "value": for value in a_dict.values(): print(value) else: @@ -92,15 +92,15 @@ def handle(self, *args, **options): @staticmethod def get_defaults(options): a_options = [ - options.get('show secrets', DEFAULT_SECRETS), - options.get('format', DEFAULT_FORMAT), - options.get('indent', DEFAULT_INDENT) + options.get("show secrets", DEFAULT_SECRETS), + options.get("format", DEFAULT_FORMAT), + options.get("indent", DEFAULT_INDENT), ] return a_options @staticmethod def include_attr(attr, settings): - if attr.startswith('__'): + if attr.startswith("__"): return False elif settings == []: return True @@ -110,4 +110,4 @@ def include_attr(attr, settings): @staticmethod def print_simple(a_dict): for key, value in a_dict.items(): - print('%-40s = %r' % (key, value)) + print("%-40s = %r" % (key, value)) diff --git a/tests/management/commands/test_print_settings.py b/tests/management/commands/test_print_settings.py index 907010eb3..f9dbbe05e 100644 --- a/tests/management/commands/test_print_settings.py +++ b/tests/management/commands/test_print_settings.py @@ -5,65 +5,60 @@ def test_without_args(capsys): - call_command('print_settings') + call_command("print_settings") out, err = capsys.readouterr() - assert 'DEBUG' in out - assert 'INSTALLED_APPS' in out + assert "DEBUG" in out + assert "INSTALLED_APPS" in out def test_with_setting_args(capsys): - call_command('print_settings', 'DEBUG') + call_command("print_settings", "DEBUG") out, err = capsys.readouterr() - assert 'DEBUG' in out - assert 'INSTALLED_APPS' not in out + assert "DEBUG" in out + assert "INSTALLED_APPS" not in out def test_with_multiple_setting_args(capsys): call_command( - 'print_settings', - 'SECRET_KEY', - 'DATABASES', - 'INSTALLED_APPS', - '--show-secrets=True' + "print_settings", + "SECRET_KEY", + "DATABASES", + "INSTALLED_APPS", + "--show-secrets=True", ) out, err = capsys.readouterr() - assert 'DEBUG' not in out - assert 'SECRET_KEY' in out - assert 'DATABASES' in out - assert 'INSTALLED_APPS' in out + assert "DEBUG" not in out + assert "SECRET_KEY" in out + assert "DATABASES" in out + assert "INSTALLED_APPS" in out + def test_with_not_show_secrets(capsys): call_command( - 'print_settings', - 'SECRET_KEY', + "print_settings", "SECRET_KEY", ) out, err = capsys.readouterr() - assert '*******' in out + assert "*******" in out def test_format(capsys): call_command( - 'print_settings', - 'DEBUG', - '--format=text', + "print_settings", "DEBUG", "--format=text", ) out, err = capsys.readouterr() - expected = 'DEBUG = False\n' + expected = "DEBUG = False\n" assert expected == out def test_format_json_without_indent(capsys): call_command( - 'print_settings', - 'DEBUG', - '--format=json', - '--indent=0', + "print_settings", "DEBUG", "--format=json", "--indent=0", ) expected = '{\n"DEBUG": false\n}\n' From 7291e8138fc8bf7dd3871fb7c4ba7d97dd7a5aa9 Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Fri, 24 Jul 2020 08:58:38 -0300 Subject: [PATCH 4/6] fix typo --- django_extensions/management/commands/print_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index 0328f3cd4..a17502a51 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -45,7 +45,7 @@ def add_arguments(self, parser): default=DEFAULT_SECRETS, dest="show secrets", type=bool, - help="Specifies if should be reveald the value of secrets", + help="Specifies if should be revealed the value of secrets", ) @signalcommand From 0cd8171c002e1fbb997f1ab9196c60b8e36ccf29 Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Fri, 24 Jul 2020 08:59:45 -0300 Subject: [PATCH 5/6] change import of get safe settings for django <= 2.2 --- .../management/commands/print_settings.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index a17502a51..d84d3af00 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -61,7 +61,7 @@ def handle(self, *args, **options): value = getattr(default_settings, attr) a_dict[attr] = value else: - settings = SafeExceptionReporterFilter().get_safe_settings() + settings = self.safe_settings() for key in settings.keys(): if key in options["setting"] or not options["setting"]: a_dict[key] = settings.get(key) @@ -111,3 +111,13 @@ def include_attr(attr, settings): def print_simple(a_dict): for key, value in a_dict.items(): print("%-40s = %r" % (key, value)) + + @staticmethod + def safe_settings(): + try: + return SafeExceptionReporterFilter().get_safe_settings() + except AttributeError: + # In django < 3.0 does not have this class + # We have to make a different import + from django.views.debug import get_safe_settings + return get_safe_settings() From a54fa42902aa331766db5aea9e27672e14f3a8f7 Mon Sep 17 00:00:00 2001 From: Lucas Hiago Date: Fri, 24 Jul 2020 10:03:31 -0300 Subject: [PATCH 6/6] add --database option on print settings --- .../management/commands/print_settings.py | 25 ++++++++++++++++++- .../commands/test_print_settings.py | 10 ++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index d84d3af00..9383a4923 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -47,11 +47,17 @@ def add_arguments(self, parser): type=bool, help="Specifies if should be revealed the value of secrets", ) + parser.add_argument( + "--database", + dest="show database", + action="store_true", + help="Shows the current database engine", + ) @signalcommand def handle(self, *args, **options): - show_secrets, output_format, indent = self.get_defaults(options) + show_secrets, output_format, indent, show_database = self.get_defaults(options) a_dict = {} @@ -66,6 +72,12 @@ def handle(self, *args, **options): if key in options["setting"] or not options["setting"]: a_dict[key] = settings.get(key) + if show_database: + database = self.safe_settings().get('DATABASES', None) + if database: + engine = database['default']['ENGINE'] + a_dict['DATABASE_ENGINE'] = self.get_database(engine) + for setting in args: if setting not in a_dict: raise CommandError("%s not found in settings." % setting) @@ -95,6 +107,7 @@ def get_defaults(options): options.get("show secrets", DEFAULT_SECRETS), options.get("format", DEFAULT_FORMAT), options.get("indent", DEFAULT_INDENT), + options.get("show database", None) ] return a_options @@ -121,3 +134,13 @@ def safe_settings(): # We have to make a different import from django.views.debug import get_safe_settings return get_safe_settings() + + @staticmethod + def get_database(engine): + db_backend_options = { + 'django.db.backends.postgresql': 'PostgreSQL', + 'django.db.backends.sqlite3': 'SQLite', + 'django.db.backends.oracle': 'Oracle', + 'django.db.backends.mysql': 'MySQL/MariaDB', + } + return db_backend_options.get(engine, 'UNKNOWN') diff --git a/tests/management/commands/test_print_settings.py b/tests/management/commands/test_print_settings.py index f9dbbe05e..7d52d1614 100644 --- a/tests/management/commands/test_print_settings.py +++ b/tests/management/commands/test_print_settings.py @@ -10,6 +10,7 @@ def test_without_args(capsys): out, err = capsys.readouterr() assert "DEBUG" in out assert "INSTALLED_APPS" in out + assert "DATABASE_ENGINE" not in out def test_with_setting_args(capsys): @@ -64,3 +65,12 @@ def test_format_json_without_indent(capsys): expected = '{\n"DEBUG": false\n}\n' out, err = capsys.readouterr() assert expected == out + + +def test_show_database_option(capsys): + call_command( + "print_settings", "--database", + ) + + out, err = capsys.readouterr() + assert "DATABASE_ENGINE" in out