1+ from __future__ import annotations
2+
13import datetime
24import re
3- from typing import Union , Tuple , Optional , List
5+ from datetime import timedelta
6+ from typing import Optional , Union
47
58DateIsh = Union [datetime .date , datetime .datetime ]
69
710
8- def total_seconds (td ) :
11+ def total_seconds (td : timedelta ) -> float :
912 """Equivalent to `datetime.timedelta.total_seconds`."""
1013 return float (td .microseconds +
1114 (td .seconds + td .days * 24 * 3600 ) * 10 ** 6 ) / 10 ** 6
1215
1316
14- def total_minutes (td ) :
17+ def total_minutes (td : timedelta ) -> float :
1518 """Alias for ``total_seconds(td) / 60``."""
1619 return total_seconds (td ) / 60
1720
1821
19- def gene_timestamp_regex (brtype , prefix = None , nocookie = False ):
22+ def gene_timestamp_regex (brtype : str , prefix : str | None = None , * , nocookie : bool = False ) -> str :
2023 """
2124 Generate timestamp regex for active/inactive/nobrace brace type
2225
@@ -84,15 +87,15 @@ def gene_timestamp_regex(brtype, prefix=None, nocookie=False):
8487 elif brtype == 'nobrace' :
8588 (bo , bc ) = ('' , '' )
8689 else :
87- raise ValueError ("brtype='{0 !r}' is invalid" . format ( brtype ) )
90+ raise ValueError (f "brtype='{ brtype !r} ' is invalid" )
8891
8992 if brtype == 'nobrace' :
9093 ignore = r'[\s\w]'
9194 else :
92- ignore = '[^{bc}]' . format ( bc = bc )
95+ ignore = f '[^{ bc } ]'
9396
9497 if prefix is None :
95- prefix = '{0 }_'. format ( brtype )
98+ prefix = f' { brtype } _'
9699
97100 regex_date_time = r"""
98101 (?P<{prefix}year>\d{{4}}) -
@@ -133,7 +136,7 @@ def gene_timestamp_regex(brtype, prefix=None, nocookie=False):
133136 return regex .format (prefix = prefix , ignore = ignore )
134137
135138
136- def date_time_format (date ) -> str :
139+ def date_time_format (date : DateIsh ) -> str :
137140 """
138141 Format a date or datetime in default org format
139142
@@ -165,7 +168,10 @@ def is_same_day(date0, date1) -> bool:
165168 re .VERBOSE )
166169
167170
168- class OrgDate (object ):
171+ _Repeater = tuple [str , int , str ]
172+
173+
174+ class OrgDate :
169175
170176 _active_default = True
171177 """
@@ -184,8 +190,14 @@ class OrgDate(object):
184190 """
185191 _allow_short_range = True
186192
187- def __init__ (self , start , end = None , active = None , repeater = None ,
188- warning = None ):
193+ def __init__ (
194+ self ,
195+ start ,
196+ end = None ,
197+ active : bool | None = None ,
198+ repeater : _Repeater | None = None ,
199+ warning : _Repeater | None = None ,
200+ ) -> None :
189201 """
190202 Create :class:`OrgDate` object
191203
@@ -242,21 +254,23 @@ def _to_date(date) -> DateIsh:
242254 raise ValueError (
243255 "Automatic conversion to the datetime object "
244256 "requires at least 3 elements in the tuple. "
245- "Only {0 } elements are in the given tuple '{1 }'."
246- . format ( len ( date ), date ) )
257+ f "Only { len ( date ) } elements are in the given tuple '{ date } '."
258+ )
247259 elif isinstance (date , (int , float )):
248260 return datetime .datetime .fromtimestamp (date )
249261 else :
250262 return date
251263
252264 @staticmethod
253- def _date_to_tuple (date ) :
265+ def _date_to_tuple (date : DateIsh ) -> tuple [ int , ...] :
254266 if isinstance (date , datetime .datetime ):
255267 return tuple (date .timetuple ()[:6 ])
256268 elif isinstance (date , datetime .date ):
257269 return tuple (date .timetuple ()[:3 ])
270+ else :
271+ raise RuntimeError (f"can't happen: { date } " )
258272
259- def __repr__ (self ):
273+ def __repr__ (self ) -> str :
260274 args = [
261275 self .__class__ .__name__ ,
262276 self ._date_to_tuple (self .start ),
@@ -269,36 +283,36 @@ def __repr__(self):
269283 args .pop ()
270284 if len (args ) > 3 and args [3 ] is None :
271285 args [3 ] = self ._active_default
272- return '{0 }({1 })' .format (args [0 ], ', ' .join (map (repr , args [1 :])))
286+ return '{}({})' .format (args [0 ], ', ' .join (map (repr , args [1 :])))
273287
274- def __str__ (self ):
288+ def __str__ (self ) -> str :
275289 fence = ("<" , ">" ) if self .is_active () else ("[" , "]" )
276290
277291 start = date_time_format (self .start )
278292 end = None
279293
280294 if self .has_end ():
281295 if self ._allow_short_range and is_same_day (self .start , self .end ):
282- start += "--%s" % self .end .strftime ("%H:%M" )
296+ start += "--{}" . format ( self .end .strftime ("%H:%M" ) )
283297 else :
284298 end = date_time_format (self .end )
285299
286- if self ._repeater :
287- start += " %s%d%s" % self ._repeater
288- if self ._warning :
289- start += " %s%d%s" % self ._warning
290- ret = "%s%s%s" % (fence [0 ], start , fence [1 ])
300+ if self ._repeater is not None :
301+ (x , y , z ) = self ._repeater
302+ start += f" { x } { y } { z } "
303+ if self ._warning is not None :
304+ (x , y , z ) = self ._warning
305+ start += f" { x } { y } { z } "
306+ ret = f"{ fence [0 ]} { start } { fence [1 ]} "
291307 if end :
292- ret += "--%s%s%s" % ( fence [0 ], end , fence [1 ])
308+ ret += f "--{ fence [0 ]} { end } { fence [1 ]} "
293309
294310 return ret
295311
296- def __nonzero__ (self ):
312+ def __bool__ (self ) -> bool :
297313 return bool (self ._start )
298314
299- __bool__ = __nonzero__ # PY3
300-
301- def __eq__ (self , other ):
315+ def __eq__ (self , other ) -> bool :
302316 if (isinstance (other , OrgDate ) and
303317 self ._start is None and
304318 other ._start is None ):
@@ -309,7 +323,7 @@ def __eq__(self, other):
309323 self ._active == other ._active )
310324
311325 @property
312- def start (self ):
326+ def start (self ) -> DateIsh :
313327 """
314328 Get date or datetime object
315329
@@ -322,7 +336,7 @@ def start(self):
322336 return self ._start
323337
324338 @property
325- def end (self ):
339+ def end (self ) -> DateIsh :
326340 """
327341 Get date or datetime object
328342
@@ -404,11 +418,11 @@ def _as_datetime(date) -> datetime.datetime:
404418 return date
405419
406420 @staticmethod
407- def _daterange_from_groupdict (dct , prefix = '' ) -> Tuple [ List , Optional [List ]]:
421+ def _daterange_from_groupdict (dct , prefix = '' ) -> tuple [ list , Optional [list ]]:
408422 start_keys = ['year' , 'month' , 'day' , 'hour' , 'min' ]
409423 end_keys = ['year' , 'month' , 'day' , 'end_hour' , 'end_min' ]
410424 start_range = list (map (int , filter (None , (dct [prefix + k ] for k in start_keys ))))
411- end_range : Optional [List ]
425+ end_range : Optional [list ]
412426 end_range = list (map (int , filter (None , (dct [prefix + k ] for k in end_keys ))))
413427 if len (end_range ) < len (end_keys ):
414428 end_range = None
@@ -419,7 +433,7 @@ def _datetuple_from_groupdict(cls, dct, prefix=''):
419433 return cls ._daterange_from_groupdict (dct , prefix = prefix )[0 ]
420434
421435 @classmethod
422- def list_from_str (cls , string : str ) -> List [ ' OrgDate' ]:
436+ def list_from_str (cls , string : str ) -> list [ OrgDate ]:
423437 """
424438 Parse string and return a list of :class:`OrgDate` objects
425439
@@ -447,8 +461,8 @@ def list_from_str(cls, string: str) -> List['OrgDate']:
447461 prefix = 'inactive_'
448462 active = False
449463 rangedash = '--['
450- repeater : Optional [Tuple [str , int , str ]] = None
451- warning : Optional [Tuple [str , int , str ]] = None
464+ repeater : Optional [tuple [str , int , str ]] = None
465+ warning : Optional [tuple [str , int , str ]] = None
452466 if mdict [prefix + 'repeatpre' ] is not None :
453467 keys = [prefix + 'repeat' + suffix for suffix in cookie_suffix ]
454468 values = [mdict [k ] for k in keys ]
@@ -471,12 +485,12 @@ def list_from_str(cls, string: str) -> List['OrgDate']:
471485 odate = cls (
472486 * cls ._daterange_from_groupdict (mdict , prefix ),
473487 active = active , repeater = repeater , warning = warning )
474- return [odate ] + cls .list_from_str (rest )
488+ return [odate , * cls .list_from_str (rest )]
475489 else :
476490 return []
477491
478492 @classmethod
479- def from_str (cls , string ) :
493+ def from_str (cls , string : str ) -> OrgDate :
480494 """
481495 Parse string and return an :class:`OrgDate` objects.
482496
@@ -500,7 +514,7 @@ def from_str(cls, string):
500514def compile_sdc_re (sdctype ):
501515 brtype = 'inactive' if sdctype == 'CLOSED' else 'active'
502516 return re .compile (
503- r'^(?!\#).*{0 }:\s+{1 }' .format (
517+ r'^(?!\#).*{}:\s+{}' .format (
504518 sdctype ,
505519 gene_timestamp_regex (brtype , prefix = '' , nocookie = True )),
506520 re .VERBOSE )
@@ -528,8 +542,8 @@ def from_str(cls, string):
528542 end_dict .update ({'hour' : end_hour , 'min' : end_min })
529543 end = cls ._datetuple_from_groupdict (end_dict )
530544 cookie_suffix = ['pre' , 'num' , 'dwmy' ]
531- repeater : Optional [Tuple [str , int , str ]] = None
532- warning : Optional [Tuple [str , int , str ]] = None
545+ repeater : Optional [tuple [str , int , str ]] = None
546+ warning : Optional [tuple [str , int , str ]] = None
533547 prefix = ''
534548 if mdict [prefix + 'repeatpre' ] is not None :
535549 keys = [prefix + 'repeat' + suffix for suffix in cookie_suffix ]
@@ -588,7 +602,7 @@ def __init__(self, start, end=None, duration=None, active=None):
588602 """
589603 Create OrgDateClock object
590604 """
591- super (OrgDateClock , self ).__init__ (start , end , active = active )
605+ super ().__init__ (start , end , active = active )
592606 self ._duration = duration
593607
594608 @property
@@ -625,7 +639,7 @@ def is_duration_consistent(self):
625639 self ._duration == total_minutes (self .duration ))
626640
627641 @classmethod
628- def from_str (cls , line : str ) -> ' OrgDateClock' :
642+ def from_str (cls , line : str ) -> OrgDateClock :
629643 """
630644 Get CLOCK from given string.
631645
@@ -674,26 +688,26 @@ class OrgDateRepeatedTask(OrgDate):
674688
675689 _active_default = False
676690
677- def __init__ (self , start , before , after , active = None ):
678- super (OrgDateRepeatedTask , self ).__init__ (start , active = active )
691+ def __init__ (self , start , before : str , after : str , active = None ) -> None :
692+ super ().__init__ (start , active = active )
679693 self ._before = before
680694 self ._after = after
681695
682- def __repr__ (self ):
683- args = [self ._date_to_tuple (self .start ), self .before , self .after ]
696+ def __repr__ (self ) -> str :
697+ args : list = [self ._date_to_tuple (self .start ), self .before , self .after ]
684698 if self ._active is not self ._active_default :
685699 args .append (self ._active )
686- return '{0 }({1 })' .format (
700+ return '{}({})' .format (
687701 self .__class__ .__name__ , ', ' .join (map (repr , args )))
688702
689- def __eq__ (self , other ):
690- return super (OrgDateRepeatedTask , self ).__eq__ (other ) and \
703+ def __eq__ (self , other ) -> bool :
704+ return super ().__eq__ (other ) and \
691705 isinstance (other , self .__class__ ) and \
692706 self ._before == other ._before and \
693707 self ._after == other ._after
694708
695709 @property
696- def before (self ):
710+ def before (self ) -> str :
697711 """
698712 The state of task before marked as done.
699713
@@ -705,7 +719,7 @@ def before(self):
705719 return self ._before
706720
707721 @property
708- def after (self ):
722+ def after (self ) -> str :
709723 """
710724 The state of task after marked as done.
711725
0 commit comments