-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
bpo-34320: Fix dict(o) didn't copy order of dict subclass #8624
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
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.
Would be nice to add tests for PEP 468 and PEP 520. These tests should be backported to 3.6, but the test for the dict constructor can not.
Objects/dictobject.c
Outdated
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.
This may be too restrictive. Most dict subclasses don't change the order. Maybe check also that __iter__ is not overridden?
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.
You mean, "Maybe check instead", right? So something like the following.
if (PyDict_Check(b) && Py_TYPE(b)->tp_iter == PyDict_Type.tp_iter) {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.
Adding the tp_iter checks seems like the most reasonable way to go. That would preserve the fast conversion speed of defaultdict.
|
Please add tests. |
|
@serhiy-storchaka Which type of test? |
|
Tests for for PEP 468 and PEP 520. |
af63eda to
253f5db
Compare
Lib/test/test_ordered_dict.py
Outdated
| # Dict preserves order by language spec from 3.7. | ||
| # Dict preserves order by implementation from 3.6. | ||
| if sys.version_info < (3, 7): | ||
| test_dict_copy_order = support.cpython_only(test_dict_copy_order) |
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.
In 3.7+ this is not needed. And I think that in <3.7 this test should be backported.
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.
Sorry, what do you mean concretely?
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.
Tests are ran with concrete Python version. sys.version_info is a constant in every branch. In branches master and 3.7 these two lines should be removed. In branch 3.6 the decorator should be added unconditionally. But the backport to 3.6 needs editing in any case (only the test should be backported), so I don't think this will add additional work.
|
Perhaps there are better places for tests for PEP 468 and PEP 520. I would try to break the order of all kwargs dicts and class dicts and see what tests will fail. |
|
I have made |
|
FYI, PEP 520 is reverted because of dict preserves order. |
|
We missed 3.7.1, maybe. May I add comment like "# TODO: Move this test to better place" and merge this? |
|
Would be nice to mention PEP 468 and 520 in comments for corresponding tests. |
serhiy-storchaka
left a comment
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.
Thank you @methane!
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.
Aside from moving the tests you already have, there should be at least 3 more tests:
- with a
metaclass.__prepare__that returns anOrderedDict(see https://bugs.python.org/issue34320#msg325898) -- this would be next to either other tests related to__prepare__()or other tests related totype() dict(obj)whereobjis an instance of some non-OrderedDictsubclass ofdictwithout a custom__iter__-- this would be intest_dict.pydict(obj)whereobjis an instance of some subclass ofdictwith a custom__iter__-- this would be intest_dict.py
Lib/test/test_ordered_dict.py
Outdated
|
|
||
| # TODO: This test is relating to PEP 468. | ||
| # Move this test to somewhere more appropriate. | ||
| def test_kwargs_order(self): |
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.
This test is about kwargs ordering rather than OrderedDict, so I'd expect it to be next to other tests for kwargs, not here in test_ordered_dict.py.
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.
Yes, but problem is I can't find other tests for kwargs.
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.
I added new test class for this, in test_call.py
Lib/test/test_ordered_dict.py
Outdated
| self.assertIsInstance(res, dict) | ||
| self.assertEqual(list(res.items()), expected) | ||
|
|
||
| # TODO: This test is relating to PEP 520. |
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.
This test is not specific to PEP 520, which only relates directly to the class definition namespace. So you should drop this comment.
Lib/test/test_ordered_dict.py
Outdated
|
|
||
| # TODO: This test is relating to PEP 520. | ||
| # Move this test to somewhere more appropriate. | ||
| def test_type_namespace_order(self): |
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.
This test should be next to other tests of the type() builtin.
Lib/test/test_ordered_dict.py
Outdated
| C = type('C', (), od) | ||
| self.assertEqual(list(C.__dict__.items())[:2], [('b', 2), ('a', 1)]) | ||
|
|
||
| def test_dict_copy_order(self): |
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.
This test should be in test_dict.py.
|
When you're done making the requested changes, leave the comment: |
|
Thank you for your suggestions @ericsnowcurrently. They all LGTM. |
f117479 to
603bc6c
Compare
603bc6c to
ee8696d
Compare
|
Thanks @methane for the PR 🌮🎉.. I'm working now to backport this PR to: 3.6, 3.7. |
|
GH-9582 is a backport of this pull request to the 3.7 branch. |
) When dict subclass overrides order (`__iter__()`, `keys()`, and `items()`), `dict(o)` should use it instead of dict ordering. https://bugs.python.org/issue34320 (cherry picked from commit 2aaf98c) Co-authored-by: INADA Naoki <[email protected]>
|
GH-9583 is a backport of this pull request to the 3.6 branch. |
) When dict subclass overrides order (`__iter__()`, `keys()`, and `items()`), `dict(o)` should use it instead of dict ordering. https://bugs.python.org/issue34320 (cherry picked from commit 2aaf98c) Co-authored-by: INADA Naoki <[email protected]>
When dict subclass overrides order (`__iter__()`, `keys()`, and `items()`), `dict(o)` should use it instead of dict ordering. https://bugs.python.org/issue34320 (cherry picked from commit 2aaf98c) Co-authored-by: INADA Naoki <[email protected]>
) (GH-9583) When dict subclass overrides order (`__iter__()`, `keys()`, and `items()`), `dict(o)` should use it instead of dict ordering. https://bugs.python.org/issue34320 (cherry picked from commit 2aaf98c) Co-authored-by: INADA Naoki <[email protected]> https://bugs.python.org/issue34320
When dict subclass overrides order (
__iter__(),keys(), anditems()),dict(o)should use it instead of dict ordering.
https://bugs.python.org/issue34320