Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Make dump for fns, classes more stable and helpful
Browse files Browse the repository at this point in the history
kdmccormick committed Jan 28, 2025
1 parent 1fe67d3 commit 511d541
Showing 2 changed files with 20 additions and 13 deletions.
25 changes: 16 additions & 9 deletions openedx/core/djangoapps/util/management/commands/dump_settings.py
Original file line number Diff line number Diff line change
@@ -33,13 +33,14 @@ class Command(BaseCommand):
* _("hello") # <-- this will become just "hello"
* "hello"
Furthermore, objects which are not easily JSON-ifiable will stringified using their `repr(...)`, e.g.:
* "Path('my/path')" # a Path object
* "<lms.myapp.MyClass object at 0x704599fa2fd0>" # some random class instance
* "<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>" # sys.stderr
Furthermore, functions and classes are printed as JSON objects like:
{
"module": "path.to.module",
"qualname": "MyClass.MyInnerClass.my_method", // Or, "<lambda>"
"source_hint": "MY_SETTING = lambda: x + y", // For <lambda>s only
}
and lambdas are printed by *roughly* printing out their source lines (it's impossible in Python to get the *exact*
source code, as it's been compiled into bytecode).
And everything else will be stringified as its `repr(...)`.
"""

def handle(self, *args, **kwargs):
@@ -82,12 +83,18 @@ def _to_json_friendly_repr(value: object) -> object:
# Print gettext_lazy as simply the wrapped string
return proxy_args[0]
try:
module = value.__module__
qualname = value.__qualname__
except AttributeError:
pass
else:
if qualname == "<lambda>":
# Handle lambdas by printing the source lines
return "lambda defined with line(s): " + inspect.getsource(value).strip()
# Handle functions and classes by printing their location (plus approximate source, for lambdas)
return {
"module": module,
"qualname": qualname,
**({
"source_hint": inspect.getsource(value).strip(),
} if qualname == "<lambda>" else {}),
}
# For all other objects, print the repr
return repr(value)
8 changes: 4 additions & 4 deletions openedx/core/djangoapps/util/tests/test_dump_settings.py
Original file line number Diff line number Diff line change
@@ -26,8 +26,8 @@ def test_for_lms_settings(capsys):
# Check: tuples are converted to lists
assert isinstance(dump['XBLOCK_MIXINS'], list)

# Check: objects (like classes) are repr'd
assert "<class 'xmodule.x_module.XModuleMixin'>" in dump['XBLOCK_MIXINS']
# Check: classes are converted to dicts of info on the class location
assert {"module": "xmodule.x_module", "qualname": "XModuleMixin"} in dump['XBLOCK_MIXINS']

# Check: nested dictionaries come through OK, and int'l strings are just strings
assert dump['COURSE_ENROLLMENT_MODES']['audit']['display_name'] == "Audit"
@@ -46,8 +46,8 @@ def test_for_cms_settings(capsys):
# Check: tuples are converted to lists
assert isinstance(dump['XBLOCK_MIXINS'], list)

# Check: objects (like classes) are repr'd
assert "<class 'xmodule.x_module.XModuleMixin'>" in dump['XBLOCK_MIXINS']
# Check: classes are converted to dicts of info on the class location
assert {"module": "xmodule.x_module", "qualname": "XModuleMixin"} in dump['XBLOCK_MIXINS']

# Check: nested dictionaries come through OK, and int'l strings are just strings
assert dump['COURSE_ENROLLMENT_MODES']['audit']['display_name'] == "Audit"

0 comments on commit 511d541

Please sign in to comment.