API Reference
Complete API documentation for Apathetic Python Logger.
Note: This library uses camelCase naming to match Pythonâs standard library
loggingmodule conventions.By default, this library provides improved behavior with enhancements over the standard library. For stdlib-compatible behavior with no breaking changes, enable Compatibility Mode.
Quick Reference: apathetic_logging Module Functions
* Improvements over Stdlib logging
\â Ported or fallthrough to Stdlib logging
Setup
| Function | Summary |
|---|---|
basicConfig()â |
Configure logging system |
getLevelName()* / getLevelNameStr() |
Convert a log level to its string name (always returns string) |
getLevelNumber() |
Convert a log level name to its numeric value |
getLogger()* |
Return the registered logger instance (auto-infers name when None) |
getLoggerOfType() |
Get a logger of the specified type, creating it if necessary |
getRootLogger() |
Return the root logger instance (primary way to access root logger) |
registerLogger() |
Register a logger for use by getLogger() |
setLoggerClass()â |
Set the class to be used when instantiating a logger |
shutdown()â |
Perform an orderly shutdown of the logging system |
Root Logger Convenience API
For applications using the root logger as the single source of truth for log levels:
| Function | Summary |
|---|---|
getRootLevel() |
Get current root logger level |
getRootLevelName() |
Get current root logger level name |
getEffectiveRootLevel() |
Get effective root logger level |
getEffectiveRootLevelName() |
Get effective root logger level name |
setRootLevel() |
Set root logger level (and optionally children) |
setRootLevelMinimum() |
Set root level only if more verbose |
useRootLevel() |
Context manager to temporarily set root level |
useRootLevelMinimum() |
Context manager to temporarily set root level (minimum) |
isRootEnabledFor() |
Check if root would log at level |
logRootDynamic() |
Log with dynamically provided level |
Logging Messages (to Root Logger)
| Function | Summary |
|---|---|
brief() |
Log a message with severity BRIEF |
critical()â / fatal()â |
Log a message with severity CRITICAL |
debug()â |
Log a message with severity DEBUG |
detail() |
Log a message with severity DETAIL |
error()â / exception()â |
Log a message with severity ERROR |
info()â |
Log a message with severity INFO |
log()â |
Log a message with an explicit level |
test() |
Log a message with severity TEST |
trace()â |
Log a message with severity TRACE |
warning()â / warn()â |
Log a message with severity WARNING |
Logging Extras
| captureWarnings()â | Capture warnings issued by the warnings module |
| currentframe()â | Return the frame object for the callerâs stack frame |
| disable()â | Disable all logging calls of severity âlevelâ and below |
Safety Logging
For when the framework isnât initialzied yet, or youâre troubleshooting.
| Function | Summary |
|---|---|
makeSafeTrace() |
Create a test trace function with a custom icon |
safeLog() |
Emergency logger that never fails |
safeTrace() |
Debug tracing function for test development |
Settings Registry
The library provides a registry system for configuring default settings that apply when creating loggers or performing operations. These settings allow you to bypass needing to pass parameters to every function call.
| Function | Purpose | Default Value |
|---|---|---|
registerCompatibilityMode() / getCompatibilityMode() |
Enable stdlib-compatible behavior | False (improved behavior) |
registerDefaultLogLevel() / getDefaultLogLevel() |
Default log level when no other source found | "INFO" |
registerLogLevelEnvVars() / getLogLevelEnvVars() |
Environment variables to check for log level | ["LOG_LEVEL"] |
registerLogger() / |
Register a logger for use by getLogger() |
 |
