Pre-commit hook to automatically detect and convert f-strings in Python code to printf-style logging calls, following W1203 Pylint rule:
To use it with pre-commit, add the following lines to your .pre-commit-config.yaml
:
- repo: https://github.com/dmar1n/lazy-log-formatter
rev: 0.6.2
hooks:
- id: lazy-log-formatter
args: ['--fix']
--fix
: Automatically fix f-strings used in log calls to lazy log calls.DIR [DIR ...]
: One or more directories to search for Python files. If not specified, defaults to the current directory.
Check all Python files in the current directory and subdirectories:
python -m src.cli
Check all Python files in two directories:
python -m src.cli src/ tests/
Fix issues in all Python files in a directory:
python -m src.cli mydir --fix
If the --fix
option is used, the hook will convert f-strings in log calls to lazy log calls, as follows:
# Before
logger.info(f'Hello {name}')
# After
logger.info('Hello %s', name)
# Before
logger.info(f'Hello {name} {surname}')
# After
logger.info('Hello %s %s', name, surname)
import logging
from datetime import datetime
def log_and_return_datetime():
now = datetime.now()
logging.info(f"Current datetime: {now}")
return now
class DateTimeLogger:
def __init__(self):
self._logger = logging.getLogger(self.__class__.__name__)
def log_datetime(self):
now = datetime.now()
self._logger.info(f"Current datetime: {now}")
return now
python src\cli.py tests\data
The output will be:
F-string in logging call at ...\tests\data\test.py:8: f'Current datetime: {now}'
F-string in logging call at ...\tests\data\test.py:18: f'Current datetime: {now}'
F-strings found and fixed in '...\tests\data\test.py'.
After running the formatter, the code will be transformed to:
import logging
from datetime import datetime
def log_and_return_datetime():
now = datetime.now()
logging.info("Current datetime: %s", now)
return now
class DateTimeLogger:
def __init__(self):
self._logger = logging.getLogger(self.__class__.__name__)
def log_datetime(self):
now = datetime.now()
self._logger.info("Current datetime: %s", now)
return now
Only works with the native Python logging
module. Other libraries, such as loguru
, do not support lazy calls.
For loguru
, see Lazy evaluation of expensive functions:
logger.opt(lazy=True).debug("If sink level <= DEBUG: {x}", x=lambda: expensive_function(2**64))