Welcome to config-cli-gui#
Unified Configuration and Interface Management
Provides a generic configuration framework that automatically generates both command-line interfaces and GUI settings dialogs from configuration parameters.
config-cli-gui is a Python library designed to streamline the management of application configurations,
generating command-line interfaces (CLIs), and dynamically creating graphical user interface (GUI) settings dialogs
from a single source of truth. It leverages Pydantic for robust parameter definition and offers
powerful features for consistent configuration across different application entry points.
๐ Installation#
You can install config-cli-gui using pip:
pip install config-cli-gui
โจ Features#
-
Single Source of Truth: Define all your application parameters in one place using simple, dataclass-like structures based on Pydantic's
BaseModel. This ensures consistency and reduces errors across your application.yaml gui: # GUI theme setting | type=str | choices=['light', 'dark', 'auto'] theme: light misc: # Example integer | type=int some_numeric: 42 # Path to the file to use | type=PosixPath some_file: some_file.txt # Color setting for the application | type=Color some_color: '#ff0000' # Font setting for the application | type=Font some_font: 'DejaVuSans.ttf, 12, #0000ff' -
Categorized Configuration: Organize your parameters into logical categories (e.g.,
cli,app,gui) for better structure and maintainability. - Dynamic CLI Generation: Automatically generate
argparse-compatible command-line arguments directly from your defined configuration parameters, including help texts, types, and choices. - Config File Management: Easily load and save configurations from/to YAML or JSON files, allowing users to customize default settings.
-
GUI Settings Dialogs: Dynamically create Tkinter-based settings dialogs for your application, allowing users to intuitively modify configuration parameters via a graphical interface.

-
Documentation Generation: Generate detailed Markdown documentation for both your CLI options and all configuration parameters, keeping your user guides always up-to-date with your codebase.

