-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
gh-132762: Fix underallocation bug in dict.fromkeys() and expand test coverage #133627
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
Conversation
previously covered: - fast path for dictionary inputs - fast path when object's constructor returns non-empty dict (too small for good coverage) now additionally covered: - fast path for set inputs - slow path for non-set, non-dictionary inputs - fast path when object's constructor returns *large* non-empty dict - slow path when object is a proper subclass of dict
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, lgtm!
Thanks @angela-tarantula for the PR, and @colesbury for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13, 3.14. |
…h-133627) The function `dict_set_fromkeys()` adds elements of a set to an existing dictionary. The size of the expanded dictionary was estimated with `PySet_GET_SIZE(iterable)`, which did not take into account the size of the existing dictionary. (cherry picked from commit 421ba58) Co-authored-by: Angela Liss <59097311+angela-tarantula@users.noreply.github.com>
Sorry, @angela-tarantula and @colesbury, I could not cleanly backport this to
|
GH-133685 is a backport of this pull request to the 3.14 branch. |
…ythongh-133627) The function `dict_set_fromkeys()` adds elements of a set to an existing dictionary. The size of the expanded dictionary was estimated with `PySet_GET_SIZE(iterable)`, which did not take into account the size of the existing dictionary. (cherry picked from commit 421ba58) Co-authored-by: Angela Liss <59097311+angela-tarantula@users.noreply.github.com>
GH-133686 is a backport of this pull request to the 3.13 branch. |
) (gh-133685) The function `dict_set_fromkeys()` adds elements of a set to an existing dictionary. The size of the expanded dictionary was estimated with `PySet_GET_SIZE(iterable)`, which did not take into account the size of the existing dictionary. (cherry picked from commit 421ba58) Co-authored-by: Angela Liss <59097311+angela-tarantula@users.noreply.github.com>
) (gh-133686) The function `dict_set_fromkeys()` adds elements of a set to an existing dictionary. The size of the expanded dictionary was estimated with `PySet_GET_SIZE(iterable)`, which did not take into account the size of the existing dictionary. (cherry picked from commit 421ba58) Co-authored-by: Angela Liss <59097311+angela-tarantula@users.noreply.github.com>
Closes #132762
Summary
dict_set_fromkeys()
was only sizing its new table by the size of theiterable
input, ignoring any existing entries in the dictionary. This triggered an infinite loop indictresize()
whenever the new dictionary size was too small to reinsert those entries. This patch adds the samePy_MAX(…, DK_LOG_SIZE(mp->ma_keys))
guard thatdict_dict_fromkeys()
uses, so we never accidentally shrink the table below its current capacity. The relevant test casebaddict3
has been updated to cover this edge case.For more background, see my proposal.
3 New Regression Tests
Ever since the fast path was updated, the slow path completely lost test coverage. To rectify this, I added 3 new tests:
iterable
input is neither a set nor a dictionaryfromkeys()
is called on a proper subclass of dict,baddict4
dict_dict_fromkeys()
anddict_set_fromkeys()
are separate)Thanks for the review! @DinoV @colesbury