-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
gh-136535: Tests: Correct Py_TPFLAGS_MANAGED_DICT
in test_class.py
#136538
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
base: main
Are you sure you want to change the base?
Conversation
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 |
665ca05
to
6050223
Compare
…ass.py` The `Py_TPFLAGS_MANAGED_DICT` constant in `Lib/test/test_class.py` was incorrectly set to (1 << 2) instead of the correct (1 << 4) from object.h.
30edb78
to
407de3c
Compare
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.
LGTM, I also double checked with the original reference:
Line 551 in 47b01da
#define Py_TPFLAGS_MANAGED_DICT (1 << 4) |
I am waiting @Fidget-Spinner or @markshannon 's review also.
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.
Hi would you like to improve the test if the is Py_TPFLAGS_MANAGED_DICT
wrongly set?
With my local change it is passed if I modify the value into 1 << 2, I prefer to prevent regression in the future.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Hello. I thought the test I added would prevent regression issues, but it didn't. |
@@ -859,7 +859,10 @@ def __init__(self, arg): | |||
|
|||
from _testinternalcapi import has_inline_values | |||
|
|||
Py_TPFLAGS_MANAGED_DICT = (1 << 2) | |||
Py_TPFLAGS_MANAGED_DICT = (1 << 4) |
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.
While reading the original source code, it seems that Py_TPFLAGS_INLINE_VALUES
was intended to be (1 << 2)
, based on how the flag is used.
So a simple fix might be to change it to:
Py_TPFLAGS_MANAGED_DICT = (1 << 4) | |
Py_TPFLAGS_INLINE_VALUES = (1 << 2) |
Also, Py_TPFLAGS_MANAGED_DICT
is used in the TestInlineValues
tests.
Let’s see what Mark and Ken Jin think about this.
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.
The best way is to find a class that has the Py_TPFLAGS_MANAGED_DICT
and Py_TPFLAGS_INLINE_VALUES
mutual exclusion case.
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.
what if we add a case that specifically uses a subclass of a variable-sized type, like tuple
?
- It gets the
Py_TPFLAGS_MANAGED_DICT
flag, as it's a heap type that receives a__dict__
. - It does not get the
Py_TPFLAGS_INLINE_VALUES
flag because it inherits a non-zerotp_itemsize
fromtuple
, and theINLINE_VALUES
optimization is only applied to fixed-size objects.
Adding the following test would explicitly verify this intended behavior and help protect against future regressions.
class VarSizedSubclass(tuple):
"""
Mutual exclusion case: A class inheriting from a variable-sized
built-in type. It has a managed dict, but no inline values.
"""
pass
class TestTypeFlags(unittest.TestCase):
def test_flags_for_mutual_exclusion_case(self):
"""
Tests the mutual exclusion case: VarSizedSubclass should only
have the MANAGED_DICT flag.
"""
flags = VarSizedSubclass.__flags__
# 1. It should have the MANAGED_DICT flag.
self.assertEqual(flags & Py_TPFLAGS_MANAGED_DICT, Py_TPFLAGS_MANAGED_DICT)
# 2. It should NOT have the INLINE_VALUES flag.
self.assertEqual(flags & Py_TPFLAGS_INLINE_VALUES, 0)
What do you think of this approach?
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.
Yeah looks good to me, just please integrate them into TestInlineValues rather than add new extra test.
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.
cpython/Lib/test/test_class.py
Lines 877 to 888 in 47b01da
class TestInlineValues(unittest.TestCase): | |
def test_flags(self): | |
self.assertEqual(Plain.__flags__ & Py_TPFLAGS_MANAGED_DICT, Py_TPFLAGS_MANAGED_DICT) | |
self.assertEqual(WithAttrs.__flags__ & Py_TPFLAGS_MANAGED_DICT, Py_TPFLAGS_MANAGED_DICT) | |
def test_has_inline_values(self): | |
c = Plain() | |
self.assertTrue(has_inline_values(c)) | |
del c.__dict__ | |
self.assertFalse(has_inline_values(c)) | |
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've updated the tests as discussed, following the approach in 9cd9c5b
(#136538)
I've added the new test cases for the various flag combinations to the existing TestInlineValues
class. I'm a little hesitant about whether this is the most appropriate place, as the name TestInlineValues might now be a bit narrow for the expanded scope of these tests.
Do you think it's acceptable to expand the scope of this class, or would you prefer a different approach (like renaming the class to TestTypeFlags, for example)?
The
Py_TPFLAGS_MANAGED_DICT
constant inLib/test/test_class.py
was incorrectly set to (1 << 2) instead of the correct (1 << 4) from object.h.issue: #136535
Py_TPFLAGS_MANAGED_DICT
inLib/test/test_class.py
#136535