Skip to content

Commit

Permalink
fix: better errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kdmccormick committed Jan 24, 2025
1 parent c1fb2ea commit 1243025
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions openedx/core/djangoapps/util/management/commands/dump_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
import re
import sys
from datetime import timedelta
from importlib.resources import files
from path import Path

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.test import TestCase
from django.core.management.base import BaseCommand


SETTING_NAME_REGEX = re.compile(r'^[A-Z][A-Z0-9_]*$')
Expand Down Expand Up @@ -48,14 +46,14 @@ def handle(self, *args, **kwargs):
Handle the command.
"""
settings_json = {
name: _to_json_friendly_repr(getattr(settings, name))
name: _to_json_friendly_repr(getattr(settings, name), [])
for name in dir(settings)
if SETTING_NAME_REGEX.match(name)
}
print(json.dumps(settings_json, indent=4))


def _to_json_friendly_repr(value: object) -> object:
def _to_json_friendly_repr(value: object, debug_keys: list[str | int]) -> object:
"""
Turn the value into something that we can print to a JSON file (that is: str, bool, None, int, float, list, dict).
Expand All @@ -66,28 +64,31 @@ def _to_json_friendly_repr(value: object) -> object:
return value
if isinstance(value, (list, tuple)):
# Print both lists and tuples as JSON arrays
return [_to_json_friendly_repr(element) for element in value]
return [_to_json_friendly_repr(element, [*debug_keys, ix]) for ix, element in enumerate(value)]
if isinstance(value, set):
# Print sets by sorting them (so that order doesn't matter) and printing the result as a JSON array
return [sorted(_to_json_friendly_repr(element) for element in value)]
return [_to_json_friendly_repr(element, [*debug_keys, ix]) for ix, element in enumerate(sorted(value))]
if isinstance(value, dict):
# Print dicts as JSON objects
for subkey in value.keys():
if not isinstance(subkey, (str, int)):
raise ValueError(f"Unexpected dict key {subkey} of type {type(subkey)}")
return {subkey: _to_json_friendly_repr(subval) for subkey, subval in value.items()}
return {subkey: _to_json_friendly_repr(subval, [*debug_keys, subkey]) for subkey, subval in value.items()}
if isinstance(value, Path):
# Print path objects as the string `Path('path/to/something')`.
return repr(value)
if isinstance(value, timedelta):
# Print timedelta objects as the string `datetime.timedelta(days=1, ...)`
return repr(value)
debug_name = (
str(debug_keys[0]) + "".join(f"[{debug_key!r}]" for debug_key in debug_keys[1:])
) if debug_keys else "<root>"
if proxy_args := getattr(value, "_proxy____args", None):
# Print gettext_lazy as simply the wrapped string
if len(proxy_args) == 1:
if isinstance(proxy_args[0], str):
return proxy_args[0]
raise ValueError(f"Not sure how to dump value {value!r} with proxy args {proxy_args!r}")
raise ValueError(f"Not sure how to dump {debug_name} with value {value!r} with proxy args {proxy_args!r}")
if value is sys.stderr:
# Print the stderr object as simply "sys.stderr"
return "sys.stderr"
Expand All @@ -97,7 +98,9 @@ def _to_json_friendly_repr(value: object) -> object:
qualname = value.__qualname__
except AttributeError:
# If that doesn't work, then give up--we don't know how to print this value.
raise ValueError(f"Not sure how to dump value {value!r} of type {type(value)}")
raise ValueError( # pylint: disable=raise-missing-from
f"Not sure how to dump {debug_name} with value {value!r} of type {type(value)}"
)
if qualname == "<lambda>":
# Handle lambdas by printing the source lines
return inspect.getsource(value).strip()
Expand Down

0 comments on commit 1243025

Please sign in to comment.