Skip to content

Keep Unicode readable in CLI JSON output across serializers - #625

Open
jackwalkerlabs wants to merge 1 commit into
qlustered:devfrom
jackwalkerlabs:codex/readable-cli-unicode
Open

jackwalkerlabs wants to merge 1 commit into
qlustered:devfrom
jackwalkerlabs:codex/readable-cli-unicode

Conversation

@jackwalkerlabs

Copy link
Copy Markdown

Keep non-ASCII names and values readable in deep diff JSON output when using the standard-library serializer, matching the existing orjson behavior. Pass ensure_ascii=False only to the builtin backend because orjson does not accept that keyword.

Fixes #572.

Validation: the new builtin-backend regression fails on the base; both backend cases pass after the change and still decode as JSON. All 27 CLI tests pass. Broader suite: 1274 passed, 44 skipped, one deselected. The excluded memory-exhaustion security test cannot set RLIMIT_AS on this macOS host (also fails on the base). Changed lines introduce no new lint errors; commands.py already has six line-length violations.

AI disclosure: Implemented, reviewed, and tested by OpenAI Codex under the account owner’s authorization; no human code review is claimed.

@seperman seperman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Static review: #625 Keep Unicode readable in CLI JSON output across serializers

Summary: The deep diff CLI now passes ensure_ascii=False when the stdlib json backend is used, so non-ASCII text prints as-is instead of as \uXXXX, matching what orjson already does. The library's to_json() default is unchanged. This addresses #572.

Overlap with other PRs

I found none. #612 uses ensure_ascii=False in its own new json_diff module but doesn't touch commands.py.

Security

  • No code execution, file, network or dependency changes.
  • Note on output: with ensure_ascii=False, stdlib json still escapes U+0000–U+001F (including ESC), " and \. It no longer escapes DEL, C1 controls (U+0080–U+009F) or bidi/format characters such as U+202E. So such characters from the compared files can now reach the terminal unescaped on installs without orjson. The orjson backend already behaves this way, so this brings the two to parity rather than adding a new kind of issue. I mention it so the choice is deliberate.

No security concerns found in static review.

Correctness

  • deepdiff/commands.py:121 checks deepdiff.commands.orjson, but the backend is actually chosen from deepdiff.serialization.orjson inside json_dumps. Both come from the same try-import, so in practice they agree. The link is implicit, though, which is why the test has to patch both modules.
  • Edge case: if stdout can't encode the characters (e.g. PYTHONIOENCODING=ascii, or output redirected on Windows with a legacy code page), print() raises UnicodeEncodeError. The fallback at commands.py:123-124 then calls pprint(diff), whose repr contains the same characters, so the command would most likely end in an uncaught traceback. Before, such installs printed ASCII-escaped JSON. orjson installs already behave this way today.

Tests

  • test_diff_command_preserves_unicode (tests/test_command.py:15): the use_orjson=False case should fail on dev (escaped output) and pass with this change. The use_orjson=True case already passes on dev and guards parity. Both check that the output is still valid JSON. The test writes only to tmp_path.

Suggestions

  • Consider keeping the backend knowledge in serialization.py, for example by letting json_dumps ignore ensure_ascii in the orjson branch (orjson never escapes). The CLI could then always pass ensure_ascii=False.
  • Optionally catch UnicodeEncodeError and retry with ensure_ascii=True, so non-UTF-8 terminals and pipes keep working.

AI-assisted static review; the code was not executed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants