@@ -287,6 +287,8 @@ def test_copying(self):
287
287
# and have a repr/eval round-trip
288
288
pairs = [('c' , 1 ), ('b' , 2 ), ('a' , 3 ), ('d' , 4 ), ('e' , 5 ), ('f' , 6 )]
289
289
od = OrderedDict (pairs )
290
+ od .x = ['x' ]
291
+ od .z = ['z' ]
290
292
def check (dup ):
291
293
msg = "\n copy: %s\n od: %s" % (dup , od )
292
294
self .assertIsNot (dup , od , msg )
@@ -295,13 +297,27 @@ def check(dup):
295
297
self .assertEqual (len (dup ), len (od ))
296
298
self .assertEqual (type (dup ), type (od ))
297
299
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' ))
300
312
# pickle directly pulls the module, so we have to fake it
301
313
with replaced_module ('collections' , self .module ):
302
314
for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
303
315
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' ))
305
321
check (eval (repr (od )))
306
322
update_test = OrderedDict ()
307
323
update_test .update (od )
@@ -756,7 +772,7 @@ def test_sizeof_exact(self):
756
772
check = self .check_sizeof
757
773
758
774
basicsize = size ('nQ2P' + '3PnPn2P' )
759
- keysize = calcsize ('2nP2n ' )
775
+ keysize = calcsize ('n2BI2n ' )
760
776
761
777
entrysize = calcsize ('n2P' )
762
778
p = calcsize ('P' )
@@ -853,6 +869,25 @@ class CPythonOrderedDictSubclassTests(CPythonOrderedDictTests):
853
869
class OrderedDict (c_coll .OrderedDict ):
854
870
pass
855
871
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
+
856
891
857
892
class PurePythonGeneralMappingTests (mapping_tests .BasicTestMappingProtocol ):
858
893
@@ -904,5 +939,90 @@ def test_popitem(self):
904
939
self .assertRaises (KeyError , d .popitem )
905
940
906
941
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
+
907
1027
if __name__ == "__main__" :
908
1028
unittest .main ()
0 commit comments