Repository navigation
Reject diffs that change a member whose name is not a string - #273
Open
stefankoegl wants to merge 1 commit into
Open
stefankoegl wants to merge 1 commit into
stefankoegl wants to merge 1 commit into
Conversation
The diff turned object keys that are not strings into strings for the
paths of its operations. A path can only refer to members whose names
are strings, though: '/1' is the member '1', not the member 1. So
make_patch({1: 'a'}, {1: 'b'}) returned a patch that failed on its own
source, make_patch({1: 'a'}, {1: 'a', 2: 'b'}) one that added a member
'2' instead of 2, and make_patch({1: 'a'}, {'1': 'a'}) an empty one.
Creating a patch now raises a TypeError if one of its operations would
have to refer to such a member. Documents with such members can still be
compared as long as these members are equal, or are part of a value that
is added, removed or moved as a whole, as those patches are correct.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PewzpjVeke4LTQ7Q88nyu6
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The diff turned object keys that are not strings into strings for the paths of its operations. A path can only refer to members whose names are strings, though:
/1is the member'1', not the member1. The resulting patches were silently wrong:make_patch(src, dst)src{1: 'a'},{1: 'b'}replace /1'1'{1: 'a'},{1: 'a', 2: 'b'}add /2{1: 'a', '2': 'b'}, notdst{1: 'a'},{'1': 'a'}srcunchanged, notdstChange
Creating a patch now raises a
TypeErrorif one of its operations would have to refer to such a member:This is narrower than rejecting all non-string keys, which I considered first. Existing tests (
test_issue_78_items_not_serializable,test_move_only_values_equal_in_json) diff documents with such keys on purpose, and those patches are correct. So these still work:Only a difference in, or inside of, such a member raises.
Decision for you
This turns a silently wrong result into an error, which can break callers that diff Python dicts with, say, integer keys and apply the patch to the JSON-serialised form of the document, where the keys are strings and the old patch happened to fit. The alternative would be to keep accepting such keys and convert them the way
json.dumpsdoes (True→"true",None→"null"). That stays compatible with those callers, but the patch would still not apply to the Python document it was created from, which is what the audit item was about.How
Keys that are not strings travel through the
DiffBuilderas a privatestrsubclass that remembers the key and is not equal to the string it looks like (so1and'1'are different members). The error is raised where paths are written, so it covers every kind of operation, including moves and the append extension.Verification
python tests.pyandproperty_tests.pypass with coverage at 100%; flake8 andsphinx-build -Ware clean (Python 3.13).master.Generated by Claude Code