@@ -234,6 +234,75 @@ def log(self, value: bool):
234234 raise ValueError ("log must be a boolean value" )
235235 self ._log = value
236236
237+ def parse_printer (self , printer : Printer | None ) -> Printer :
238+ """Parse the printer argument.
239+
240+ If the printer is None, return the default printer.
241+ If the printer is a callable, return it.
242+ Otherwise, raise an error.
243+
244+ Args:
245+ printer (Printer | None): The printer to use.
246+
247+ Returns:
248+ Printer: The printer to use.
249+
250+ Raises:
251+ ValueError: If the printer is not a callable or None.
252+
253+ """
254+ if printer is None :
255+ return self .printer
256+ if not callable (printer ):
257+ raise ValueError ("printer must be a callable function or None" )
258+ return printer
259+
260+ def parse_res (self , res : int | None ) -> int :
261+ """Parse the res argument.
262+
263+ If res is None, return the default res.
264+ If res is an int, return it.
265+ Otherwise, raise an error.
266+
267+ Args:
268+ res (int | None): The number of decimal places to round to.
269+
270+ Returns:
271+ int: The number of decimal places to round to.
272+
273+ Raises:
274+ ValueError: If res is not an int or None.
275+
276+ """
277+ if res is None :
278+ return self .res
279+ if not isinstance (res , int ) or res < 0 :
280+ raise ValueError ("res must be a non-negative integer or None" )
281+ return res
282+
283+ def parse_log (self , log : bool | None ) -> bool :
284+ """Parse the log argument.
285+
286+ If log is None, return the default log setting.
287+ If log is a bool, return it.
288+ Otherwise, raise an error.
289+
290+ Args:
291+ log (bool | None): Whether to log the duration at occurence.
292+
293+ Returns:
294+ bool: Whether to log the duration at occurence.
295+
296+ Raises:
297+ ValueError: If log is not a boolean or None.
298+
299+ """
300+ if log is None :
301+ return self .log
302+ if not isinstance (log , bool ):
303+ raise ValueError ("log must be a boolean value or None" )
304+ return log
305+
237306 def reset (self ):
238307 """Reset the durations."""
239308 self .durations : dict [str , list [float ]] = defaultdict (list )
@@ -300,7 +369,7 @@ def combine(*timers: "Chronometer") -> "Chronometer":
300369
301370 return combined
302371
303- def summary (self , res : int | None = None , printer : Printer | None = None ):
372+ def summary (self , * , res : int | None = None , printer : Printer | None = None ):
304373 """Print a summary of the durations.
305374
306375 Args:
@@ -310,8 +379,8 @@ def summary(self, res: int | None = None, printer: Printer | None = None):
310379 Defaults to None.
311380
312381 """
313- res = res or self .res
314- printer = printer or self .printer
382+ res = self .parse_res ( res )
383+ printer = self .parse_printer ( printer )
315384 for key , values in self .durations .items ():
316385 if not values :
317386 printer (f"{ key } has no durations recorded" )
@@ -334,9 +403,10 @@ def start(self, key: str):
334403 key (str): The msg / key to store the start time under.
335404
336405 """
406+ assert isinstance (key , str ), "key must be a string"
337407 self .idling_starts [key ].append (time .perf_counter ())
338408
339- def stop (self , key : str , res : int | None = None , log : bool | None = None , printer : Printer | None = None ):
409+ def stop (self , key : str , * , res : int | None = None , log : bool | None = None , printer : Printer | None = None ):
340410 """Stop the timer for a key.
341411
342412 Args:
@@ -349,9 +419,10 @@ def stop(self, key: str, res: int | None = None, log: bool | None = None, printe
349419 Defaults to None.
350420
351421 """
352- res = res or self .res
353- log = log if log is not None else self .log
354- printer = printer or self .printer
422+ assert isinstance (key , str ), "key must be a string"
423+ res = self .parse_res (res )
424+ log = self .parse_log (log )
425+ printer = self .parse_printer (printer )
355426 end = time .perf_counter ()
356427 try :
357428 start = self .idling_starts [key ].pop (0 )
@@ -365,6 +436,7 @@ def stop(self, key: str, res: int | None = None, log: bool | None = None, printe
365436 def f (
366437 self ,
367438 key : str ,
439+ * ,
368440 res : int | None = None ,
369441 log : bool | None = None ,
370442 printer : Printer | None = None ,
@@ -396,9 +468,10 @@ def f(
396468 ValueError: If any of the print_kwargs are not in the functions signature.
397469
398470 """
399- res = res or self .res
400- log = log if log is not None else self .log
401- printer = printer or self .printer
471+ assert isinstance (key , str ), "key must be a string"
472+ res = self .parse_res (res )
473+ log = self .parse_log (log )
474+ printer = self .parse_printer (printer )
402475
403476 def _decorator (func ):
404477 func_signature = signature (func )
@@ -441,6 +514,7 @@ def _inner(*args, **kwargs):
441514 def __call__ (
442515 self ,
443516 key : str ,
517+ * ,
444518 res : int | None = None ,
445519 log : bool | None = None ,
446520 printer : Printer | None = None ,
0 commit comments