Config Utilities is a Python project that provides tools for managing application configurations. It simplifies loading, validating, and setting default values for configuration files, and includes support for logging configurations and file handling. The project is under development.
MIT License
The config_utilities
project provides utilities for managing configurations and logging in Python applications. It simplifies setting up a config.ini
file, configuring logging, and optionally logging function calls with detailed information about arguments and return values.
This manual guides you through installation, setting up configurations, enabling logging, and customizing function call logging.
To install the project directly from the GitHub repository, run:
pip install git+https://github.com/audkus/config_utilities.git
Heres a simple example of how to use the config_utilities
in a Python application. This example demonstrates basic setup, configuring logging, and logging function calls.
app.py
):# app.py
from logging_util import setup_logging, log_function_call
# Initialize logging for the application
setup_logging('app')
@log_function_call
def add(a, b):
return a + b
@log_function_call
def subtract(a, b):
return a - b
def main():
result_add = add(5, 3)
result_subtract = subtract(10, 7)
print(f"Addition Result: {result_add}")
print(f"Subtraction Result: {result_subtract}")
if __name__ == "__main__":
main()
config.ini
file (explained below). If the configuration file does not exist, it will be created automatically with default settings.Whether you install the module from GitHub or PyPI, the import statements will be the same:
from logging_util import setup_logging, log_function_call
These imports will work regardless of where the package is installed (GitHub, PyPI, or locally).
The config_manager
module provides centralized management of your application's configuration files, ensuring consistent behavior across different parts of the project.
Key features include:
config.ini
, .git
, setup.py
) to determine the root directory of your project.config.ini
file.from config_manager import load_and_validate_config
config = load_and_validate_config(enable_logging=True)
log_dir = config.get('Logging', 'log_dir')
global_log_level = config.get('log_level', 'global_log_level')
This ensures that your application is always running with the correct configuration settings, even if the configuration file needs to be created from scratch.
To demonstrate the functionality, you can use the main
function in config_manager.py
:
if __name__ == "__main__":
config, config_path = load_and_validate_config(enable_logging=True)
log_dir = config.get('Logging', 'log_dir', fallback='logs')
global_log_level = config.get('log_level', 'global_log_level', fallback='INFO')
print(f"Log directory: {log_dir}")
print(f"Effective log level: {global_log_level}")
The save_config
function allows you to save any changes made to the configuration back to the configuration file. This is useful if you modify any values during runtime and want to persist them to the config.ini
.
Heres an example of how to use the save_config
function:
from config_manager import load_and_validate_config, save_config
# Load the existing configuration
config, config_path = load_and_validate_config(enable_logging=True)
# Modify the configuration as needed
config.set('Logging', 'log_dir', '/new/log/directory')
# Save the updated configuration
save_config(config, config_path)
print(f"Configuration saved to {config_path}")
In this example, the log_dir
setting in the Logging
section is updated and then saved back to the configuration file.
def save_config(config: configparser.ConfigParser, config_path: str) -> None:
"""
Save the configuration to the specified file path.
Args:
config (configparser.ConfigParser): The configuration object to save.
config_path (str): The path to the configuration file.
Raises:
IOError: If the configuration file cannot be written to.
"""
Use save_config
whenever you need to persist changes made to the configuration object during runtime. Ensure that the config_path
is correct to avoid overwriting the wrong configuration file.
config.ini
)By default, the application looks for a config.ini
file in the projects root directory. If it does not exist, the module will create one.
If load_and_validate_config(enable_logging=True) is set the following default contents will be added :
[Logging]
log_dir = logs
log_override = true
log_function_calls = false
use_global_log_level = true
[log_level]
global_log_level = INFO
If load_and_validate_config(enable_logging=False) or load_and_validate_config() then an empty config.ini is created, and the developer can set the required config parameters.
You can modify config.ini
to suit your projects needs:
True
, logs are overwritten with each new application run. If False
, logs are appended to the existing file.True
, logs function calls (if decorated with @log_function_call
).For more granular control, specify log levels for individual modules in the [log_level]
section:
[log_level]
global_log_level = INFO
myapp.module1 = DEBUG
myapp.module2 = ERROR
In each module of your project, initialize logging with setup_logging
:
from logging_util import setup_logging
setup_logging('my_module')
This configures logging based on the settings in the config.ini
file. Logs will be saved in the directory specified by log_dir
.
@log_function_call
In Python, it is not possible to automatically log all function calls without explicitly decorating them. The @log_function_call
decorator allows detailed logging for specific functions, including:
Testing showed that it was not feasible to apply this feature globally across all functions. Therefore, functions must be decorated individually to enable logging.
from logging_util import log_function_call
@log_function_call
def multiply(x, y):
return x * y
With log_function_calls
enabled (log_function_calls = true
in config.ini
), the following logs will be produced when multiply()
is called:
DEBUG - Entering multiply() with arguments: (3, 5)
DEBUG - Exiting multiply() with result: 15
log_override
The log_override
setting controls whether log files are overwritten or appended with each new application run:
True
: The log file is overwritten.False
: Logs are appended to the existing log file.Use log_override
to control how long you want to retain log data. For example, in development, you may want to overwrite logs on each run, but in production, appending logs may be preferable.
log_function_calls
This setting controls whether function calls and their parameters/return values are logged. To enable function logging:
log_function_calls = true
in the config.ini
.@log_function_call
.The global log level is a single log level that applies across all modules in your application. This simplifies logging configuration by providing a consistent log level for the entire application.
use_global_log_level
is True
: The global log level applies to all modules.use_global_log_level
is False
: Each module can have its own log level, specified under the [log_level]
section.use_global_log_level = true
to simplify logging across the project. Use individual module levels only when necessary.log_override = false
, ensure you manage log file sizes appropriately by implementing log rotation to avoid excessive log growth.We welcome contributions to the project. Please submit issues or pull requests on GitHub.
This project is licensed under the MIT License. See the LICENSE
file for details.
The config_utilities
project provides an efficient and flexible way to manage configurations and logging in Python applications. By using decorators like @log_function_call
, you can easily track function execution while keeping your logs organized and manageable through the config.ini
file.