Log and progress bar manager for console, notebooks, web applications with unified APIs and nested progress tracking.
—
Core logging functionality that provides state management, message logging, and iteration tracking capabilities. The ProgressLogger class serves as the foundation for all other proglog functionality and can be used standalone for simple logging scenarios without progress bars.
Create a new progress logger with optional initial state.
class ProgressLogger:
def __init__(self, init_state=None):
"""
Initialize a new progress logger.
Parameters:
- init_state (dict, optional): Dictionary representing the initial state
"""Usage Example:
from proglog import ProgressLogger
# Basic logger
logger = ProgressLogger()
# Logger with initial state
logger = ProgressLogger(init_state={"task": "processing", "stage": 1})Add messages to the logger's log with automatic indentation support for hierarchical logging.
def log(self, message):
"""
Add a message to the logs with current indentation.
Parameters:
- message (str): Message to log
"""Usage Example:
logger = ProgressLogger()
logger.log("Starting process")
logger.log_indent = 2 # Increase indentation
logger.log("Processing files")
logger.log("Found 10 files")
logger.log_indent = 0 # Reset indentation
logger.log("Process complete")Retrieve or save logged messages to a file.
def dump_logs(self, filepath=None):
"""
Write logs to file or return as string.
Parameters:
- filepath (str, optional): Path to write logs to. If None, returns logs as string
Returns:
str: Log messages as string (only when filepath is None)
"""Usage Example:
logger = ProgressLogger()
logger.log("Task started")
logger.log("Task completed")
# Get logs as string
log_content = logger.dump_logs()
print(log_content)
# Save logs to file
logger.dump_logs("process.log")Update logger state and trigger custom callbacks.
def __call__(self, **kw):
"""
Update the logger state and trigger callback.
Parameters:
- **kw: Arbitrary keyword arguments to update state
"""
def callback(self, **kw):
"""
Execute custom action after state update.
This default implementation does nothing. Override in subclasses
for custom behavior.
Parameters:
- **kw: State elements that were updated
"""Usage Example:
class CustomLogger(ProgressLogger):
def callback(self, **kw):
if "progress" in kw:
print(f"Progress updated: {kw['progress']}%")
logger = CustomLogger()
logger(progress=25) # Prints: Progress updated: 25%
logger(progress=50, task="processing") # Updates multiple state valuesStore large or non-serializable objects with dedicated callbacks.
def store(self, **kw):
"""
Store objects in the logger and trigger store_callback.
Unlike __call__(), this method is intended for large objects
that may not be serializable and are used for operations like
drawing plots on the fly.
Parameters:
- **kw: Objects to store
"""
def store_callback(self, **kw):
"""
Execute custom action after store update.
This default implementation does nothing. Override in subclasses
for custom behavior.
Parameters:
- **kw: Store elements that were updated
"""Usage Example:
import matplotlib.pyplot as plt
class PlotLogger(ProgressLogger):
def store_callback(self, **kw):
if "plot" in kw:
kw["plot"].savefig(f"plot_{len(self.stored)}.png")
logger = PlotLogger()
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [1, 4, 2])
logger.store(plot=fig) # Saves plot automaticallyIterate through data while automatically updating logger state.
def iter(self, **kw):
"""
Iterate through a list while updating the state.
Parameters:
- **kw: Single key-value pair where key is state field name
and value is iterable to process
Yields:
Items from the iterable while updating logger state
"""Usage Example:
logger = ProgressLogger()
# Iterate through usernames, updating state
for username in logger.iter(user=["tom", "tim", "lea"]):
print(f"Processing user: {username}")
print(f"Current state: {logger.state}")
# State['user'] is automatically updated at each iteration
# Iterate through multiple data types
for item in logger.iter(data_file=["file1.txt", "file2.txt", "file3.txt"]):
print(f"Processing {item}")# Instance attributes
state: dict # Current logger state
stored: dict # Stored objects (large/non-serializable)
logs: list # List of log messages
log_indent: int # Current indentation level for logsDirect Access Example:
logger = ProgressLogger()
logger(task="processing", progress=0)
# Direct state access
print(logger.state) # {'task': 'processing', 'progress': 0}
# Update state directly
logger.state["progress"] = 50
logger.callback(progress=50) # Manually trigger callbackInstall with Tessl CLI
npx tessl i tessl/pypi-proglog