mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			186 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Test implementation of the PEP 509: dictionary versionning.
 | 
						|
"""
 | 
						|
import unittest
 | 
						|
from test import support
 | 
						|
 | 
						|
# PEP 509 is implemented in CPython but other Python implementations
 | 
						|
# don't require to implement it
 | 
						|
_testcapi = support.import_module('_testcapi')
 | 
						|
 | 
						|
 | 
						|
class DictVersionTests(unittest.TestCase):
 | 
						|
    type2test = dict
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        self.seen_versions = set()
 | 
						|
        self.dict = None
 | 
						|
 | 
						|
    def check_version_unique(self, mydict):
 | 
						|
        version = _testcapi.dict_get_version(mydict)
 | 
						|
        self.assertNotIn(version, self.seen_versions)
 | 
						|
        self.seen_versions.add(version)
 | 
						|
 | 
						|
    def check_version_changed(self, mydict, method, *args, **kw):
 | 
						|
        result = method(*args, **kw)
 | 
						|
        self.check_version_unique(mydict)
 | 
						|
        return result
 | 
						|
 | 
						|
    def check_version_dont_change(self, mydict, method, *args, **kw):
 | 
						|
        version1 = _testcapi.dict_get_version(mydict)
 | 
						|
        self.seen_versions.add(version1)
 | 
						|
 | 
						|
        result = method(*args, **kw)
 | 
						|
 | 
						|
        version2 = _testcapi.dict_get_version(mydict)
 | 
						|
        self.assertEqual(version2, version1, "version changed")
 | 
						|
 | 
						|
        return  result
 | 
						|
 | 
						|
    def new_dict(self, *args, **kw):
 | 
						|
        d = self.type2test(*args, **kw)
 | 
						|
        self.check_version_unique(d)
 | 
						|
        return d
 | 
						|
 | 
						|
    def test_constructor(self):
 | 
						|
        # new empty dictionaries must all have an unique version
 | 
						|
        empty1 = self.new_dict()
 | 
						|
        empty2 = self.new_dict()
 | 
						|
        empty3 = self.new_dict()
 | 
						|
 | 
						|
        # non-empty dictionaries must also have an unique version
 | 
						|
        nonempty1 = self.new_dict(x='x')
 | 
						|
        nonempty2 = self.new_dict(x='x', y='y')
 | 
						|
 | 
						|
    def test_copy(self):
 | 
						|
        d = self.new_dict(a=1, b=2)
 | 
						|
 | 
						|
        d2 = self.check_version_dont_change(d, d.copy)
 | 
						|
 | 
						|
        # dict.copy() must create a dictionary with a new unique version
 | 
						|
        self.check_version_unique(d2)
 | 
						|
 | 
						|
    def test_setitem(self):
 | 
						|
        d = self.new_dict()
 | 
						|
 | 
						|
        # creating new keys must change the version
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'x', 'x')
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'y', 'y')
 | 
						|
 | 
						|
        # changing values must change the version
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'x', 1)
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'y', 2)
 | 
						|
 | 
						|
    def test_setitem_same_value(self):
 | 
						|
        value = object()
 | 
						|
        d = self.new_dict()
 | 
						|
 | 
						|
        # setting a key must change the version
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'key', value)
 | 
						|
 | 
						|
        # setting a key to the same value with dict.__setitem__
 | 
						|
        # must change the version
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'key', value)
 | 
						|
 | 
						|
        # setting a key to the same value with dict.update
 | 
						|
        # must change the version
 | 
						|
        self.check_version_changed(d, d.update, key=value)
 | 
						|
 | 
						|
        d2 = self.new_dict(key=value)
 | 
						|
        self.check_version_changed(d, d.update, d2)
 | 
						|
 | 
						|
    def test_setitem_equal(self):
 | 
						|
        class AlwaysEqual:
 | 
						|
            def __eq__(self, other):
 | 
						|
                return True
 | 
						|
 | 
						|
        value1 = AlwaysEqual()
 | 
						|
        value2 = AlwaysEqual()
 | 
						|
        self.assertTrue(value1 == value2)
 | 
						|
        self.assertFalse(value1 != value2)
 | 
						|
 | 
						|
        d = self.new_dict()
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'key', value1)
 | 
						|
 | 
						|
        # setting a key to a value equal to the current value
 | 
						|
        # with dict.__setitem__() must change the version
 | 
						|
        self.check_version_changed(d, d.__setitem__, 'key', value2)
 | 
						|
 | 
						|
        # setting a key to a value equal to the current value
 | 
						|
        # with dict.update() must change the version
 | 
						|
        self.check_version_changed(d, d.update, key=value1)
 | 
						|
 | 
						|
        d2 = self.new_dict(key=value2)
 | 
						|
        self.check_version_changed(d, d.update, d2)
 | 
						|
 | 
						|
    def test_setdefault(self):
 | 
						|
        d = self.new_dict()
 | 
						|
 | 
						|
        # setting a key with dict.setdefault() must change the version
 | 
						|
        self.check_version_changed(d, d.setdefault, 'key', 'value1')
 | 
						|
 | 
						|
        # don't change the version if the key already exists
 | 
						|
        self.check_version_dont_change(d, d.setdefault, 'key', 'value2')
 | 
						|
 | 
						|
    def test_delitem(self):
 | 
						|
        d = self.new_dict(key='value')
 | 
						|
 | 
						|
        # deleting a key with dict.__delitem__() must change the version
 | 
						|
        self.check_version_changed(d, d.__delitem__, 'key')
 | 
						|
 | 
						|
        # don't change the version if the key doesn't exist
 | 
						|
        self.check_version_dont_change(d, self.assertRaises, KeyError,
 | 
						|
                                       d.__delitem__, 'key')
 | 
						|
 | 
						|
    def test_pop(self):
 | 
						|
        d = self.new_dict(key='value')
 | 
						|
 | 
						|
        # pop() must change the version if the key exists
 | 
						|
        self.check_version_changed(d, d.pop, 'key')
 | 
						|
 | 
						|
        # pop() must not change the version if the key does not exist
 | 
						|
        self.check_version_dont_change(d, self.assertRaises, KeyError,
 | 
						|
                                       d.pop, 'key')
 | 
						|
 | 
						|
    def test_popitem(self):
 | 
						|
        d = self.new_dict(key='value')
 | 
						|
 | 
						|
        # popitem() must change the version if the dict is not empty
 | 
						|
        self.check_version_changed(d, d.popitem)
 | 
						|
 | 
						|
        # popitem() must not change the version if the dict is empty
 | 
						|
        self.check_version_dont_change(d, self.assertRaises, KeyError,
 | 
						|
                                       d.popitem)
 | 
						|
 | 
						|
    def test_update(self):
 | 
						|
        d = self.new_dict(key='value')
 | 
						|
 | 
						|
        # update() calling with no argument must not change the version
 | 
						|
        self.check_version_dont_change(d, d.update)
 | 
						|
 | 
						|
        # update() must change the version
 | 
						|
        self.check_version_changed(d, d.update, key='new value')
 | 
						|
 | 
						|
        d2 = self.new_dict(key='value 3')
 | 
						|
        self.check_version_changed(d, d.update, d2)
 | 
						|
 | 
						|
    def test_clear(self):
 | 
						|
        d = self.new_dict(key='value')
 | 
						|
 | 
						|
        # clear() must change the version if the dict is not empty
 | 
						|
        self.check_version_changed(d, d.clear)
 | 
						|
 | 
						|
        # clear() must not change the version if the dict is empty
 | 
						|
        self.check_version_dont_change(d, d.clear)
 | 
						|
 | 
						|
 | 
						|
class Dict(dict):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class DictSubtypeVersionTests(DictVersionTests):
 | 
						|
    type2test = Dict
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    unittest.main()
 |