7171 Logger ,
7272 StreamHandler ,
7373)
74- from typing import List , Optional , cast
74+ from typing import List , Optional , Union , cast
7575
7676from typeguard import typechecked
7777
@@ -130,6 +130,11 @@ class LogLevel(Enum):
130130"""
131131
132132
133+ # sentinel
134+ _UNSET = object ()
135+ _UnsetType = object # just for readability in the union
136+
137+
133138class ArkoudaLogger (Logger ):
134139 DEFAULT_LOG_FORMAT = "[%(name)s] Line %(lineno)d %(levelname)s: %(message)s"
135140
@@ -147,7 +152,7 @@ class ArkoudaLogger(Logger):
147152 def __init__ (
148153 self ,
149154 name : str ,
150- log_level : LogLevel = LogLevel . INFO ,
155+ log_level : Union [ LogLevel , _UnsetType ] = _UNSET , # sentinel means "not provided"
151156 handlers : Optional [List [Handler ]] = None ,
152157 log_format : Optional [str ] = "[%(name)s] Line %(lineno)d %(levelname)s: %(message)s" ,
153158 ** kwargs ,
@@ -200,25 +205,37 @@ def __init__(
200205 the individual handlers.
201206
202207 """
208+ # --- log_level alias handling ---
203209 if "logLevel" in kwargs :
204- if log_level is not None :
210+ if log_level is not _UNSET :
205211 raise TypeError ("Pass only one of 'logLevel' or 'log_level'" )
206212 warnings .warn (
207213 "'logLevel' is deprecated; use 'log_level' instead" ,
208214 DeprecationWarning ,
209215 stacklevel = 2 ,
210216 )
211217 log_level = kwargs .pop ("logLevel" )
218+ elif log_level is _UNSET :
219+ log_level = LogLevel .INFO
212220
221+ # --- log_format alias handling ---
213222 if "logFormat" in kwargs :
214- if log_format is not None :
223+ if log_format is not _UNSET :
215224 raise TypeError ("Pass only one of 'logFormat' or 'log_format'" )
216225 warnings .warn (
217226 "'logFormat' is deprecated; use 'log_format' instead" ,
218227 DeprecationWarning ,
219228 stacklevel = 2 ,
220229 )
221230 log_format = kwargs .pop ("logFormat" )
231+ elif log_format is _UNSET :
232+ log_format = "[%(name)s] Line %(lineno)d %(levelname)s: %(message)s"
233+
234+ if not isinstance (log_level , LogLevel ):
235+ raise TypeError ("log_level must be a LogLevel" )
236+
237+ if not isinstance (log_format , str ):
238+ raise TypeError ("log_format must be a str" )
222239
223240 if kwargs :
224241 raise TypeError (f"Unexpected keyword argument(s): { ', ' .join (kwargs )} " )
@@ -276,7 +293,7 @@ def enableVerbose(self) -> None:
276293 self .changeLogLevel (LogLevel .DEBUG )
277294
278295 @typechecked
279- def disableVerbose (self , log_level : LogLevel = LogLevel . INFO , ** kwargs ) -> None :
296+ def disableVerbose (self , log_level : object = _UNSET , ** kwargs ) -> None :
280297 """
281298 Disables verbose output.
282299
@@ -293,20 +310,25 @@ def disableVerbose(self, log_level: LogLevel = LogLevel.INFO, **kwargs) -> None:
293310 ------
294311 TypeError
295312 Raised if log_level is not a LogLevel enum
296-
297313 """
298314 if "logLevel" in kwargs :
299- if log_level is not None :
315+ if log_level is not _UNSET :
300316 raise TypeError ("Pass only one of 'logLevel' or 'log_level'" )
301317 warnings .warn (
302318 "'logLevel' is deprecated; use 'log_level' instead" ,
303319 DeprecationWarning ,
304320 stacklevel = 2 ,
305321 )
306322 log_level = kwargs .pop ("logLevel" )
323+ elif log_level is _UNSET :
324+ log_level = LogLevel .INFO
307325
308326 if kwargs :
309327 raise TypeError (f"Unexpected keyword argument(s): { ', ' .join (kwargs )} " )
328+
329+ if not isinstance (log_level , LogLevel ):
330+ raise TypeError ("log_level must be a LogLevel" )
331+
310332 self .changeLogLevel (log_level )
311333
312334 @typechecked
@@ -338,62 +360,64 @@ def getHandler(self, name: str) -> Handler:
338360 raise ValueError (f"The name { name } does not match any handler" )
339361
340362
363+ _UNSET = object ()
364+
365+
341366@typechecked
342367def getArkoudaLogger (
343368 name : str ,
344369 handlers : Optional [List [Handler ]] = None ,
345- log_format : Optional [ str ] = ArkoudaLogger . DEFAULT_LOG_FORMAT ,
346- log_level : Optional [ LogLevel ] = None ,
370+ log_format : object = _UNSET ,
371+ log_level : object = _UNSET ,
347372 ** kwargs ,
348373) -> ArkoudaLogger :
349- """
350- Instantiate an ArkoudaLogger that retrieves the logging level from ARKOUDA_LOG_LEVEL env variable.
351-
352- Parameters
353- ----------
354- name : str
355- The name of the ArkoudaLogger
356- handlers : List[Handler]
357- A list of logging.Handler objects, if None, a list consisting of
358- one StreamHandler named 'console-handler' is generated and configured
359- log_format : str
360- The format for log messages, defaults to the following format:
361- '[%(name)s] Line %(lineno)d %(levelname)s: %(message)s'
362-
363- Returns
364- -------
365- ArkoudaLogger
366-
367- Raises
368- ------
369- TypeError
370- Raised if either name or log_format is not a str object or if handlers
371- is not a list of str objects
372-
373- Notes
374- -----
375- Important note: if a list of 1..n logging.Handler objects is passed in, and
376- dynamic changes to 1..n handlers is desired, set a name for each Handler
377- object as follows: handler.name = <desired name>, which will enable retrieval
378- and updates for the specified handler.
379-
380- """
374+ # --- deprecated alias: logFormat -> log_format ---
381375 if "logFormat" in kwargs :
382- if log_format is not None and kwargs ["logFormat" ] is not None :
383- raise TypeError ("Pass only one of logFormat or log_format" )
384- warnings .warn ("logFormat is deprecated; use log_format" , DeprecationWarning , stacklevel = 2 )
376+ if log_format is not _UNSET :
377+ raise TypeError ("Pass only one of 'logFormat' or 'log_format'" )
378+ warnings .warn (
379+ "'logFormat' is deprecated; use 'log_format' instead" ,
380+ DeprecationWarning ,
381+ stacklevel = 2 ,
382+ )
385383 log_format = kwargs .pop ("logFormat" )
386384
385+ # --- deprecated alias: logLevel -> log_level ---
387386 if "logLevel" in kwargs :
388- if log_level is not None and kwargs ["logLevel" ] is not None :
389- raise TypeError ("Pass only one of logLevel or log_level" )
390- warnings .warn ("logLevel is deprecated; use log_level" , DeprecationWarning , stacklevel = 2 )
387+ if log_level is not _UNSET :
388+ raise TypeError ("Pass only one of 'logLevel' or 'log_level'" )
389+ warnings .warn (
390+ "'logLevel' is deprecated; use 'log_level' instead" ,
391+ DeprecationWarning ,
392+ stacklevel = 2 ,
393+ )
391394 log_level = kwargs .pop ("logLevel" )
392395
393- if not log_level :
394- log_level = LogLevel ( os . getenv ( "ARKOUDA_LOG_LEVEL" , LogLevel ( "INFO" )) )
396+ if kwargs :
397+ raise TypeError ( f"Unexpected keyword argument(s): { ', ' . join ( kwargs ) } " )
395398
396- logger = ArkoudaLogger (name = name , handlers = handlers , log_format = log_format , log_level = log_level )
399+ # defaults
400+ if log_format is _UNSET :
401+ log_format = ArkoudaLogger .DEFAULT_LOG_FORMAT
402+ if log_level is _UNSET :
403+ env_val = os .getenv ("ARKOUDA_LOG_LEVEL" , "INFO" )
404+ try :
405+ log_level = LogLevel (env_val )
406+ except Exception as e :
407+ raise ValueError (f"Invalid ARKOUDA_LOG_LEVEL={ env_val !r} " ) from e
408+
409+ # validate types (since we used object for sentinel)
410+ if not isinstance (log_format , str ):
411+ raise TypeError ("log_format must be a str" )
412+ if not isinstance (log_level , LogLevel ):
413+ raise TypeError ("log_level must be a LogLevel" )
414+
415+ logger = ArkoudaLogger (
416+ name = name ,
417+ handlers = handlers ,
418+ log_format = log_format ,
419+ log_level = log_level ,
420+ )
397421 loggers [logger .name ] = logger
398422 return logger
399423
@@ -437,8 +461,11 @@ def enableVerbose() -> None:
437461 logger .enableVerbose ()
438462
439463
464+ _UNSET = object ()
465+
466+
440467@typechecked
441- def disableVerbose (log_level : LogLevel = LogLevel . INFO , ** kwargs ) -> None :
468+ def disableVerbose (log_level : object = _UNSET , ** kwargs ) -> None :
442469 """
443470 Disables verbose logging.
444471
@@ -448,27 +475,31 @@ def disableVerbose(log_level: LogLevel = LogLevel.INFO, **kwargs) -> None:
448475 Parameters
449476 ----------
450477 log_level : LogLevel
451- The new log level, defaultts to LogLevel.INFO
478+ The new log level, defaults to LogLevel.INFO
452479
453480 Raises
454481 ------
455482 TypeError
456483 Raised if log_level is not a LogLevel enum
457-
458484 """
459485 if "logLevel" in kwargs :
460- if log_level is not None :
486+ if log_level is not _UNSET :
461487 raise TypeError ("Pass only one of 'logLevel' or 'log_level'" )
462488 warnings .warn (
463489 "'logLevel' is deprecated; use 'log_level' instead" ,
464490 DeprecationWarning ,
465491 stacklevel = 2 ,
466492 )
467493 log_level = kwargs .pop ("logLevel" )
494+ elif log_level is _UNSET :
495+ log_level = LogLevel .INFO
468496
469497 if kwargs :
470498 raise TypeError (f"Unexpected keyword argument(s): { ', ' .join (kwargs )} " )
471499
500+ if not isinstance (log_level , LogLevel ):
501+ raise TypeError ("log_level must be a LogLevel" )
502+
472503 for logger in loggers .values ():
473504 logger .disableVerbose (log_level )
474505
0 commit comments