Skip to content

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ever0de
Copy link

@ever0de ever0de commented Jul 11, 2025

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.

issue: #136535

@python-cla-bot
Copy link

python-cla-bot bot commented Jul 11, 2025

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app bedevere-app bot added awaiting review tests Tests in the Lib/test dir labels Jul 11, 2025
@bedevere-app
Copy link

bedevere-app bot commented Jul 11, 2025

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 skip news label instead.

…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.
Copy link
Member

@corona10 corona10 left a 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:

#define Py_TPFLAGS_MANAGED_DICT (1 << 4)

I am waiting @Fidget-Spinner or @markshannon 's review also.

Copy link
Member

@corona10 corona10 left a 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.

@bedevere-app
Copy link

bedevere-app bot commented Jul 13, 2025

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 I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@corona10 corona10 added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes labels Jul 13, 2025
@ever0de
Copy link
Author

ever0de commented Jul 13, 2025

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.

Hello. I thought the test I added would prevent regression issues, but it didn't.
I think I can prevent this problem by checking Py_TPFLAGS_INLINE_VALUES (1 << 2 flag) in NoManagedDict. Would it be better to add it this way?
If you have any other better improvement suggestions, could you please propose them? Thank you!

@@ -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)
Copy link
Member

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:

Suggested change
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.

Copy link
Member

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.

Copy link
Author

@ever0de ever0de Jul 13, 2025

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?

  1. It gets the Py_TPFLAGS_MANAGED_DICT flag, as it's a heap type that receives a __dict__.
  2. It does not get the Py_TPFLAGS_INLINE_VALUES flag because it inherits a non-zero tp_itemsize from tuple, and the INLINE_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?

Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))

Copy link
Author

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)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting changes needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes skip news tests Tests in the Lib/test dir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy