@@ -574,12 +574,17 @@ def __str__(self) -> str:
574
574
""""""
575
575
return self .iso_format ()
576
576
577
- def __copy__ (self ) -> Duration :
578
- return self .__new__ (self .__class__ , months = self [0 ], days = self [1 ],
579
- seconds = self [2 ], nanoseconds = self [3 ])
577
+ def __reduce__ (self ):
578
+ return (
579
+ type (self )._restore , (tuple (self ), self .__dict__ )
580
+ )
580
581
581
- def __deepcopy__ (self , memo ) -> Duration :
582
- return self .__copy__ ()
582
+ @classmethod
583
+ def _restore (cls , elements , dict_ ):
584
+ instance = tuple .__new__ (cls , elements )
585
+ if dict_ :
586
+ instance .__dict__ .update (dict_ )
587
+ return instance
583
588
584
589
@classmethod
585
590
def from_iso_format (cls , s : str ) -> Duration :
@@ -763,6 +768,13 @@ class Date(date_base_class, metaclass=DateType):
763
768
# CONSTRUCTOR #
764
769
765
770
def __new__ (cls , year : int , month : int , day : int ) -> Date :
771
+ # TODO: 6.0 - remove the __new__ magic and ZeroDate being a singleton.
772
+ # It's fine to remain as constant. Instead, simply use
773
+ # __init__ and simplify pickle/copy (remove __reduce__).
774
+ # N.B. this is a breaking change and must be treated as
775
+ # such. Also consider introducing __slots__. Potentially
776
+ # apply similar treatment to other temporal types as well
777
+ # as spatial types.
766
778
if year == month == day == 0 :
767
779
return ZeroDate
768
780
year , month , day = _normalize_day (year , month , day )
@@ -1218,11 +1230,17 @@ def __sub__(self, other):
1218
1230
except TypeError :
1219
1231
return NotImplemented
1220
1232
1221
- def __copy__ (self ) -> Date :
1222
- return self .__new (self .__ordinal , self .__year , self .__month , self .__day )
1233
+ def __reduce__ (self ):
1234
+ if self is ZeroDate :
1235
+ return "ZeroDate"
1236
+ return type (self )._restore , (self .__dict__ ,)
1223
1237
1224
- def __deepcopy__ (self , * args , ** kwargs ) -> Date :
1225
- return self .__copy__ ()
1238
+ @classmethod
1239
+ def _restore (cls , dict_ ) -> Date :
1240
+ instance = object .__new__ (cls )
1241
+ if dict_ :
1242
+ instance .__dict__ .update (dict_ )
1243
+ return instance
1226
1244
1227
1245
# INSTANCE METHODS #
1228
1246
@@ -1396,34 +1414,53 @@ class Time(time_base_class, metaclass=TimeType):
1396
1414
1397
1415
# CONSTRUCTOR #
1398
1416
1399
- def __new__ (
1400
- cls ,
1417
+ def __init__ (
1418
+ self ,
1401
1419
hour : int = 0 ,
1402
1420
minute : int = 0 ,
1403
1421
second : int = 0 ,
1404
1422
nanosecond : int = 0 ,
1405
1423
tzinfo : t .Optional [_tzinfo ] = None
1406
- ) -> Time :
1407
- hour , minute , second , nanosecond = cls .__normalize_nanosecond (
1424
+ ) -> None :
1425
+ hour , minute , second , nanosecond = self .__normalize_nanosecond (
1408
1426
hour , minute , second , nanosecond
1409
1427
)
1410
1428
ticks = (3600000000000 * hour
1411
1429
+ 60000000000 * minute
1412
1430
+ 1000000000 * second
1413
1431
+ nanosecond )
1414
- return cls . __new (ticks , hour , minute , second , nanosecond , tzinfo )
1432
+ self . __unchecked_init (ticks , hour , minute , second , nanosecond , tzinfo )
1415
1433
1416
1434
@classmethod
1417
- def __new (cls , ticks , hour , minute , second , nanosecond , tzinfo ):
1418
- instance = object .__new__ (cls )
1419
- instance .__ticks = int (ticks )
1420
- instance .__hour = int (hour )
1421
- instance .__minute = int (minute )
1422
- instance .__second = int (second )
1423
- instance .__nanosecond = int (nanosecond )
1424
- instance .__tzinfo = tzinfo
1435
+ def __unchecked_new (
1436
+ cls ,
1437
+ ticks : int ,
1438
+ hour : int ,
1439
+ minutes : int ,
1440
+ second : int ,
1441
+ nano : int ,
1442
+ tz : t .Optional [_tzinfo ]
1443
+ ) -> Time :
1444
+ instance = object .__new__ (Time )
1445
+ instance .__unchecked_init (ticks , hour , minutes , second , nano , tz )
1425
1446
return instance
1426
1447
1448
+ def __unchecked_init (
1449
+ self ,
1450
+ ticks : int ,
1451
+ hour : int ,
1452
+ minutes : int ,
1453
+ second : int ,
1454
+ nano : int ,
1455
+ tz : t .Optional [_tzinfo ]
1456
+ ) -> None :
1457
+ self .__ticks = ticks
1458
+ self .__hour = hour
1459
+ self .__minute = minutes
1460
+ self .__second = second
1461
+ self .__nanosecond = nano
1462
+ self .__tzinfo = tz
1463
+
1427
1464
# CLASS METHODS #
1428
1465
1429
1466
@classmethod
@@ -1521,7 +1558,8 @@ def from_ticks(cls, ticks: int, tz: t.Optional[_tzinfo] = None) -> Time:
1521
1558
second , nanosecond = divmod (ticks , NANO_SECONDS )
1522
1559
minute , second = divmod (second , 60 )
1523
1560
hour , minute = divmod (minute , 60 )
1524
- return cls .__new (ticks , hour , minute , second , nanosecond , tz )
1561
+ return cls .__unchecked_new (ticks , hour , minute , second , nanosecond ,
1562
+ tz )
1525
1563
raise ValueError ("Ticks out of range (0..86400000000000)" )
1526
1564
1527
1565
@classmethod
@@ -1619,7 +1657,7 @@ def utc_now(cls) -> Time:
1619
1657
1620
1658
__nanosecond = 0
1621
1659
1622
- __tzinfo = None
1660
+ __tzinfo : t . Optional [ _tzinfo ] = None
1623
1661
1624
1662
@property
1625
1663
def ticks (self ) -> int :
@@ -1751,13 +1789,6 @@ def __gt__(self, other: t.Union[Time, time]) -> bool:
1751
1789
return NotImplemented
1752
1790
return self_ticks > other_ticks
1753
1791
1754
- def __copy__ (self ) -> Time :
1755
- return self .__new (self .__ticks , self .__hour , self .__minute ,
1756
- self .__second , self .__nanosecond , self .__tzinfo )
1757
-
1758
- def __deepcopy__ (self , * args , ** kwargs ) -> Time :
1759
- return self .__copy__ ()
1760
-
1761
1792
# INSTANCE METHODS #
1762
1793
1763
1794
if t .TYPE_CHECKING :
@@ -2126,6 +2157,10 @@ def combine( # type: ignore[override]
2126
2157
"""
2127
2158
assert isinstance (date , Date )
2128
2159
assert isinstance (time , Time )
2160
+ return cls ._combine (date , time )
2161
+
2162
+ @classmethod
2163
+ def _combine (cls , date : Date , time : Time ) -> DateTime :
2129
2164
instance = object .__new__ (cls )
2130
2165
instance .__date = date
2131
2166
instance .__time = time
@@ -2491,11 +2526,15 @@ def __sub__(self, other):
2491
2526
return self .__add__ (- other )
2492
2527
return NotImplemented
2493
2528
2494
- def __copy__ (self ) -> DateTime :
2495
- return self . combine (self . __date , self .__time )
2529
+ def __reduce__ (self ):
2530
+ return type (self ). _restore , ( self .__dict__ , )
2496
2531
2497
- def __deepcopy__ (self , memo ) -> DateTime :
2498
- return self .__copy__ ()
2532
+ @classmethod
2533
+ def _restore (cls , dict_ ):
2534
+ instance = object .__new__ (cls )
2535
+ if dict_ :
2536
+ instance .__dict__ .update (dict_ )
2537
+ return instance
2499
2538
2500
2539
# INSTANCE METHODS #
2501
2540
0 commit comments