@@ -287,6 +287,8 @@ def test_copying(self):
287287 # and have a repr/eval round-trip
288288 pairs = [('c' , 1 ), ('b' , 2 ), ('a' , 3 ), ('d' , 4 ), ('e' , 5 ), ('f' , 6 )]
289289 od = OrderedDict (pairs )
290+ od .x = ['x' ]
291+ od .z = ['z' ]
290292 def check (dup ):
291293 msg = "\n copy: %s\n od: %s" % (dup , od )
292294 self .assertIsNot (dup , od , msg )
@@ -295,13 +297,27 @@ def check(dup):
295297 self .assertEqual (len (dup ), len (od ))
296298 self .assertEqual (type (dup ), type (od ))
297299 check (od .copy ())
298- check (copy .copy (od ))
299- check (copy .deepcopy (od ))
300+ dup = copy .copy (od )
301+ check (dup )
302+ self .assertIs (dup .x , od .x )
303+ self .assertIs (dup .z , od .z )
304+ self .assertFalse (hasattr (dup , 'y' ))
305+ dup = copy .deepcopy (od )
306+ check (dup )
307+ self .assertEqual (dup .x , od .x )
308+ self .assertIsNot (dup .x , od .x )
309+ self .assertEqual (dup .z , od .z )
310+ self .assertIsNot (dup .z , od .z )
311+ self .assertFalse (hasattr (dup , 'y' ))
300312 # pickle directly pulls the module, so we have to fake it
301313 with replaced_module ('collections' , self .module ):
302314 for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
303315 with self .subTest (proto = proto ):
304- check (pickle .loads (pickle .dumps (od , proto )))
316+ dup = pickle .loads (pickle .dumps (od , proto ))
317+ check (dup )
318+ self .assertEqual (dup .x , od .x )
319+ self .assertEqual (dup .z , od .z )
320+ self .assertFalse (hasattr (dup , 'y' ))
305321 check (eval (repr (od )))
306322 update_test = OrderedDict ()
307323 update_test .update (od )
@@ -756,7 +772,7 @@ def test_sizeof_exact(self):
756772 check = self .check_sizeof
757773
758774 basicsize = size ('nQ2P' + '3PnPn2P' )
759- keysize = calcsize ('2nP2n ' )
775+ keysize = calcsize ('n2BI2n ' )
760776
761777 entrysize = calcsize ('n2P' )
762778 p = calcsize ('P' )
@@ -853,6 +869,25 @@ class CPythonOrderedDictSubclassTests(CPythonOrderedDictTests):
853869 class OrderedDict (c_coll .OrderedDict ):
854870 pass
855871
872+ # TODO: RUSTPYTHON
873+ @unittest .expectedFailure
874+ class PurePythonOrderedDictWithSlotsCopyingTests (unittest .TestCase ):
875+
876+ module = py_coll
877+ class OrderedDict (py_coll .OrderedDict ):
878+ __slots__ = ('x' , 'y' )
879+ test_copying = OrderedDictTests .test_copying
880+
881+ # TODO: RUSTPYTHON
882+ @unittest .expectedFailure
883+ @unittest .skipUnless (c_coll , 'requires the C version of the collections module' )
884+ class CPythonOrderedDictWithSlotsCopyingTests (unittest .TestCase ):
885+
886+ module = c_coll
887+ class OrderedDict (c_coll .OrderedDict ):
888+ __slots__ = ('x' , 'y' )
889+ test_copying = OrderedDictTests .test_copying
890+
856891
857892class PurePythonGeneralMappingTests (mapping_tests .BasicTestMappingProtocol ):
858893
@@ -904,5 +939,90 @@ def test_popitem(self):
904939 self .assertRaises (KeyError , d .popitem )
905940
906941
942+ class SimpleLRUCache :
943+
944+ def __init__ (self , size ):
945+ super ().__init__ ()
946+ self .size = size
947+ self .counts = dict .fromkeys (('get' , 'set' , 'del' ), 0 )
948+
949+ def __getitem__ (self , item ):
950+ self .counts ['get' ] += 1
951+ value = super ().__getitem__ (item )
952+ self .move_to_end (item )
953+ return value
954+
955+ def __setitem__ (self , key , value ):
956+ self .counts ['set' ] += 1
957+ while key not in self and len (self ) >= self .size :
958+ self .popitem (last = False )
959+ super ().__setitem__ (key , value )
960+ self .move_to_end (key )
961+
962+ def __delitem__ (self , key ):
963+ self .counts ['del' ] += 1
964+ super ().__delitem__ (key )
965+
966+
967+ class SimpleLRUCacheTests :
968+
969+ def test_add_after_full (self ):
970+ c = self .type2test (2 )
971+ c ['t1' ] = 1
972+ c ['t2' ] = 2
973+ c ['t3' ] = 3
974+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
975+ self .assertEqual (list (c ), ['t2' , 't3' ])
976+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
977+
978+ def test_popitem (self ):
979+ c = self .type2test (3 )
980+ for i in range (1 , 4 ):
981+ c [i ] = i
982+ self .assertEqual (c .popitem (last = False ), (1 , 1 ))
983+ self .assertEqual (c .popitem (last = True ), (3 , 3 ))
984+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
985+
986+ # TODO: RUSTPYTHON
987+ @unittest .expectedFailure
988+ def test_pop (self ):
989+ c = self .type2test (3 )
990+ for i in range (1 , 4 ):
991+ c [i ] = i
992+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
993+ self .assertEqual (c .pop (2 ), 2 )
994+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
995+ self .assertEqual (c .pop (4 , 0 ), 0 )
996+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
997+ self .assertRaises (KeyError , c .pop , 4 )
998+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
999+
1000+ def test_change_order_on_get (self ):
1001+ c = self .type2test (3 )
1002+ for i in range (1 , 4 ):
1003+ c [i ] = i
1004+ self .assertEqual (list (c ), list (range (1 , 4 )))
1005+ self .assertEqual (c .counts , {'get' : 0 , 'set' : 3 , 'del' : 0 })
1006+ self .assertEqual (c [2 ], 2 )
1007+ self .assertEqual (c .counts , {'get' : 1 , 'set' : 3 , 'del' : 0 })
1008+ self .assertEqual (list (c ), [1 , 3 , 2 ])
1009+
1010+
1011+ class PySimpleLRUCacheTests (SimpleLRUCacheTests , unittest .TestCase ):
1012+
1013+ class type2test (SimpleLRUCache , py_coll .OrderedDict ):
1014+ pass
1015+
1016+ @unittest .skip ("TODO: RUSTPYTHON" )
1017+ @unittest .skipUnless (c_coll , 'requires the C version of the collections module' )
1018+ class CSimpleLRUCacheTests (SimpleLRUCacheTests , unittest .TestCase ):
1019+
1020+ @classmethod
1021+ def setUpClass (cls ):
1022+ class type2test (SimpleLRUCache , c_coll .OrderedDict ):
1023+ pass
1024+ cls .type2test = type2test
1025+
1026+
9071027if __name__ == "__main__" :
9081028 unittest .main ()
0 commit comments