bpo-34320: Fix dict(o) didn't copy order of dict subclass#8624
Conversation
There was a problem hiding this comment.
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.
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.
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
| # 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.
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.
Sorry, what do you mean concretely?
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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
|
|
||
| # 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.
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.
Yes, but problem is I can't find other tests for kwargs.
There was a problem hiding this comment.
I added new test class for this, in test_call.py
| 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.
This test is not specific to PEP 520, which only relates directly to the class definition namespace. So you should drop this comment.
|
|
||
| # 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.
This test should be next to other tests of the type() builtin.
| 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.
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 <methane@users.noreply.github.com>
|
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 <methane@users.noreply.github.com>
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 <methane@users.noreply.github.com>
) (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 <methane@users.noreply.github.com> 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