@@ -443,19 +443,16 @@ def __eq__(self, other):
443443 self .assertFalse (key .eq_called )
444444 self .assertIs (tz2 , tz1 )
445445
446-
447- class CZoneInfoTest (ZoneInfoTest ):
448- module = c_zoneinfo
449-
450446 def test_duck_typed_invalid_values (self ):
451447 long_max = (1 << (struct .calcsize ("l" ) * 8 - 1 )) - 1
448+ int_max = (1 << (struct .calcsize ("i" ) * 8 - 1 )) - 1
452449 cases = [
453- ("fold" , value , ValueError , f"fold must be 0 or 1, got { value } " )
450+ ("fold" , value , ValueError , f"fold must be 0 or 1, not { value } " )
454451 for value in (- 1 , 2 , 3 , 256 , long_max , - long_max - 1 )
455452 ]
456453 cases .extend (
457454 ("year" , value , ValueError , f"year must be in 1..9999, not { value } " )
458- for value in (0 , - 1 , 10000 )
455+ for value in (0 , - 1 , 10000 , int_max , - int_max - 1 )
459456 )
460457 cases .extend (
461458 (attr , value , exc , message )
@@ -464,21 +461,29 @@ def test_duck_typed_invalid_values(self):
464461 (1 << 100 , OverflowError , "" ),
465462 (- (1 << 100 ), OverflowError , "" ),
466463 (None , TypeError , "" ),
464+ (1.0 , TypeError , "" ),
467465 )
468466 )
467+ cases .extend (
468+ (attr , value , OverflowError , "" )
469+ for attr , maximum in (("fold" , long_max ), ("year" , int_max ))
470+ for value in (maximum + 1 , - maximum - 2 )
471+ )
469472 # Use a date beyond the last transition to exercise year validation.
470473 dt = datetime (2040 , 1 , 1 )
471- zi = self .zone_from_key ("Europe/London" )
472474 for attr , value , exc , message in cases :
473475 false_friend = types .SimpleNamespace (
474476 year = dt .year , hour = 0 , minute = 0 , second = 0 , fold = 0 ,
475477 toordinal = dt .toordinal ,
476478 )
477479 setattr (false_friend , attr , value )
478- for method in (zi .utcoffset , zi .dst , zi .tzname ):
479- with self .subTest (attr = attr , value = value , method = method ):
480- with self .assertRaisesRegex (exc , re .escape (message )):
481- method (false_friend )
480+ for key in ("Europe/London" , "UTC" ):
481+ zi = self .zone_from_key (key )
482+ for method in (zi .utcoffset , zi .dst , zi .tzname ):
483+ with self .subTest (attr = attr , value = value , key = key ,
484+ method = method ):
485+ with self .assertRaisesRegex (exc , re .escape (message )):
486+ method (false_friend )
482487
483488 def test_duck_typed_valid_boundaries (self ):
484489 zi = self .zone_from_key ("Europe/London" )
@@ -493,6 +498,30 @@ def test_duck_typed_valid_boundaries(self):
493498 with self .subTest (year = year , fold = fold , method = method ):
494499 self .assertEqual (method (false_friend ), method (dt ))
495500
501+ def test_duck_typed_index (self ):
502+ class Index :
503+ def __init__ (self , value ):
504+ self .value = value
505+
506+ def __index__ (self ):
507+ return self .value
508+
509+ zi = self .zone_from_key ("Europe/London" )
510+ for fold in (0 , 1 ):
511+ # An ambiguous time beyond the last explicit transition.
512+ dt = datetime (2040 , 10 , 28 , 1 , 30 , fold = fold )
513+ false_friend = types .SimpleNamespace (
514+ year = Index (dt .year ), hour = dt .hour , minute = dt .minute ,
515+ second = dt .second , fold = Index (fold ), toordinal = dt .toordinal ,
516+ )
517+ for method in (zi .utcoffset , zi .dst , zi .tzname ):
518+ with self .subTest (fold = fold , method = method ):
519+ self .assertEqual (method (false_friend ), method (dt ))
520+
521+
522+ class CZoneInfoTest (ZoneInfoTest ):
523+ module = c_zoneinfo
524+
496525 @unittest .skipIf (MISSING_C_DOCSTRINGS ,
497526 "Signature information for builtins requires docstrings" )
498527 def test_signatures (self ):
0 commit comments