-
Override System: Supports robust overriding of configuration values via configuration files and command-line arguments, with clear precedence.
๐ Usage#
1. Define Your Configuration#
Start by defining your application's configuration parameters in a central config.py file within your project. You will inherit from config-cli-gui's GenericConfigManager and BaseConfigCategory.
# my_project/config_example.py
from datetime import datetime
from pathlib import Path
from config_cli_gui.config import (
ConfigCategory,
ConfigManager,
ConfigParameter,
)
from config_cli_gui.configtypes.color import Color
from config_cli_gui.configtypes.font import Font
from config_cli_gui.configtypes.vector import Vector
class MiscConfig(ConfigCategory):
def get_category_name(self) -> str:
return "misc"
some_numeric: ConfigParameter = ConfigParameter(
name="some_numeric",
value=int(42),
help="Example integer",
is_cli=True,
)
some_vector: ConfigParameter = ConfigParameter(
name="some_vector",
value=Vector(1, 2, 3),
help="Example vector",
)
some_file: ConfigParameter = ConfigParameter(
name="some_file",
value=Path("some_file.txt"),
help="Path to the file to use",
)
some_color: ConfigParameter = ConfigParameter(
name="some_color",
value=Color(255, 0, 0),
help="Color setting for the application",
)
some_date: ConfigParameter = ConfigParameter(
name="some_date",
value=datetime.fromisoformat("2025-12-31 10:30:45"),
help="Date setting for the application",
)
some_font: ConfigParameter = ConfigParameter(
name="some_font",
value=Font("DejaVuSans.ttf", size=12, color=Color(0, 0, 255)),
help="Font setting for the application",
)
class AppConfig(ConfigCategory):
"""Application-specific configuration parameters."""
def get_category_name(self) -> str:
return "app"
log_level: ConfigParameter = ConfigParameter(
name="log_level",
value="INFO",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help="Logging level for the application",
)
log_file_max_size: ConfigParameter = ConfigParameter(
name="log_file_max_size",
value=10,
help="Maximum log file size in MB before rotation",
)
class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
"""Main configuration manager that handles all parameter categories."""
app: AppConfig
misc: MiscConfig
def __init__(self, config_file: str | None = None, **kwargs):
"""Initialize the configuration manager with all parameter categories."""
categories = (MiscConfig(), AppConfig())
super().__init__(categories, config_file, **kwargs)
2. Generate CLI#
Use the generic CLI functions to parse command-line arguments based on your defined CliConfig.
# my_project/cli_example.py
from config_cli_gui.cli import CliGenerator
from config_cli_gui.config import ConfigManager
from tests.example_project.config.config_example import ProjectConfigManager
from tests.example_project.core.base import BaseGPXProcessor
from tests.example_project.core.logging import initialize_logging
def run_main_processing(_config: ConfigManager) -> int:
"""Main processing function that gets called by the CLI generator.
Args:
_config: Configuration manager with all settings
Returns:
Exit code (0 for success, non-zero for error)
"""
# Initialize logging system
logger_manager = initialize_logging(_config)
logger = logger_manager.get_logger("config_cli_gui.cli")
try:
# Log startup information
logger.info("Starting config_cli_gui CLI")
logger_manager.log_config_summary()
logger.info(f"Processing input")
# Create and run BaseGPXProcessor
processor = BaseGPXProcessor(
_config.get_category("cli").input.default,
_config.get_category("cli").output.default,
_config.get_category("cli").min_dist.default,
_config.get_category("app").date_format.default,
_config.get_category("cli").elevation.default,
logger=logger,
)
logger.info("Starting conversion process")
# Run the processing (adjust method name based on your actual implementation)
result_files = processor.compress_files()
logger.info(f"Successfully processed {result_files}")
return 0
except Exception as e:
logger.error(f"Processing failed: {e}")
logger.debug("Full traceback:", exc_info=True)
return 1
def main():
"""Main entry point for the CLI application."""
# Create the base configuration manager
config_manager = ProjectConfigManager()
# Create CLI generator
cli_generator = CliGenerator(config_manager=config_manager, app_name="config_cli_gui")
# Run the CLI with our main processing function
return cli_generator.run_cli(
main_function=run_main_processing,
description="Example CLI for config-cli-gui using the generic config framework.",
)
if __name__ == "__main__":
import sys
sys.exit(main())
3. Integrate GUI Settings Dialog#
The SettingsDialog from config-cli-gui (or your project's adapted version) can be used to easily create a settings window.
# my_project/gui_example.py (Simplified example)
import tkinter as tk
from tests.example_project.config.config_example import ProjectConfigManager
from config_cli_gui.gui import GenericSettingsDialog # Assuming gui_settings is part of the generic lib or adapted
def open_settings_window(parent_root, config_manager: ProjectConfigManager):
dialog = GenericSettingsDialog(parent_root, config_manager)
parent_root.wait_window(dialog.dialog)
# After dialog closes, config_manager will have updated values if 'OK' was clicked
print("Settings updated or cancelled.")
print(f"New GUI Theme: {config_manager.get_category('gui').theme.default}")
if __name__ == "__main__":
root = tk.Tk()
root.withdraw() # Hide main window for this example
# Initialize your project's config manager
project_config = ProjectConfigManager()
open_settings_window(root, project_config)
root.destroy()
4. Generate Documentation and Default Config#
Use the static methods on your ProjectConfigManager to generate config.yaml, cli.md, and config.md files.
# scripts/generate_docs.py (or similar script in your project)
from tests.example_project.config.config_example import ProjectConfigManager
from config_cli_gui.docs import DocumentationGenerator
import os
# Define output paths
output_dir = "docs/generated"
os.makedirs(output_dir, exist_ok=True)
default_config = "config.yaml" # At the project root or similar
default_cli_doc = os.path.join(output_dir, "cli.md")
default_config_doc = os.path.join(output_dir, "config.md")
_config = ProjectConfigManager()
doc_gen = DocumentationGenerator(_config)
doc_gen.generate_default_config_file(output_file=default_config)
print(f"Generated: {default_config}")
doc_gen.generate_config_markdown_doc(output_file=default_config_doc)
print(f"Generated: {default_config_doc}")
doc_gen.generate_cli_markdown_doc(output_file=default_cli_doc)
print(f"Generated: {default_cli_doc}")
print("Documentation and default config generation complete.")
By following this structure, config-cli-gui provides a robust and maintainable foundation for your application's configuration needs.