@@ -62,7 +62,11 @@ class BadTuple(tuple):
6262 def __add__ (self , other ):
6363 return list (self ) + list (other )
6464
65- class MyDict (dict ):
65+
66+ class MyDict (frozendict ):
67+ pass
68+
69+ class MyFrozenDict (frozendict ):
6670 pass
6771
6872class TestImportTime (unittest .TestCase ):
@@ -338,7 +342,7 @@ def test_pickle(self):
338342 with replaced_module ('functools' , self .module ):
339343 f = self .partial (signature , ['asdf' ], bar = [True ])
340344 f .attr = []
341- for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
345+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
342346 f_copy = pickle .loads (pickle .dumps (f , proto ))
343347 self .assertEqual (signature (f_copy ), signature (f ))
344348
@@ -404,6 +408,16 @@ def test_setstate(self):
404408 with self .assertRaisesRegex (TypeError , f'^{ msg_regex } $' ) as cm :
405409 f .__setstate__ ((capture , (1 , PH ), dict (a = 10 ), dict (attr = [])))
406410
411+ with self .assertRaises (TypeError ):
412+ f .__setstate__ ((capture , (1 ,), {1234 : 1234 }, dict (attr = [])))
413+
414+ class FakeString (str ):
415+ pass
416+
417+ with self .assertRaises (TypeError ):
418+ f .__setstate__ ((capture , (1 ,), {FakeString ("string" ): 1234 }, dict (attr = [])))
419+
420+
407421 def test_setstate_errors (self ):
408422 f = self .partial (signature )
409423
@@ -423,7 +437,18 @@ def test_setstate_subclasses(self):
423437 s = signature (f )
424438 self .assertEqual (s , (capture , (1 ,), dict (a = 10 ), {}))
425439 self .assertIs (type (s [1 ]), tuple )
426- self .assertIs (type (s [2 ]), dict )
440+ self .assertIs (type (s [2 ]), frozendict )
441+ r = f ()
442+ self .assertEqual (r , ((1 ,), {'a' : 10 }))
443+ self .assertIs (type (r [0 ]), tuple )
444+ self .assertIs (type (r [1 ]), dict )
445+
446+
447+ f .__setstate__ ((capture , MyTuple ((1 ,)), MyFrozenDict (a = 10 ), None ))
448+ s = signature (f )
449+ self .assertEqual (s , (capture , (1 ,), dict (a = 10 ), {}))
450+ self .assertIs (type (s [1 ]), tuple )
451+ self .assertIs (type (s [2 ]), frozendict )
427452 r = f ()
428453 self .assertEqual (r , ((1 ,), {'a' : 10 }))
429454 self .assertIs (type (r [0 ]), tuple )
@@ -445,7 +470,7 @@ def test_recursive_pickle(self):
445470 f = self .partial (capture )
446471 f .__setstate__ ((f , (), {}, {}))
447472 try :
448- for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
473+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
449474 # gh-117008: Small limit since pickle uses C stack memory
450475 with support .infinite_recursion (100 ):
451476 with self .assertRaises (RecursionError ):
@@ -456,7 +481,7 @@ def test_recursive_pickle(self):
456481 f = self .partial (capture )
457482 f .__setstate__ ((capture , (f ,), {}, {}))
458483 try :
459- for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
484+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
460485 f_copy = pickle .loads (pickle .dumps (f , proto ))
461486 try :
462487 self .assertIs (f_copy .args [0 ], f_copy )
@@ -468,7 +493,7 @@ def test_recursive_pickle(self):
468493 f = self .partial (capture )
469494 f .__setstate__ ((capture , (), {'a' : f }, {}))
470495 try :
471- for proto in range (pickle .HIGHEST_PROTOCOL + 1 ):
496+ for proto in range (2 , pickle .HIGHEST_PROTOCOL + 1 ):
472497 f_copy = pickle .loads (pickle .dumps (f , proto ))
473498 try :
474499 self .assertIs (f_copy .keywords ['a' ], f_copy )
@@ -588,30 +613,15 @@ def test_attributes_unwritable(self):
588613 else :
589614 self .fail ('partial object allowed __dict__ to be deleted' )
590615
591- def test_manually_adding_non_string_keyword (self ):
616+ def test_keyword_mutations (self ):
592617 p = self .partial (capture )
593- # Adding a non-string/unicode keyword to partial kwargs
594- p .keywords [1234 ] = 'value'
595- r = repr (p )
596- self .assertIn ('1234' , r )
597- self .assertIn ("'value'" , r )
598- with self .assertRaises (TypeError ):
599- p ()
600618
601- def test_keystr_replaces_value ( self ):
602- p = self . partial ( capture )
619+ with self . assertRaises ( TypeError ):
620+ p . keywords [ "new key" ] = [ 'sth' ]
603621
604- class MutatesYourDict (object ):
605- def __str__ (self ):
606- p .keywords [self ] = ['sth2' ]
607- return 'astr'
608-
609- # Replacing the value during key formatting should keep the original
610- # value alive (at least long enough).
611- p .keywords [MutatesYourDict ()] = ['sth' ]
612- r = repr (p )
613- self .assertIn ('astr' , r )
614- self .assertIn ("['sth']" , r )
622+ # Adding a non-string/unicode keyword to partial kwargs
623+ with self .assertRaises (TypeError ):
624+ p .keywords [1234 ] = 'value'
615625
616626 def test_placeholders_refcount_smoke (self ):
617627 PH = self .module .Placeholder
0 commit comments