Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[feat] Database Option #1559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 87 additions & 27 deletions django_extensions/management/commands/print_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,72 +8,112 @@

import json

from django.conf import settings
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

DEFAULT_FORMAT = "simple"
DEFAULT_INDENT = 4
DEFAULT_SECRETS = False


class Command(BaseCommand):
help = "Print the active Django settings."

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',
default='simple',
dest='format',
help='Specifies output format.'
"--format",
default=DEFAULT_FORMAT,
dest="format",
help="Specifies output format.",
)
parser.add_argument(
'--indent',
default=4,
dest='indent',
"--indent",
default=DEFAULT_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",
default=DEFAULT_SECRETS,
dest="show secrets",
type=bool,
help="Specifies if should be revealed the value of secrets",
)
parser.add_argument(
"--database",
dest="show database",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no spaces, just underscores :-)

action="store_true",
help="Shows the current database engine",
)

@signalcommand
def handle(self, *args, **options):

show_secrets, output_format, indent, show_database = 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
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 = self.safe_settings()
for key in settings.keys():
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)
raise CommandError("%s not found in settings." % setting)

output_format = options['format']
indent = options['indent']

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:
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),
options.get("show database", None)
]
return a_options

@staticmethod
def include_attr(attr, settings):
if attr.startswith('__'):
if attr.startswith("__"):
return False
elif settings == []:
return True
Expand All @@ -83,4 +123,24 @@ 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))

@staticmethod
def safe_settings():
try:
return SafeExceptionReporterFilter().get_safe_settings()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If django < 3.0 does not have this class then the import above will already have failed and this code is meaningless.

Either the comment below is wrong or we should catch ImportError during importing.

FYI: This entire code can be replaced to function at startup time which seem to be preferred to this way if it served no additional function.

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()

@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')
60 changes: 38 additions & 22 deletions tests/management/commands/test_print_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,72 @@


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
assert "DATABASE_ENGINE" not 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',
"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",
)

out, err = capsys.readouterr()

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'
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