registerPortHandlers() |
Whether to port handlers when replacing loggers | True |
registerPortLevel() |
Whether to port level when replacing loggers | True |
registerPropagate() / getDefaultPropagate() |
Default propagate setting for loggers | False |
registerReplaceRootLogger() |
Whether to replace root logger if not correct type | True |
registerTargetPythonVersion() / getTargetPythonVersion() |
Target Python version for compatibility checking | (3, 10) |
Internal
For writing library extensions.
| Function | Summary |
|---|---|
addLevelName()â |
Associate a level name with a numeric level |
getDefaultLoggerName() |
Get default logger name with optional inference from callerâs frame |
getHandlerByName()â |
3.12+: Get a handler with the specified name |
getHandlerNames()â |
3.12+: Return all known handler names |
getLevelNamesMapping()â |
3.11+: Get mapping of level names to numeric values |
getLoggerClass()â |
Return the class to be used when instantiating a logger |
getLogRecordFactory()â |
Return the factory function used to create LogRecords |
getRegisteredLoggerName() |
Get the registered logger name |
getTargetPythonVersion() |
Get the target Python version |
hasLogger() |
Check if a logger exists in the logging managerâs registry |
isRootLoggerInstantiated() |
Check if the root logger has been instantiated |
makeLogRecord()â |
Create a LogRecord from the given parameters |
removeLogger() |
Remove a logger from the logging managerâs registry |
setLogRecordFactory()â |
Set the factory function used to create LogRecords |
Quick Reference: apathetic_logging.Logger Class Methods
* Improvements over Stdlib logging.Logger
\â Ported or fallthrough to Stdlib logging.Logger. See the Python logging.Logger documentation for the complete list.
Setup
| Method | Summary |
|---|---|
determineColorEnabled() |
Return True if colored output should be enabled (classmethod) |
determineLogLevel() |
Resolve log level from CLI â env â root config â default |
effectiveLevel |
Return the effective level (whatâs actually used) (property) |
effectiveLevelName |
Return the effective level name (whatâs actually used) (property) |
extendLoggingModule() |
Extend Pythonâs logging module with TRACE and SILENT levels (classmethod) |
getEffectiveLevelName() |
Return the effective level name (whatâs actually used) |
getLevel() |
Return the explicit level set on this logger |
getLevelName() |
Return the explicit level name set on this logger |
levelName |
Return the explicit level name set on this logger (property) |
setLevel()* |
Set the logging level (accepts string names and has minimum parameter) |
setLevelInherit() |
Set logger to inherit level from parent |
setLevelMinimum() |
Set level only if itâs more verbose than current level |
useLevel() |
Context manager to temporarily change log level |
useLevelMinimum() |
Context manager to temporarily change log level (only if more verbose) |
Advanced Setup
getChildren()â - 3.12+: Return a set of loggers that are immediate children of this logger |setLevelAndPropagate()| Set level and propagate together with smart defaults | |useLevelAndPropagate()| Context manager to temporarily set level and propagate together | |usePropagate()| Context manager to temporarily change propagate setting |
Logging Levels
| Method | Summary |
|---|---|
brief() |
Log a message at BRIEF level |
criticalIfNotDebug() |
Log a critical error with full traceback only if debug/trace is enabled |
detail() |
Log a message at DETAIL level |
errorIfNotDebug() |
Log an error with full traceback only if debug/trace is enabled |
logDynamic() |
Log a message at a dynamically specified level |
test() |
Log a message at TEST level |
trace() |
Log a message at TRACE level |
Logging Extras
| colorize() | Apply ANSI color codes to text |
Internal
| Method | Summary |
|---|---|
_log()* |
Log a message with the specified level (automatically ensures handlers) |
addLevelName()* |
Associate a level name with a numeric level (validates level > 0) (staticmethod) |
ensureHandlers() |
Ensure handlers are attached to this logger |
validateLevel() |
Validate that a level value is positive (> 0) (staticmethod) |
apathetic_logging Function Reference
addLevelName
addLevelName(level: int, level_name: str) -> None
Wrapper for logging.addLevelName(). Associate a level name with a numeric level.
For detailed documentation, see the Python logging.addLevelName() documentation.
basicConfig
basicConfig(*args: Any, **kwargs: Any) -> None
Wrapper for logging.basicConfig(). Configure the logging system.
For detailed documentation, see the Python logging.basicConfig() documentation.
brief
brief(msg: str, *args: Any, **kwargs: Any) -> None
Log a message with severity BRIEF on the root logger.
BRIEF is less detailed than INFO. This function gets an apathetic_logging.Logger instance (ensuring the root logger is an apathetic logger) and calls its brief() method.
If the logger has no handlers, basicConfig() is automatically called to add a console handler with a pre-defined format.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
import apathetic_logging
# Log a brief message
apathetic_logging.brief("brief information: %s", summary)
captureWarnings
captureWarnings(capture: bool, *args: Any, **kwargs: Any) -> None
Wrapper for logging.captureWarnings(). Redirect warnings to the logging package.
If capture is True, redirect all warnings issued by the warnings module to the logging package. If capture is False, ensure that warnings are not redirected to logging but to their original destinations.
For detailed documentation, see the Python logging.captureWarnings() documentation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
capture |
bool | If True, redirect warnings to logging. If False, restore original warning behavior. |
*args |
Any | Additional positional arguments (passed through to stdlib) |
**kwargs |
Any | Additional keyword arguments (passed through to stdlib) |
Example:
import apathetic_logging
import warnings
# Capture warnings and log them
apathetic_logging.captureWarnings(True)
warnings.warn("This warning will be logged")
# Stop capturing warnings
apathetic_logging.captureWarnings(False)
critical
critical(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.critical(). Log a message with severity CRITICAL.
For detailed documentation, see the Python logging.critical() documentation.
currentframe
currentframe(*args: Any, **kwargs: Any) -> FrameType | None
Wrapper for logging.currentframe(). Return the frame object for the callerâs stack frame.
For detailed documentation, see the Python logging.currentframe() documentation.
debug
debug(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.debug(). Log a message with severity DEBUG.
For detailed documentation, see the Python logging.debug() documentation.
detail
detail(msg: str, *args: Any, **kwargs: Any) -> None
Log a message with severity DETAIL on the root logger.
DETAIL is more detailed than INFO. This function gets an apathetic_logging.Logger instance (ensuring the root logger is an apathetic logger) and calls its detail() method.
If the logger has no handlers, basicConfig() is automatically called to add a console handler with a pre-defined format.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
import apathetic_logging
# Log a detail message
apathetic_logging.detail("Additional detail: %s", information)
disable
disable(level: int) -> None
Wrapper for logging.disable(). Disable all logging calls of severity âlevelâ and below.
For detailed documentation, see the Python logging.disable() documentation.
error
error(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.error(). Log a message with severity ERROR.
For detailed documentation, see the Python logging.error() documentation.
exception
exception(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.exception(). Log a message with severity ERROR with exception info.
For detailed documentation, see the Python logging.exception() documentation.
fatal
fatal(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.fatal(). Log a message with severity CRITICAL.
For detailed documentation, see the Python logging.fatal() documentation.
info
info(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.info(). Log a message with severity INFO on the root logger.
If the logger has no handlers, basicConfig() is automatically called to add a console handler with a pre-defined format.
For detailed documentation, see the Python logging.info() documentation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
import apathetic_logging
# Log an info message
apathetic_logging.info("Application started")
apathetic_logging.info("Processing %d items", count)
log
log(level: int, msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.log(). Log a message with an explicit level on the root logger.
If the logger has no handlers, basicConfig() is automatically called to add a console handler with a pre-defined format.
For detailed documentation, see the Python logging.log() documentation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | The numeric logging level (e.g., logging.DEBUG, logging.INFO) |
msg |
str | Message to log |
*args |
Any | Format arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
import apathetic_logging
import logging
# Log with explicit level
apathetic_logging.log(logging.INFO, "Info message")
apathetic_logging.log(logging.DEBUG, "Debug message: %s", variable)
apathetic_logging.log(logging.WARNING, "Warning: %d items processed", count)
getCompatibilityMode
getCompatibilityMode() -> bool
Get the compatibility mode setting.
Returns the registered compatibility mode setting, or False (improved behavior) if not registered.
Returns:
bool: Compatibility mode setting.Falsemeans improved behavior with enhancements (default).Truemeans stdlib-compatible behavior with no breaking changes.
Example:
from apathetic_logging import getCompatibilityMode
compat_mode = getCompatibilityMode()
print(compat_mode) # False (default: improved behavior)
getDefaultLogLevel
getDefaultLogLevel() -> str
Get the default log level.
Returns the registered default log level, or the default value if not registered.
Returns:
str: Default log level name
Example:
from apathetic_logging import getDefaultLogLevel
default_level = getDefaultLogLevel()
print(default_level) # "INFO" (default)
getDefaultLoggerName
getDefaultLoggerName(
logger_name: str | None = None,
*,
check_registry: bool = True,
skip_frames: int = 1,
raise_on_error: bool = False,
infer: bool = True,
register: bool = False
) -> str | None
Get default logger name with optional inference from callerâs frame.
Parameters:
| Parameter | Type | Description |
|---|---|---|
logger_name |
str | None | Explicit logger name, or None to infer (default: None) |
check_registry |
bool | If True, check registry before inferring (default: True) |
skip_frames |
int | Number of frames to skip (default: 1) |
raise_on_error |
bool | If True, raise RuntimeError if logger name cannot be resolved. If False (default), return None instead |
infer |
bool | If True (default), attempt to infer logger name from callerâs frame when not found in registry. If False, skip inference |
register |
bool | If True, store inferred name in registry. If False (default), do not modify registry. Note: Explicit names are never stored regardless of this parameter |
Returns:
str | None: Resolved logger name, or None if cannot be resolved and raise_on_error=False
Raises:
RuntimeError: If logger name cannot be resolved and raise_on_error=True
getDefaultPropagate
getDefaultPropagate() -> bool
Get the default propagate setting.
Returns the registered propagate setting, or the default value if not registered.
Returns:
bool: Default propagate setting
Example:
from apathetic_logging import getDefaultPropagate
propagate = getDefaultPropagate()
print(propagate) # False (default)
getHandlerByName
getHandlerByName(name: str) -> logging.Handler | None
Requires Python 3.12+
Wrapper for logging.getHandlerByName(). Get a handler with the specified name.
For detailed documentation, see the Python logging.getHandlerByName() documentation.
getHandlerNames
getHandlerNames() -> list[str]
Requires Python 3.12+
Wrapper for logging.getHandlerNames(). Return all known handler names.
For detailed documentation, see the Python logging.getHandlerNames() documentation.
getLevelName
getLevelName(level: int | str, *, strict: bool = False) -> str | int
Return the textual or numeric representation of a logging level.
Behavior depends on compatibility mode (set via registerCompatibilityMode()):
Compatibility mode enabled (compat_mode=True):
- Behaves like stdlib
logging.getLevelName()(bidirectional) - Returns
strfor integer input,intfor string input (known levels) - Returns
"Level {level}"string for unknown levels - Value-add: Uppercases string inputs before processing (case-insensitive)
Compatibility mode disabled (compat_mode=False, default):
- Accepts both integer and string input
- For string input: uppercases and returns the string (value-add, no conversion)
- For integer input: returns level name as string (never returns
int) - Optional strict mode to raise
ValueErrorfor unknown integer levels
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | str | Log level as integer or string name |
strict |
bool | If True, raise ValueError for unknown levels. If False (default), returns âLevel {level}â format for unknown integer levels (matching stdlib behavior). Only used when compatibility mode is disabled and level is an integer. |
Returns:
- Compatibility mode enabled:
str | int(bidirectional like stdlib) - Compatibility mode disabled:
str(always string; string input is uppercased and returned, int input is converted to name)
Raises:
ValueError: If strict=True and level is an integer that cannot be resolved to a known level name
Example:
from apathetic_logging import getLevelName, getLevelNumber, registerCompatibilityMode
# Compatibility mode enabled (stdlib-like behavior):
registerCompatibilityMode(compat_mode=True)
getLevelName(10) # "DEBUG" (str)
getLevelName("DEBUG") # 10 (int)
getLevelName("debug") # 10 (int, case-insensitive)
# Compatibility mode disabled (improved behavior):
registerCompatibilityMode(compat_mode=False)
getLevelName(10) # "DEBUG"
getLevelName("DEBUG") # "DEBUG" (uppercased and returned)
getLevelName("debug") # "DEBUG" (uppercased)
getLevelName(999, strict=True) # ValueError: Unknown log level: 999
# For stringâint conversion when compat mode disabled, use getLevelNumber()
getLevelNumber("DEBUG") # 10
getLevelNameStr
getLevelNameStr(level: int | str, *, strict: bool = False) -> str
Convert a log level to its string name representation.
Unidirectional function that always returns a string. This is the recommended way to convert log levels to strings when you want guaranteed string output without compatibility mode behavior.
Unlike getLevelName() which has compatibility mode and bidirectional behavior, this function always returns a string:
- Integer input: converts to level name string (returns âLevel {level}â for unknown levels unless strict=True)
- String input: validates level exists, then returns uppercased string
Handles all levels registered via logging.addLevelName() (including standard library levels, custom apathetic levels, and user-registered levels).
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | str | Log level as integer or string name (case-insensitive) |
strict |
bool | If True, raise ValueError for unknown integer levels. If False (default), returns âLevel {level}â format for unknown integer levels (matching stdlib behavior). |
Returns:
str: Level name as uppercase string
Raises:
ValueError: If string level cannot be resolved to a known level, or if strict=True and integer level cannot be resolved to a known level
Example:
from apathetic_logging import getLevelNameStr
# Integer input converts to level name
getLevelNameStr(10) # "DEBUG"
getLevelNameStr(5) # "TRACE"
getLevelNameStr(20) # "INFO"
# String input validates and returns uppercased string
getLevelNameStr("DEBUG") # "DEBUG"
getLevelNameStr("debug") # "DEBUG"
getLevelNameStr("Info") # "INFO"
# Unknown integer levels return "Level {level}" format (strict=False, default)
getLevelNameStr(999) # "Level 999"
# Unknown integer levels raise ValueError when strict=True
getLevelNameStr(999, strict=True) # ValueError: Unknown log level: 999
# Unknown string input raises ValueError
getLevelNameStr("UNKNOWN") # ValueError: Unknown log level: 'UNKNOWN'
See Also:
getLevelNumber()- Convert string to int (complementary function)getLevelName()- Bidirectional conversion with compatibility mode
getLevelNamesMapping
getLevelNamesMapping() -> dict[int, str]
Requires Python 3.11+
Wrapper for logging.getLevelNamesMapping(). Get mapping of level names to numeric values.
For detailed documentation, see the Python logging.getLevelNamesMapping() documentation.
getLevelNumber
getLevelNumber(level: str | int) -> int
Convert a log level name to its numeric value.
Recommended way to convert string level names to integers. This function explicitly performs stringâint conversion, unlike getLevelName() which has bidirectional behavior for backward compatibility.
Handles all levels registered via logging.addLevelName() (including standard library levels, custom apathetic levels, and user-registered levels).
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level as string name (case-insensitive) or integer |
Returns:
int: Integer level value
Raises:
ValueError: If level cannot be resolved to a known level
Example:
from apathetic_logging import getLevelNumber
# Known levels return int
getLevelNumber("DEBUG") # 10
getLevelNumber("TRACE") # 5
getLevelNumber(20) # 20
# Unknown level raises ValueError
getLevelNumber("UNKNOWN") # ValueError: Unknown log level: 'UNKNOWN'
See Also:
getLevelName()- Bidirectional conversion with compatibility modegetLevelNameStr()- Unidirectional conversion (always returns string)
getLogLevelEnvVars
getLogLevelEnvVars() -> list[str]
Get the environment variable names to check for log level.
Returns the registered environment variable names, or the default environment variables if none are registered. These environment variables are checked in order by determineLogLevel() when resolving the log level.
Returns:
list[str]: List of environment variable names to check for log level. Defaults to["LOG_LEVEL"]if not registered.
Example:
from apathetic_logging import getLogLevelEnvVars, registerLogLevelEnvVars
# Get default environment variables
env_vars = getLogLevelEnvVars()
print(env_vars) # ["LOG_LEVEL"]
# Register custom environment variables
registerLogLevelEnvVars(["MYAPP_LOG_LEVEL", "LOG_LEVEL"])
env_vars = getLogLevelEnvVars()
print(env_vars) # ["MYAPP_LOG_LEVEL", "LOG_LEVEL"]
See Also:
registerLogLevelEnvVars()- Register environment variables to check for log leveldetermineLogLevel()- Resolve log level from CLI â env â root config â default
getLogRecordFactory
getLogRecordFactory() -> Callable
Wrapper for logging.getLogRecordFactory(). Return the factory function used to create LogRecords.
For detailed documentation, see the Python logging.getLogRecordFactory() documentation.
getLogger
getLogger(
name: str | None = None,
*args: Any,
level: str | int | None = None,
minimum: bool | None = None,
extend: bool | None = None,
**kwargs: Any
) -> Logger
Return a logger with the specified name, creating it if necessary.
Changed from stdlib: This function has several improvements over logging.getLogger():
- Auto-inference: When
nameisNone, automatically infers the logger name from the calling moduleâs__package__attribute by examining the call stack, instead of returning the root logger. This makes it convenient to usegetLogger()without explicitly passing a name. - Root logger access: When
nameis an empty string (""), returns the root logger as usual, matching standard library behavior. - Apathetic logger: Returns an
apathetic_logging.Loggerinstance instead of the standardlogging.Logger. - Level setting: Optional
levelparameter to set the loggerâs level when creating it. - Minimum level: Optional
minimumparameter to only set the level if itâs more verbose than the current level. - Compatibility mode: In compatibility mode,
getLogger(None)returns the root logger (stdlib behavior).
For detailed documentation on the base functionality, see the Python logging.getLogger() documentation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
name |
str | None | The name of the logger to get. If None, the logger name will be auto-inferred from the calling moduleâs __package__. If an empty string (""), returns the root logger. |
*args |
Any | Additional positional arguments (for future-proofing) |
level |
str | int | None | Exact log level to set on the logger. Accepts both string names (case-insensitive) and numeric values. If provided, sets the loggerâs level to this value. Defaults to None. |
minimum |
bool | None | If True, only set the level if itâs more verbose (lower numeric value) than the current level. This prevents downgrading from a more verbose level (e.g., TRACE) to a less verbose one (e.g., DEBUG). If None, defaults to False. Only used when level is provided. |
extend |
bool | None | If True (default), extend the logging module. If False, skip extension. |
**kwargs |
Any | Additional keyword arguments (for future-proofing) |
Returns:
Logger: Anapathetic_logging.Loggerinstance
Example:
from apathetic_logging import getLogger
# Auto-infer logger name from calling module
logger = getLogger() # Uses __package__ from caller
# Explicit logger name
logger = getLogger("mymodule")
# Get root logger
root = getLogger("")
# Create logger with level
logger = getLogger("mymodule", level="DEBUG")
# Create logger with minimum level (won't downgrade from TRACE)
logger = getLogger("mymodule", level="DEBUG", minimum=True)
See Also:
getLoggerOfType()- Get a logger of a specific typegetRootLogger()- Return the root logger instanceregisterLogger()- Register a logger name for use bygetLogger()
getLoggerOfType
getLoggerOfType(
name: str | None,
class_type: type[Logger],
skip_frames: int = 1,
*args: Any,
level: str | int | None = None,
minimum: bool | None = None,
extend: bool | None = True,
replace_root: bool | None = None,
**kwargs: Any
) -> Logger
Get a logger of the specified type, creating it if necessary.
This function is similar to getLogger(), but allows you to specify a custom logger class type. This is useful when you have a custom logger subclass and want to ensure you get an instance of that specific type.
Key Features:
- Custom logger type: Returns a logger instance of the specified
class_typeinstead of the defaultapathetic_logging.Logger. - Auto-inference: When
nameisNone, automatically infers the logger name from the calling moduleâs__package__attribute by examining the call stack, instead of returning the root logger. - Root logger access: When
nameis an empty string (""), returns the root logger as usual, matching standard library behavior. - Level setting: Optional
levelparameter to set the loggerâs level when creating it. - Minimum level: Optional
minimumparameter to only set the level if itâs more verbose than the current level. - Type safety: Ensures the logger is of the specified type, replacing it if necessary and porting state (handlers, level, etc.) from the old logger.
Parameters:
| Parameter | Type | Description |
|---|---|---|
name |
str | None | The name of the logger to get. If None, the logger name will be auto-inferred from the calling moduleâs __package__. If an empty string (""), returns the root logger. |
class_type |
type[Logger] | The logger class type to use (e.g., AppLogger, CustomLogger). |
skip_frames |
int | Number of frames to skip when inferring logger name. Prefer using as a keyword argument (e.g., skip_frames=2) for clarity. Defaults to 1. |
*args |
Any | Additional positional arguments (for future-proofing) |
level |
str | int | None | Exact log level to set on the logger. Accepts both string names (case-insensitive) and numeric values. If provided, sets the loggerâs level to this value. Defaults to None. |
minimum |
bool | None | If True, only set the level if itâs more verbose (lower numeric value) than the current level. This prevents downgrading from a more verbose level (e.g., TRACE) to a less verbose one (e.g., DEBUG). If None, defaults to False. Only used when level is provided. |
extend |
bool | None | If True (default), extend the logging module. If False, skip extension. |
replace_root |
bool | None | Whether to replace the root logger if itâs not the correct type. If None (default), uses registry setting or constant default. Only used when extend=True. |
**kwargs |
Any | Additional keyword arguments (for future-proofing) |
Returns:
Logger: A logger instance of the specified type
Example:
from apathetic_logging import getLoggerOfType, Logger
# Get a standard apathetic logger
logger = getLoggerOfType("mymodule", Logger)
# Get a custom logger type (e.g., AppLogger)
from myapp.logs import AppLogger
app_logger = getLoggerOfType("myapp", AppLogger)
# Auto-infer name with custom type
app_logger = getLoggerOfType(None, AppLogger)
# Create logger with level
app_logger = getLoggerOfType("myapp", AppLogger, level="DEBUG")
See Also:
getLogger()- Get a logger (returns defaultapathetic_logging.Loggertype)registerLogger()- Register a logger name for use bygetLogger()
getLoggerClass
getLoggerClass() -> type[logging.Logger]
Wrapper for logging.getLoggerClass(). Return the class to be used when instantiating a logger.
For detailed documentation, see the Python logging.getLoggerClass() documentation.
getRegisteredLoggerName
getRegisteredLoggerName() -> str | None
Get the registered logger name.
Returns the registered logger name, or None if no logger name has been registered. Unlike getDefaultLoggerName(), this does not perform inference - it only returns the explicitly registered value.
Returns:
str | None: Registered logger name, or None if not registered
Note: This is a registry getter function. For other registry getters, see the subsections above.
getRootLogger
getRootLogger() -> Logger | logging.RootLogger
Return the root logger instance.
This is the primary way to access the root logger. Itâs more explicit and discoverable than using logging.getLogger("") or getLogger("").
The root logger may be either:
- An
apathetic_logging.Loggerif it was created afterextendLoggingModule()was called (expected/common case) - A standard
logging.RootLoggerif it was created beforeextendLoggingModule()was called (fallback)
Returns:
Logger | logging.RootLogger: The root logger instance (eitherapathetic_logging.Loggerorlogging.RootLogger)
Example:
from apathetic_logging import getRootLogger
# Get the root logger
root = getRootLogger()
# Configure the root logger
root.setLevel("debug")
root.info("This logs to the root logger")
See Also:
getLogger("")- Alternative way to get the root loggerextendLoggingModule()- Extend the logging module and ensure root logger is apathetic type
getTargetPythonVersion
getTargetPythonVersion() -> tuple[int, int] | None
Get the target Python version.
Returns the registered target Python version, or the minimum supported version if none is registered. This version is used by checkPythonVersionRequirement() to determine if version-gated functions should be available.
Returns:
tuple[int, int] | None: Target Python version as(major, minor)tuple, orNoneif no version is registered andTARGET_PYTHON_VERSIONisNone(checks disabled)
Example:
from apathetic_logging import getTargetPythonVersion, registerTargetPythonVersion
# Get default target version
version = getTargetPythonVersion()
print(version) # (3, 10) or None if checks are disabled
# Register a custom target version
registerTargetPythonVersion((3, 11))
version = getTargetPythonVersion()
print(version) # (3, 11)
See Also:
registerTargetPythonVersion()- Register the target Python version for compatibility checkingcheckPythonVersionRequirement()- Check if a function is available for the target Python version
hasLogger
hasLogger(logger_name: str) -> bool
Check if a logger exists in the logging managerâs registry.
Parameters:
| Parameter | Type | Description |
|---|---|---|
logger_name |
str | The name of the logger to check |
Returns:
bool: True if the logger exists, False otherwise
isRootLoggerInstantiated
isRootLoggerInstantiated() -> bool
Check if the root logger has been instantiated/accessed yet.
The root logger is created lazily by Pythonâs logging module. This function checks if it has been instantiated without creating it as a side effect.
Returns:
bool: True if the root logger has been instantiated (exists in manager registry), False if itâs fresh and ready for configuration with defaults
Use Cases:
This is useful to distinguish between:
- Fresh root logger: Never accessed, ready to be configured with defaults
- Existing root logger: Already created/accessed, should preserve its state
Note:
Calling logging.getLogger("") after this returns False will instantiate the root logger, so timing matters. This check should be done before any code that accesses the root logger.
Example:
if not isRootLoggerInstantiated():
# Root logger is fresh, apply our defaults
root.setLevel(determineLogLevel())
else:
# Root logger already exists, port its state
portLoggerState(old_root, new_root, port_level=True)
removeLogger
removeLogger(logger_name: str) -> None
Remove a logger from the logging managerâs registry.
Parameters:
| Parameter | Type | Description |
|---|---|---|
logger_name |
str | The name of the logger to remove |
safeLog
safeLog(msg: str) -> None
Emergency logger that never fails.
This function bypasses the normal logging system and writes directly to sys.__stderr__. Itâs designed for use in error handlers where the logging system itself might be broken.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
Example:
from apathetic_logging import safeLog
try:
# Some operation
pass
except Exception:
safeLog("Critical error: logging system may be broken")
safeTrace
safeTrace(label: str, *args: Any, icon: str = "đ§Ş") -> None
Debug tracing function for test development. Only active when safe trace is enabled via environment variables.
Safe trace is enabled when any of the following conditions are met:
SAFE_TRACEenvironment variable is set to"1","true", or"yes"(case insensitive)LOG_LEVELenvironment variable (case insensitive) is set to"TRACE"or"TEST"LOG_LEVELnumeric value is less than or equal toTRACE_LEVEL(supports both numeric strings like"5"and standard logging level names like"DEBUG")
Parameters:
| Parameter | Type | Description |
|---|---|---|
label |
str | Trace label |
*args |
Any | Additional arguments to trace |
icon |
str | Icon to use (default: "đ§Ş") |
Example:
from apathetic_logging import safeTrace
import os
# Enable via SAFE_TRACE
os.environ["SAFE_TRACE"] = "1"
safeTrace("debug", "message") # Will output
# Enable via LOG_LEVEL
os.environ["LOG_LEVEL"] = "TRACE"
safeTrace("debug", "message") # Will output
# Or via numeric LOG_LEVEL
os.environ["LOG_LEVEL"] = "5" # TRACE_LEVEL is 5
safeTrace("debug", "message") # Will output
makeSafeTrace
makeSafeTrace(icon: str = "đ§Ş") -> Callable
Create a test trace function with a custom icon.
Parameters:
| Parameter | Type | Description |
|---|---|---|
icon |
str | Icon to use |
Returns:
Callable: Test trace function
makeLogRecord
makeLogRecord(
name: str,
level: int,
fn: str,
lno: int,
msg: str,
args: tuple,
exc_info: Any
) -> logging.LogRecord
Wrapper for logging.makeLogRecord(). Create a LogRecord from the given parameters.
For detailed documentation, see the Python logging.makeLogRecord() documentation.
test
test(msg: str, *args: Any, **kwargs: Any) -> None
Log a message at TEST level.
TEST is the most verbose level and bypasses capture. This function gets an apathetic_logging.Logger instance (ensuring the root logger is an apathetic logger) and calls its test() method.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
Example:
import apathetic_logging
# Log a test message
apathetic_logging.test("Test message: %s", variable)
trace
trace(msg: str, *args: Any, **kwargs: Any) -> None
Log a message with severity TRACE on the root logger.
TRACE is more verbose than DEBUG. This function gets an apathetic_logging.Logger instance (ensuring the root logger is an apathetic logger) and calls its trace() method.
If the logger has no handlers, basicConfig() is automatically called to add a console handler with a pre-defined format.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
import apathetic_logging
# Log a trace message
apathetic_logging.trace("Detailed trace information: %s", variable)
warn
warn(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.warn(). Log a message with severity WARNING.
For detailed documentation, see the Python logging.warn() documentation.
warning
warning(msg: str, *args: Any, **kwargs: Any) -> None
Wrapper for logging.warning(). Log a message with severity WARNING.
For detailed documentation, see the Python logging.warning() documentation.
registerCompatibilityMode
registerCompatibilityMode(*, compat_mode: bool | None) -> None
Register the compatibility mode setting for stdlib drop-in replacement.
This sets the compatibility mode that will be used when creating loggers. If not set, the library defaults to False (improved behavior).
When compat_mode is True, restores stdlib-compatible behavior where possible (e.g., getLogger(None) returns root logger instead of auto-inferring).
Parameters:
| Parameter | Type | Description |
|---|---|---|
compat_mode |
bool | None | Compatibility mode setting (True or False). If None, returns immediately without making any changes. |
Example:
from apathetic_logging import registerCompatibilityMode, getLogger
# Enable compatibility mode (stdlib behavior)
registerCompatibilityMode(compat_mode=True)
# Now getLogger(None) returns root logger (stdlib behavior)
# Disable compatibility mode (improved behavior, default)
registerCompatibilityMode(compat_mode=False)
# Now getLogger(None) auto-infers logger name
See Also:
getCompatibilityMode()- Get the compatibility mode setting
registerDefaultLogLevel
registerDefaultLogLevel(default_level: str | None) -> None
Register the default log level to use when no other source is found.
This sets the default log level that will be used by determineLogLevel() when no other source (CLI args, environment variables, root logger level) provides a log level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
default_level |
str | None | Default log level name (e.g., "info", "warning"). If None, returns immediately without making any changes. |
Example:
from apathetic_logging import registerDefaultLogLevel, getLogger
# Set default log level
registerDefaultLogLevel("warning")
# Now determineLogLevel() will use "warning" as fallback
logger = getLogger("mymodule")
level = logger.determineLogLevel()
print(level) # "WARNING"
See Also:
getDefaultLogLevel()- Get the registered default log leveldetermineLogLevel()- Resolve log level from CLI â env â root config â default
registerLogLevelEnvVars
registerLogLevelEnvVars(env_vars: list[str] | None) -> None
Register environment variable names to check for log level.
The environment variables will be checked in order by determineLogLevel(), and the first non-empty value found will be used.
Parameters:
| Parameter | Type | Description |
|---|---|---|
env_vars |
list[str] | None | List of environment variable names to check (e.g., ["MYAPP_LOG_LEVEL", "LOG_LEVEL"]). If None, returns immediately without making any changes. |
Example:
from apathetic_logging import registerLogLevelEnvVars, getLogger
import os
# Register custom environment variables
registerLogLevelEnvVars(["MYAPP_LOG_LEVEL", "LOG_LEVEL"])
# Set environment variable
os.environ["MYAPP_LOG_LEVEL"] = "debug"
# Now determineLogLevel() will check MYAPP_LOG_LEVEL first, then LOG_LEVEL
logger = getLogger("mymodule")
level = logger.determineLogLevel()
print(level) # "DEBUG" (from MYAPP_LOG_LEVEL)
See Also:
getLogLevelEnvVars()- Get the registered environment variable namesdetermineLogLevel()- Resolve log level from CLI â env â root config â default
registerLogger
registerLogger(
logger_name: str | None = None,
logger_class: type[Logger] | None = None,
*,
target_python_version: tuple[int, int] | None = None,
log_level_env_vars: list[str] | None = None,
default_log_level: str | None = None,
propagate: bool | None = None,
compat_mode: bool | None = None,
replace_root: bool | None = None
) -> None
Register a logger for use by getLogger().
This is the public API for registering a logger. It registers the logger name and extends the logging module with custom levels if needed.
If logger_name is not provided, the top-level package is automatically extracted from the calling moduleâs __package__ attribute.
If logger_class is provided and has an extendLoggingModule() method, it will be called to extend the logging module with custom levels and set the logger class. If logger_class is provided but does not have extendLoggingModule(), logging.setLoggerClass() will be called directly to set the logger class. If logger_class is not provided, nothing is done with the logger class (the default Logger is already extended at import time).
Important: If youâre using a custom logger class that has extendLoggingModule(), do not call logging.setLoggerClass() directly. Instead, pass the class to registerLogger() and let extendLoggingModule() handle setting the logger class. This ensures consistent behavior and avoids class identity issues in stitched mode.
Parameters:
| Parameter | Type | Description |
|---|---|---|
logger_name |
str | None | The name of the logger to retrieve (e.g., "myapp"). If None, extracts the top-level package from __package__. |
logger_class |
type[Logger] | None | Optional logger class to use. If provided and the class has an extendLoggingModule() method, it will be called. If the class doesnât have that method, logging.setLoggerClass() will be called directly. If None, nothing is done (default Logger is already set up at import time). |
target_python_version |
tuple[int, int] | None | Optional target Python version (major, minor) tuple. If provided, sets the target Python version in the registry permanently. Defaults to None (no change). |
log_level_env_vars |
list[str] | None | Optional list of environment variable names to check for log level. If provided, sets the log level environment variables in the registry permanently. Defaults to None (no change). |
default_log_level |
str | None | Optional default log level name. If provided, sets the default log level in the registry permanently. Defaults to None (no change). |
propagate |
bool | None | Optional propagate setting. If provided, sets the propagate value in the registry permanently. Defaults to None (no change). |
compat_mode |
bool | None | Optional compatibility mode setting. If provided, sets the compatibility mode in the registry permanently. When True, restores stdlib-compatible behavior where possible (e.g., getLogger(None) returns root logger). Defaults to None (no change). |
replace_root |
bool | None | Optional setting for whether to replace root logger. If provided, passes this value to extendLoggingModule() when extending the logging module. If None, uses registry setting or constant default. Only used when logger_class has an extendLoggingModule() method. |
Example:
from apathetic_logging import registerLogger, getLogger
# Explicit registration with default Logger (already extended)
registerLogger("myapp")
logger = getLogger() # Uses "myapp" as logger name
# Auto-infer from __package__
registerLogger() # Uses top-level package from __package__
# Register with custom logger class (has extendLoggingModule)
from apathetic_logging import Logger
class AppLogger(Logger):
pass
# Don't call AppLogger.extendLoggingModule() or
# logging.setLoggerClass() directly - registerLogger() handles it
registerLogger("myapp", AppLogger)
# Register with convenience parameters
registerLogger(
"myapp",
AppLogger,
target_python_version=(3, 10),
log_level_env_vars=["MYAPP_LOG_LEVEL", "LOG_LEVEL"],
default_log_level="info",
propagate=False,
compat_mode=False
)
See Also:
getLogger()- Get a logger instance (uses registered name if available)getLoggerOfType()- Get a logger of a specific typegetRegisteredLoggerName()- Get the registered logger name
registerPortHandlers
registerPortHandlers(*, port_handlers: bool | None) -> None
Register whether to port handlers when replacing a logger.
This sets whether logger replacement should port handlers from the old logger to the new logger. If not set, the library defaults to DEFAULT_PORT_HANDLERS from constants.py (True by default - port handlers to preserve existing configuration).
When port_handlers is True, handlers from the old logger are ported to the new logger. When False, the new logger manages its own handlers via manageHandlers().
Parameters:
| Parameter | Type | Description |
|---|---|---|
port_handlers |
bool | None | Whether to port handlers (True or False). If None, the registration is skipped. |
Example:
from apathetic_logging import registerPortHandlers
# Enable handler porting to preserve existing handlers
registerPortHandlers(port_handlers=True)
# Now logger replacement will port handlers
registerPortLevel
registerPortLevel(*, port_level: bool | None) -> None
Register whether to port level when replacing a logger.
This sets whether logger replacement should port the log level from the old logger to the new logger. If not set, the library defaults to DEFAULT_PORT_LEVEL from constants.py (True by default - port level to preserve existing configuration).
When port_level is True, the log level is ported from the old logger. When False, the new logger uses apathetic defaults (determineLogLevel() for root logger, INHERIT_LEVEL for leaf loggers).
Note: User-provided level parameters in getLogger()/getLoggerOfType() take precedence over ported level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
port_level |
bool | None | Whether to port level (True or False). If None, the registration is skipped. |
Example:
from apathetic_logging import registerPortLevel
# Enable level porting to preserve existing level
registerPortLevel(port_level=True)
# Now logger replacement will port level
registerPropagate
registerPropagate(*, propagate: bool | None) -> None
Register the propagate setting for loggers.
This sets the default propagate value that will be used when creating loggers. If not set, the library defaults to DEFAULT_PROPAGATE from constants.py (True by default - propagate to parent loggers).
When propagate is True, loggers propagate messages to parent loggers, allowing centralized control via root logger. When False, messages only go to the loggerâs own handlers.
Parameters:
| Parameter | Type | Description |
|---|---|---|
propagate |
bool | None | Propagate setting (True or False). If None, returns immediately without making any changes. |
Example:
from apathetic_logging import registerPropagate, getLogger
# Enable propagation (default)
registerPropagate(propagate=True)
logger = getLogger("mymodule")
# Messages will propagate to root logger
# Disable propagation (isolated logging)
registerPropagate(propagate=False)
logger = getLogger("mymodule")
# Messages only go to logger's own handlers
See Also:
getDefaultPropagate()- Get the registered propagate settingsetLevelAndPropagate()- Set level and propagate together with smart defaults
registerReplaceRootLogger
registerReplaceRootLogger(*, replace_root: bool | None) -> None
Register whether to replace root logger if itâs not the correct type.
This sets whether extendLoggingModule() should replace the root logger if itâs not an instance of the apathetic logger class. If not set, the library defaults to DEFAULT_REPLACE_ROOT_LOGGER from constants.py (True by default - replace root logger to ensure itâs an apathetic logger).
When replace_root is False, extendLoggingModule() will not replace the root logger, allowing applications to use their own custom logger class for the root logger.
Parameters:
| Parameter | Type | Description |
|---|---|---|
replace_root |
bool | None | Whether to replace root logger (True or False). If None, the registration is skipped. |
Example:
from apathetic_logging import registerReplaceRootLogger
# Disable root logger replacement to use your own logger class
registerReplaceRootLogger(replace_root=False)
# Now extendLoggingModule() won't replace the root logger
registerTargetPythonVersion
registerTargetPythonVersion(version: tuple[int, int] | None) -> None
Register the target Python version for compatibility checking.
This sets the target Python version that will be used to validate function calls. If a function requires a Python version newer than the target version, it will raise a NotImplementedError even if the runtime version is sufficient.
If not set, the library defaults to TARGET_PYTHON_VERSION from constants.py (3, 10). This allows developers to catch version incompatibilities during development even when running on a newer Python version than their target.
Note: The runtime version is still checked as a safety net. If the runtime version is older than required, the function will still raise an error even if the target version is sufficient.
Parameters:
| Parameter | Type | Description |
|---|---|---|
version |
tuple[int, int] | None | Target Python version as (major, minor) tuple (e.g., (3, 10) or (3, 11)). If None, returns immediately without making any changes. |
Example:
from apathetic_logging import registerTargetPythonVersion, getLevelNamesMapping
# Register target Python version
registerTargetPythonVersion((3, 10))
# Now functions requiring 3.11+ will raise even if running on 3.12
try:
mapping = getLevelNamesMapping() # Requires Python 3.11+
except NotImplementedError as e:
print(f"Function not available: {e}")
# Error message suggests raising target version if needed
Why this matters:
- Prevents accidental use of newer Python features during development
- Ensures your code works on your target Python version
- Error messages guide you to either avoid the function or raise your target version
See Also:
getTargetPythonVersion()- Get the registered target Python versioncheckPythonVersionRequirement()- Check if a function is available for the target Python version
setRootLevel
setRootLevel(
level: str | int,
*,
apply_to_children: bool = True,
set_children_to_level: bool = True,
root: logging.Logger | None = None
) -> None
Set the log level on the root logger and optionally on child loggers.
This is the recommended way to set log levels in a CLI application, as it ensures all loggers (including those from libraries) use the same level. When propagation is enabled (default), child loggers inherit from root, so setting root level affects all loggers.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to set (string name or numeric value). Supports standard levels (DEBUG, INFO, etc.) and custom levels (TRACE, DETAIL, BRIEF, SILENT). |
apply_to_children |
bool | If True (default), also sets level on any child loggers with explicit levels. Useful for loggers created before root level was set. |
set_children_to_level |
bool | If True (default), sets child loggers to same level as root. If False, sets child loggers to NOTSET to inherit from root. |
root |
logging.Logger | None | Logger to use as root. If None, uses actual root logger. Can pass any logger to work on its children. |
Example:
from apathetic_logging import setRootLevel
# Set root level - all loggers inherit
setRootLevel("debug")
# Set root level and reset children to NOTSET to inherit
setRootLevel("info", set_children_to_level=False)
See Also:
getRootLevel()- Get current root levelgetRootLevelName()- Get current root level namesetRootLevelMinimum()- Only set if more verboseuseRootLevel()- Temporarily change root level
getRootLevel
getRootLevel() -> int
Return the current explicit log level set on the root logger.
Returns the level explicitly set on the root logger, not the effective level (which would be the same for root since it has no parent).
Returns:
int: Integer log level value (e.g., 10 for DEBUG, 20 for INFO)
Example:
from apathetic_logging import setRootLevel, getRootLevel
setRootLevel("DEBUG")
print(getRootLevel()) # 10
See Also:
getRootLevelName()- Get level namegetEffectiveRootLevel()- Get effective levelsetRootLevel()- Set root level
getRootLevelName
getRootLevelName() -> str
Return the name of the current explicit log level set on the root logger.
Returns the name of the level explicitly set on the root logger (e.g., âDEBUGâ, âINFOâ, âNOTSETâ).
Returns:
str: Level name as uppercase string
Example:
from apathetic_logging import setRootLevel, getRootLevelName
setRootLevel("DEBUG")
print(getRootLevelName()) # "DEBUG"
See Also:
getRootLevel()- Get level valuegetEffectiveRootLevelName()- Get effective level name
getEffectiveRootLevel
getEffectiveRootLevel() -> int
Return the effective log level on the root logger.
For the root logger, this is the same as the explicit level since the root logger has no parent to inherit from. This method exists for API completeness and symmetry with Logger.getEffectiveLevel().
Returns:
int: Integer log level value
Example:
from apathetic_logging import getEffectiveRootLevel
print(getEffectiveRootLevel()) # Effective level value
See Also:
getRootLevel()- Get explicit levelgetEffectiveRootLevelName()- Get effective level name
getEffectiveRootLevelName
getEffectiveRootLevelName() -> str
Return the name of the effective log level on the root logger.
For the root logger, this is the same as the explicit level name. This method exists for API completeness and symmetry with Logger.getEffectiveLevelName().
Returns:
str: Level name as uppercase string
Example:
from apathetic_logging import getEffectiveRootLevelName
print(getEffectiveRootLevelName()) # "INFO"
See Also:
getRootLevelName()- Get explicit level namegetEffectiveRootLevel()- Get effective level value
setRootLevelMinimum
setRootLevelMinimum(level: str | int) -> None
Set root logger level only if more verbose than current level.
This is a convenience method that prevents downgrades from more verbose to less verbose levels. Useful for ensuring you donât accidentally reduce logging verbosity.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to potentially set |
Example:
from apathetic_logging import setRootLevelMinimum, setRootLevel
setRootLevel("INFO")
setRootLevelMinimum("DEBUG") # Sets to DEBUG (more verbose)
setRootLevelMinimum("WARNING") # Does nothing (already DEBUG)
See Also:
setRootLevel()- Set level unconditionallyuseRootLevelMinimum()- Temporary version
setRootLevelInherit
setRootLevelInherit() -> None
Set root logger to inherit level (NOTSET).
For the root logger, this sets level to NOTSET (0). Since the root logger has no parent, this effectively means the root will not filter by level - all messages are accepted.
Useful when you want child loggers to have explicit levels but the root logger should accept everything and let children decide what to log.
Example:
from apathetic_logging import setRootLevelInherit, getRootLevel
setRootLevelInherit()
print(getRootLevel()) # 0 (NOTSET/INHERIT_LEVEL)
See Also:
setRootLevel()- Set specific leveluseRootLevel()- Temporary change
useRootLevel
useRootLevel(level: str | int, *, minimum: bool = False) -> ContextManager
Context manager to temporarily set root logger level.
Sets the root logger to a specific level for the duration of the with block, then restores the previous level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Temporary log level to use |
minimum |
bool | If True, only applies level if more verbose than current. Defaults to False. |
Returns:
- Context manager that restores the previous level on exit
Example:
from apathetic_logging import setRootLevel, useRootLevel
setRootLevel("INFO")
with useRootLevel("DEBUG"):
# Root is at DEBUG level here
pass
# Back to INFO level
See Also:
setRootLevel()- Permanently set leveluseRootLevelMinimum()- Convenience for minimum=True
useRootLevelMinimum
useRootLevelMinimum(level: str | int) -> ContextManager
Context manager to temporarily set root level only if more verbose.
Convenience context manager equivalent to useRootLevel(level, minimum=True). Only applies the level if itâs more verbose than the current effective level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Temporary log level to potentially use |
Returns:
- Context manager that restores the previous level on exit
Example:
from apathetic_logging import setRootLevel, useRootLevelMinimum
setRootLevel("DEBUG")
with useRootLevelMinimum("TRACE"):
# Root upgraded to TRACE (more verbose)
pass
setRootLevel("TRACE")
with useRootLevelMinimum("DEBUG"):
# Stays at TRACE (already more verbose)
pass
See Also:
useRootLevel()- For unconditional temporary changesetRootLevelMinimum()- Permanent version
isRootEnabledFor
isRootEnabledFor(level: str | int) -> bool
Check if root logger would process messages at the given level.
Returns True if the root loggerâs effective level would allow messages at the given level to be processed. Useful for conditional expensive operations that should only run if logging is enabled.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to check (string name or numeric value) |
Returns:
bool: True if root logger would process messages at this level
Example:
from apathetic_logging import setRootLevel, isRootEnabledFor
setRootLevel("INFO")
if isRootEnabledFor("DEBUG"):
# Expensive debug info generation
pass
See Also:
getRootLevel()- Get current root level
logRootDynamic
logRootDynamic(level: str | int, msg: str, *args: Any, **kwargs: Any) -> None
Log a message to root logger with dynamically provided level.
Allows logging with a level that is determined at runtime rather than compile time. Useful when the logging level comes from user input, configuration, or other dynamic sources.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level as string name or integer value |
msg |
str | The log message |
*args |
Any | Arguments for message formatting |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
Example:
from apathetic_logging import logRootDynamic
level = "DEBUG" # From config
logRootDynamic(level, "Message at %s level", level)
logRootDynamic(10, "Direct integer level")
See Also:
getRootLogger()- Get root logger for standard logging methods
setLogRecordFactory
setLogRecordFactory(factory: Callable) -> None
Wrapper for logging.setLogRecordFactory(). Set the factory function used to create LogRecords.
For detailed documentation, see the Python logging.setLogRecordFactory() documentation.
setLoggerClass
setLoggerClass(klass: type[logging.Logger]) -> None
Wrapper for logging.setLoggerClass(). Set the class to be used when instantiating a logger.
For detailed documentation, see the Python logging.setLoggerClass() documentation.
shutdown
shutdown() -> None
Wrapper for logging.shutdown(). Perform an orderly shutdown of the logging system.
For detailed documentation, see the Python logging.shutdown() documentation.
apathetic_logging.Logger Function Reference
Constructor
Logger(
name: str,
level: int = logging.NOTSET,
*,
enable_color: bool | None = None
)
Logger class for all Apathetic tools. Extends Pythonâs standard logging.Logger.
Parameters:
| Parameter | Type | Description |
|---|---|---|
name |
str | Logger name |
level |
int | Initial log level (defaults to INHERIT_LEVEL (i.e. logging.NOTSET)) |
enable_color |
bool | None | Whether to enable colorized output. If None, auto-detects based on TTY and environment variables. |
_log
_log(level: int, msg: str, args: tuple[Any, ...], **kwargs: Any) -> None
Log a message with the specified level.
Changed from stdlib: Automatically ensures handlers are attached via ensureHandlers().
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | The numeric logging level |
msg |
str | The message format string |
args |
tuple[Any, âŚ] | Arguments for the message format string |
**kwargs |
Any | Additional keyword arguments passed to the base implementation |
addLevelName
addLevelName(level: int, level_name: str) -> None
Associate a level name with a numeric level. (staticmethod)
Changed from stdlib: Validates that level value is positive (> 0) to prevent INHERIT_LEVEL (i.e. NOTSET)
inheritance issues. Sets logging.<LEVEL_NAME> attribute for convenience.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | The numeric level value (must be > 0 for custom levels) |
level_name |
str | The name to associate with this level |
Raises:
ValueError: If level <= 0 (which would cause INHERIT_LEVEL (i.e. NOTSET) inheritance)ValueError: Iflogging.<LEVEL_NAME>already exists with an invalid value
brief
brief(msg: str, *args: Any, **kwargs: Any) -> None
Log a message at BRIEF level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
colorize
colorize(text: str, color: str, *, enable_color: bool | None = None) -> str
Apply ANSI color codes to text.
Parameters:
| Parameter | Type | Description |
|---|---|---|
text |
str | Text to colorize |
color |
str | ANSI color code (e.g., ANSIColors.CYAN, ANSIColors.RED) |
enable_color |
bool | None | Override color enablement. If None, uses instance setting. |
Returns:
str: Colorized text (or original text if colors disabled)
criticalIfNotDebug
criticalIfNotDebug(msg: str, *args: Any, **kwargs: Any) -> None
Log a critical error with full traceback only if debug/trace is enabled.
Similar to errorIfNotDebug() but logs at CRITICAL level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Error message |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
detail
detail(msg: str, *args: Any, **kwargs: Any) -> None
Log a message at DETAIL level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
determineColorEnabled
determineColorEnabled() -> bool
Return True if colored output should be enabled. (classmethod)
Checks:
NO_COLORenvironment variable (disables colors)FORCE_COLORenvironment variable (enables colors)- TTY detection (enables colors if stdout is a TTY)
Returns:
bool: True if colors should be enabled
determineLogLevel
determineLogLevel(
*,
args: argparse.Namespace | None = None,
root_log_level: str | None = None
) -> str
Resolve log level from CLI â env â root config â default.
Parameters:
| Parameter | Type | Description |
|---|---|---|
args |
argparse.Namespace | None | Parsed command-line arguments (checks for args.log_level) |
root_log_level |
str | None | Root logger level to use as fallback |
Returns:
str: Resolved log level name (uppercase)
Example:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--log-level", default="info")
args = parser.parse_args()
level = logger.determineLogLevel(args=args)
logger.setLevel(level)
effectiveLevel
effectiveLevel: int
Return the effective level (whatâs actually used) (read-only property).
This property returns the effective logging level for this logger, considering
inheritance from parent loggers. This is the preferred way to get the effective
level. Also available via getEffectiveLevel() for stdlib compatibility.
Example:
parent = getLogger("parent")
parent.setLevel("info")
child = getLogger("parent.child")
print(child.level) # 0 (INHERIT_LEVEL, i.e. NOTSET - explicit)
print(child.effectiveLevel) # 20 (INFO - effective, from parent)
effectiveLevelName
effectiveLevelName: str
Return the effective level name (whatâs actually used) (read-only property).
This property returns the name of the effective logging level for this logger,
considering inheritance from parent loggers. This is the preferred way to get
the effective level name. Also available via getEffectiveLevelName() for
consistency.
Example:
parent = getLogger("parent")
parent.setLevel("info")
child = getLogger("parent.child")
print(child.levelName) # "NOTSET" (explicit - INHERIT_LEVEL, i.e. NOTSET)
print(child.effectiveLevelName) # "INFO" (effective, from parent)
errorIfNotDebug
errorIfNotDebug(msg: str, *args: Any, **kwargs: Any) -> None
Log an error with full traceback only if debug/trace is enabled.
If debug mode is enabled, shows full exception traceback. Otherwise, shows only the error message.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Error message |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
Example:
try:
risky_operation()
except Exception:
logger.errorIfNotDebug("Operation failed")
extendLoggingModule
extendLoggingModule(
*,
replace_root: bool | None = None,
port_handlers: bool | None = None,
port_level: bool | None = None
) -> bool
Extend Pythonâs logging module with TRACE and SILENT levels. (classmethod)
This method:
- Sets
apathetic_logging.Loggeras the default logger class - Adds
TRACEandSILENTlevel names - Adds
logging.TRACEandlogging.SILENTconstants - Optionally replaces the root logger if itâs not the correct type
Parameters:
| Parameter | Type | Description |
|---|---|---|
replace_root |
bool | None | Whether to replace the root logger if itâs not the correct type. If None (default), checks the registry setting (set via registerReplaceRootLogger()). If not set in registry, defaults to True for backward compatibility. When False, the root logger will not be replaced, allowing applications to use their own custom logger class for the root logger. |
port_handlers |
bool | None | Whether to port handlers from the old root logger to the new logger. If None (default), checks the registry setting (set via registerPortHandlers()). If not set in registry, defaults to True. When True, handlers from the old logger are ported. When False, the new logger manages its own handlers via manageHandlers(). |
port_level |
bool | None | Whether to port level from the old root logger to the new logger. If None (default), checks the registry setting (set via registerPortLevel()). If not set in registry, defaults to True. When True, the old level is preserved. When False, the new root logger uses determineLogLevel() to get a sensible default. |
Returns:
bool: True if the extension ran, False if it was already extended
Note: When the root logger is replaced, its state is preserved by default (handlers and level are ported, propagate and disabled are always ported). Child loggers are automatically reconnected to the new root logger instance.
getChildren
getChildren() -> set[logging.Logger]
Requires Python 3.12+
Return a set of loggers that are immediate children of this logger.
This method returns only the direct children of the logger (loggers whose names are one level deeper in the hierarchy). For example, if you have loggers named foo, foo.bar, and foo.bar.baz, calling getLogger("foo").getChildren() will return a set containing only the foo.bar logger, not foo.bar.baz.
Returns:
set[logging.Logger]: A set of Logger instances that are immediate children of this logger
Example:
from apathetic_logging import getLogger
root = getLogger("")
foo = getLogger("foo")
bar = getLogger("foo.bar")
baz = getLogger("foo.bar.baz")
# Get immediate children of root logger
children = root.getChildren() # {foo logger}
# Get immediate children of foo logger
children = foo.getChildren() # {bar logger}
# Get immediate children of bar logger
children = bar.getChildren() # {baz logger}
For detailed documentation, see the Python logging.Logger.getChildren() documentation.
getEffectiveLevelName
getEffectiveLevelName() -> str
Return the effective level name (whatâs actually used).
This method returns the name of the effective logging level for this logger,
considering inheritance from parent loggers. Prefer the effectiveLevelName property
for convenience, or use this method for consistency with getEffectiveLevel().
Returns:
str: The effective level name for this logger
Example:
parent = getLogger("parent")
parent.setLevel("info")
child = getLogger("parent.child")
print(child.getEffectiveLevelName()) # "INFO" (from parent)
getLevel
getLevel() -> int
Return the explicit level set on this logger.
This method returns the level explicitly set on this logger (same as level
property). For the effective level, use getEffectiveLevel() or the
effectiveLevel property.
Returns:
int: The explicit level value set on this logger
Example:
logger.setLevel("debug")
print(logger.getLevel()) # 10
getLevelName
getLevelName() -> str
Return the explicit level name set on this logger.
This method returns the name of the level explicitly set on this logger (same
as levelName property). For the effective level name, use
getEffectiveLevelName() or the effectiveLevelName property.
Returns:
str: The explicit level name set on this logger
Example:
logger.setLevel("debug")
print(logger.getLevelName()) # "DEBUG"
ensureHandlers
ensureHandlers() -> None
Ensure handlers are attached to this logger.
DualStreamHandler is what will ensure logs go to the write channel. Rebuilds handlers if theyâre missing or if stdout/stderr have changed.
Note: This method is automatically called by _log() when logging. You typically donât need to call it directly.
levelName
levelName: str
Return the explicit level name set on this logger (read-only property).
This property returns the name of the level explicitly set on this logger.
For the effective level name (whatâs actually used, considering inheritance),
use effectiveLevelName instead.
Example:
logger.setLevel("debug")
print(logger.levelName) # "DEBUG"
logDynamic
logDynamic(level: str | int, msg: str, *args: Any, **kwargs: Any) -> None
Log a message at a dynamically specified level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level name or numeric value |
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
Example:
logger.logDynamic("warning", "This is a warning")
logger.logDynamic(logging.ERROR, "This is an error")
setLevel
setLevel(level: int | str, *, minimum: bool | None = False, allow_inherit: bool = False) -> None
Set the logging level. Accepts both string names (case-insensitive) and numeric values.
Changed from stdlib: Accepts string level names and has minimum and allow_inherit parameters. In improved mode (default), validates that levels are > 0 to prevent accidental INHERIT_LEVEL (i.e. NOTSET) inheritance. In compatibility mode, accepts any level value (including 0 and negative) matching stdlib behavior.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | str | Log level name or numeric value |
minimum |
bool | None | If True, only set the level if itâs more verbose (lower numeric value) than the current level. Defaults to False. |
allow_inherit |
bool | If True, allows setting level to 0 (INHERIT_LEVEL, i.e. NOTSET) in improved mode. In compatibility mode, this parameter is ignored and 0 is always accepted. Defaults to False. |
Behavior:
- Improved mode (default): Rejects level 0 (INHERIT_LEVEL, i.e. NOTSET) unless
allow_inherit=Trueis explicitly provided. This prevents accidental INHERIT_LEVEL (i.e. NOTSET) inheritance from custom levels that accidentally evaluate to 0. - Compatibility mode: Accepts any level value (including 0 and negative) matching stdlib behavior. The
allow_inheritparameter is ignored in this mode.
Example:
logger.setLevel("debug")
logger.setLevel(logging.DEBUG)
# Set to INHERIT_LEVEL (i.e. NOTSET) (inherits from parent) - requires explicit allow_inherit=True
logger.setLevel(0, allow_inherit=True)
# In compatibility mode, INHERIT_LEVEL (i.e. NOTSET) is accepted without allow_inherit
from apathetic_logging import registerCompatibilityMode
registerCompatibilityMode(compat_mode=True)
logger.setLevel(0) # Works in compat mode
setLevelAndPropagate
setLevelAndPropagate(
level: int | str,
*,
minimum: bool | None = False,
allow_inherit: bool = False,
manage_handlers: bool | None = None
) -> None
Set the logging level and propagate setting together in a smart way.
This convenience method combines setLevel() and setPropagate() with intelligent defaults:
- If level is
INHERIT_LEVEL(NOTSET): setspropagate=True - If level is a specific level: sets
propagate=False - On root logger: only sets level (propagate is unchanged)
This matches common use cases: when inheriting level, you typically want to propagate to parent handlers. When setting an explicit level, you typically want isolated logging with your own handler.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | str | Log level name or numeric value. Use INHERIT_LEVEL (0) or âNOTSETâ to inherit. |
minimum |
bool | None | If True, only set the level if itâs more verbose (lower numeric value) than the current level. Defaults to False. |
allow_inherit |
bool | If True, allows setting level to 0 (INHERIT_LEVEL, i.e. NOTSET) in improved mode. Defaults to False. |
manage_handlers |
bool | None | If True, automatically manage apathetic handlers based on propagate setting. If None, uses DEFAULT_MANAGE_HANDLERS from constants. If False, only sets propagate without managing handlers. |
Example:
logger = getLogger("mymodule")
# Set to inherit level and propagate to root
from apathetic_logging import INHERIT_LEVEL
logger.setLevelAndPropagate(INHERIT_LEVEL, allow_inherit=True)
# Set explicit level and disable propagation (isolated logging)
logger.setLevelAndPropagate("debug")
setLevelInherit
setLevelInherit() -> None
Set the logger to inherit its level from the parent logger.
This convenience method is equivalent to calling setLevel(NOTSET, allow_inherit=True). It explicitly sets the logger to INHERIT_LEVEL (i.e. NOTSET) so it inherits its effective level from the root logger or parent logger.
Example:
logger.setLevel("DEBUG")
# Set to inherit from root logger
logger.setLevelInherit()
assert logger.levelName == "NOTSET"
assert logger.effectiveLevel == root.level # Inherits from root
setLevelMinimum
setLevelMinimum(level: int | str) -> None
Set the logging level only if itâs more verbose than the current level.
This convenience method is equivalent to calling setLevel(level, minimum=True). It prevents downgrading from a more verbose level (e.g., TRACE) to a less verbose one (e.g., DEBUG).
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | str | Log level name or numeric value. Only set if itâs more verbose (lower numeric value) than the current effective level. |
Example:
logger.setLevel("TRACE")
# This won't downgrade from TRACE to DEBUG
logger.setLevelMinimum("DEBUG")
assert logger.levelName == "TRACE" # Still TRACE
# This will upgrade from INFO to DEBUG
logger.setLevel("INFO")
logger.setLevelMinimum("DEBUG")
assert logger.levelName == "DEBUG" # Upgraded to DEBUG
test
test(msg: str, *args: Any, **kwargs: Any) -> None
Log a message at TEST level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments |
trace
trace(msg: str, *args: Any, **kwargs: Any) -> None
Log a message at TRACE level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
msg |
str | Message to log |
*args |
Any | Format arguments |
**kwargs |
Any | Additional keyword arguments (e.g., exc_info, stacklevel) |
useLevel
useLevel(level: str | int, *, minimum: bool = False) -> ContextManager
Context manager to temporarily change log level.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to use |
minimum |
bool | If True, only set the level if itâs more verbose (lower numeric value) than the current level. Prevents downgrading from a more verbose level. |
Returns:
- Context manager that restores the previous level on exit
Example:
with logger.useLevel("debug"):
logger.debug("This will be shown")
# Level is restored after the context
useLevelAndPropagate
useLevelAndPropagate(
level: str | int,
*,
minimum: bool = False,
manage_handlers: bool | None = None
) -> ContextManager
Context manager to temporarily set level and propagate together.
This convenience context manager combines useLevel() and usePropagate() with intelligent defaults:
- If level is
INHERIT_LEVEL(NOTSET): setspropagate=True - If level is a specific level: sets
propagate=False - On root logger: only sets level (propagate is unchanged)
Both settings are restored when the context exits.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to use (string name or numeric value). Use INHERIT_LEVEL (0) or âNOTSETâ to inherit. |
minimum |
bool | If True, only set the level if itâs more verbose (lower numeric value) than the current effective level. Prevents downgrading from a more verbose level. Defaults to False. |
manage_handlers |
bool | None | If True, automatically manage apathetic handlers based on propagate setting. If None, uses DEFAULT_MANAGE_HANDLERS from constants. If False, only sets propagate without managing handlers. |
Returns:
- Context manager that restores both the previous level and propagate setting on exit
Example:
logger = getLogger("mymodule")
# Temporarily set to inherit level and propagate to root
with logger.useLevelAndPropagate(INHERIT_LEVEL, allow_inherit=True):
logger.info("This will propagate to root")
# Temporarily set explicit level and disable propagation
with logger.useLevelAndPropagate("debug"):
logger.debug("This only goes to logger's handlers")
# Both settings are restored after the context
useLevelMinimum
useLevelMinimum(level: str | int) -> ContextManager
Context manager to temporarily change log level, only if itâs more verbose than the current level.
This convenience method is equivalent to calling useLevel(level, minimum=True). It prevents downgrading from a more verbose level (e.g., TRACE) to a less verbose one (e.g., DEBUG).
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
str | int | Log level to use. Only applied if itâs more verbose than the current effective level. |
Returns:
- Context manager that restores the previous level on exit
Example:
logger.setLevel("TRACE")
# This won't downgrade from TRACE to DEBUG
with logger.useLevelMinimum("DEBUG"):
assert logger.levelName == "TRACE" # Still TRACE
# This will upgrade from INFO to DEBUG
logger.setLevel("INFO")
with logger.useLevelMinimum("DEBUG"):
assert logger.levelName == "DEBUG" # Upgraded to DEBUG
usePropagate
usePropagate(propagate: bool, *, manage_handlers: bool | None = None) -> ContextManager
Context manager to temporarily change propagate setting.
Parameters:
| Parameter | Type | Description |
|---|---|---|
propagate |
bool | If True, messages propagate to parent loggers. If False, messages only go to this loggerâs handlers. |
manage_handlers |
bool | None | If True, automatically manage apathetic handlers based on propagate setting. If None, uses DEFAULT_MANAGE_HANDLERS from constants. If False, only sets propagate without managing handlers. In compat_mode, this may default to False. |
Returns:
- Context manager that restores the previous propagate setting on exit
Example:
# Temporarily disable propagation to capture logs locally
with logger.usePropagate(False):
logger.info("This message only goes to logger's handlers")
# Do something that should not propagate to root
# Propagate setting is restored after the context
validateLevel
validateLevel(level: int, *, level_name: str | None = None, allow_inherit: bool = False) -> None
Validate that a level value is positive (> 0). (staticmethod)
Custom levels with values <= 0 will inherit from the root logger, causing INHERIT_LEVEL (i.e. NOTSET) inheritance issues. In compatibility mode, validation is skipped.
Parameters:
| Parameter | Type | Description |
|---|---|---|
level |
int | The numeric level value to validate |
level_name |
str | None | Optional name for the level (for error messages). If None, will attempt to get from getLevelName() |
allow_inherit |
bool | If True, allows level 0 (INHERIT_LEVEL, i.e. NOTSET). Defaults to False. |
Raises:
ValueError: If level <= 0 (or level == 0 withoutallow_inherit=True)
Example:
Logger.validateLevel(5, level_name="TRACE")
Logger.validateLevel(0, level_name="TEST")
# ValueError: setLevel(0) sets the logger to INHERIT_LEVEL (i.e. NOTSET)...
Logger.validateLevel(0, level_name="TEST", allow_inherit=True)
# Passes validation
Note: This method is automatically called by setLevel() and addLevelName(). You typically donât need to call it directly unless youâre implementing custom level validation logic.