tests for the internal type cache in cpython import unittest from test import support from test support import importhelper try from sys import cleartypecache except importerror cleartypecache none skip this test if the testcapi module isn t available typegetversion importhelper importmodule testcapi typegetversion typeassignversion importhelper importmodule testcapi typeassignversion support cpythononly unittest skipifcleartypecache is none requires sys cleartypecache class typecachetestsunittest testcase def testtpversiontaguniqueself check if global version tag has already overflowed y type y y x 1 y x force a pytypelookup populating version tag yver typegetversiony overflow or not enough left to conduct the test if yver 0 or yver 0xfffff000 self skiptestout of type version tags note try to avoid any method lookups within this loop it will affect global version tag allversiontags appendresult allversiontags append assertnotequal self assertnotequal for in range30 cleartypecache x type y x x 1 x x tpversiontagafter typegetversionx assertnotequaltpversiontagafter 0 msgversion overflowed appendresulttpversiontagafter self assertequallensetallversiontags 30 msgfallversiontags contains nonunique versions def testtypeassignversionself class c x 5 self assertequaltypeassignversionc 1 cver typegetversionc c x 6 self assertequaltypegetversionc 0 self assertequaltypeassignversionc 1 self assertnotequaltypegetversionc 0 self assertnotequaltypegetversionc cver if name main unittest main skip this test if the _testcapi module isn t available tp_version_tag should be unique assuming no overflow even after clearing type cache check if global version tag has already overflowed force a _pytype_lookup populating version tag overflow or not enough left to conduct the test note try to avoid any method lookups within this loop it will affect global version tag
import unittest
from test import support
from test.support import import_helper
try:
    from sys import _clear_type_cache
except ImportError:
    _clear_type_cache = None


type_get_version = import_helper.import_module('_testcapi').type_get_version
type_assign_version = import_helper.import_module('_testcapi').type_assign_version


@support.cpython_only
@unittest.skipIf(_clear_type_cache is None, "requires sys._clear_type_cache")
class TypeCacheTests(unittest.TestCase):
    def test_tp_version_tag_unique(self):
        
        
        Y = type('Y', (), {})
        Y.x = 1
        Y.x  
        y_ver = type_get_version(Y)
        
        if y_ver == 0 or y_ver > 0xFFFFF000:
            self.skipTest("Out of type version tags")
        
        
        all_version_tags = []
        append_result = all_version_tags.append
        assertNotEqual = self.assertNotEqual
        for _ in range(30):
            _clear_type_cache()
            X = type('Y', (), {})
            X.x = 1
            X.x
            tp_version_tag_after = type_get_version(X)
            assertNotEqual(tp_version_tag_after, 0, msg="Version overflowed")
            append_result(tp_version_tag_after)
        self.assertEqual(len(set(all_version_tags)), 30,
                         msg=f"{all_version_tags} contains non-unique versions")

    def test_type_assign_version(self):
        class C:
            x = 5

        self.assertEqual(type_assign_version(C), 1)
        c_ver = type_get_version(C)

        C.x = 6
        self.assertEqual(type_get_version(C), 0)
        self.assertEqual(type_assign_version(C), 1)
        self.assertNotEqual(type_get_version(C), 0)
        self.assertNotEqual(type_get_version(C), c_ver)


if __name__ == "__main__":
    unittest.main()