-
Notifications
You must be signed in to change notification settings - Fork 1
✨ feat: Add TOML configuration support #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Migrate from .env to config.toml for better configuration management: - Add config.toml.example with comprehensive settings - Create utils/config.py for centralized config management - Support environment variable overrides for backward compatibility - Update bot.py to use new configuration system with .env fallback - Add tomli dependency for Python < 3.11 compatibility - Update .gitignore to ignore config.toml but not the example - Update documentation to reflect new configuration approach 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add missing python-dotenv dependency to pyproject.toml - Update README.md dependencies list to include python-dotenv - Improve DummyConfig implementation with better compatibility - Add proper documentation and property methods to DummyConfig Fixes identified by Copilot review: - Missing dependency for load_dotenv() function - Documentation formatting consistency - Code duplication reduction in fallback configuration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds full TOML-based configuration support with environment variable overrides, preserves .env fallback, and centralizes settings access via a singleton ConfigManager.
- Introduces a new
ConfigManagerfor loading TOML, applying env overrides, and exposing typed getters - Updates
bot.pyto initialize viaConfigManagerand provide a.env-based fallback - Adds
tomlidependency, updates docs and examples for the new configuration methods
Reviewed Changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/config.py | New ConfigManager handling TOML parsing, env overrides, and getters |
| utils/init.py | Exports get_config and ConfigManager |
| pyproject.toml | Added python-dotenv and tomli dependencies |
| config.toml.example | Full example of all supported config sections |
| bot.py | Loads configuration via ConfigManager, sets up logging, and falls back to .env |
| README.md | Documentation for TOML and env var configuration methods |
| .env.example | Clarified backward-compatibility notes and optional Gemini API key |
Comments suppressed due to low confidence (2)
README.md:64
- [nitpick] The TOML example in the README omits the
[bot]section forcommand_prefix. Add a snippet showing how to configurebot.command_prefixfor completeness.
[schedule]
bot.py:50
- The call to
load_dotenv(and subsequentos.getenvusage) requires imports for bothosandload_dotenvfromdotenv. Without these imports, this will raise a NameError.
load_dotenv(dotenv_path='.env', verbose=True, override=True)
| from datetime import datetime, timedelta | ||
| from pathlib import Path | ||
| import logging | ||
| from utils.logger import setup_logging, get_logger, set_module_level |
Copilot
AI
Jul 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The set_module_level import is unused in this file; consider removing it to keep imports clean.
| from utils.logger import setup_logging, get_logger, set_module_level | |
| from utils.logger import setup_logging, get_logger |
| class DummyConfig: | ||
| """Compatibility wrapper for .env configuration""" | ||
|
|
||
| def get(self, key, default=None): | ||
| """Get configuration value with .env fallback""" | ||
| if key == "database.path": | ||
| return "data/data.db" | ||
| elif key == "schedule.post_time": | ||
| return POST_TIME | ||
| elif key == "schedule.timezone": | ||
| return TIMEZONE | ||
| return default | ||
|
|
||
| def get_section(self, section): | ||
| """Get configuration section""" | ||
| if section == "logging": | ||
| return { | ||
| "level": "INFO", | ||
| "directory": "./logs", | ||
| "modules": { | ||
| "bot": "DEBUG", | ||
| "bot.discord": "DEBUG", | ||
| "bot.lcus": "DEBUG", | ||
| "bot.db": "DEBUG", | ||
| "discord": "WARNING", | ||
| "discord.gateway": "WARNING", | ||
| "discord.client": "WARNING", | ||
| "requests": "WARNING" | ||
| } | ||
| } | ||
| return {} | ||
|
|
||
| def get_llm_model_config(self, model_type): | ||
| """Get LLM model configuration""" | ||
| if model_type == "standard": | ||
| return {"name": "gemini-2.5-flash", "temperature": 0.0} | ||
| else: | ||
| return {"name": "gemini-2.5-pro", "temperature": 0.0} | ||
|
|
||
| def get_cache_expire_seconds(self, cache_type): | ||
| """Get cache expiration time""" | ||
| return 3600 if cache_type == "translation" else 86400 | ||
|
|
||
| @property | ||
| def discord_token(self): | ||
| return DISCORD_TOKEN | ||
|
|
||
| @property | ||
| def gemini_api_key(self): | ||
| return os.getenv('GOOGLE_GEMINI_API_KEY') | ||
|
|
||
| @property | ||
| def post_time(self): | ||
| return POST_TIME | ||
|
|
||
| @property | ||
| def timezone(self): | ||
| return TIMEZONE | ||
|
|
||
| config = DummyConfig() |
Copilot
AI
Jul 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The DummyConfig class duplicates logic and default values from ConfigManager. Consider refactoring to reuse common code or reduce duplication.
| class DummyConfig: | |
| """Compatibility wrapper for .env configuration""" | |
| def get(self, key, default=None): | |
| """Get configuration value with .env fallback""" | |
| if key == "database.path": | |
| return "data/data.db" | |
| elif key == "schedule.post_time": | |
| return POST_TIME | |
| elif key == "schedule.timezone": | |
| return TIMEZONE | |
| return default | |
| def get_section(self, section): | |
| """Get configuration section""" | |
| if section == "logging": | |
| return { | |
| "level": "INFO", | |
| "directory": "./logs", | |
| "modules": { | |
| "bot": "DEBUG", | |
| "bot.discord": "DEBUG", | |
| "bot.lcus": "DEBUG", | |
| "bot.db": "DEBUG", | |
| "discord": "WARNING", | |
| "discord.gateway": "WARNING", | |
| "discord.client": "WARNING", | |
| "requests": "WARNING" | |
| } | |
| } | |
| return {} | |
| def get_llm_model_config(self, model_type): | |
| """Get LLM model configuration""" | |
| if model_type == "standard": | |
| return {"name": "gemini-2.5-flash", "temperature": 0.0} | |
| else: | |
| return {"name": "gemini-2.5-pro", "temperature": 0.0} | |
| def get_cache_expire_seconds(self, cache_type): | |
| """Get cache expiration time""" | |
| return 3600 if cache_type == "translation" else 86400 | |
| @property | |
| def discord_token(self): | |
| return DISCORD_TOKEN | |
| @property | |
| def gemini_api_key(self): | |
| return os.getenv('GOOGLE_GEMINI_API_KEY') | |
| @property | |
| def post_time(self): | |
| return POST_TIME | |
| @property | |
| def timezone(self): | |
| return TIMEZONE | |
| config = DummyConfig() | |
| class DummyConfig(get_config().__class__): | |
| """Compatibility wrapper for .env configuration""" | |
| def __init__(self): | |
| super().__init__() | |
| self.env_values = { | |
| "discord_token": os.getenv('DISCORD_TOKEN'), | |
| "post_time": os.getenv('POST_TIME', '00:00'), | |
| "timezone": os.getenv('TIMEZONE', 'UTC'), | |
| "gemini_api_key": os.getenv('GOOGLE_GEMINI_API_KEY'), | |
| } | |
| def get(self, key, default=None): | |
| """Get configuration value with .env fallback""" | |
| if key in self.env_values: | |
| return self.env_values[key] | |
| return super().get(key, default) | |
| @property | |
| def discord_token(self): | |
| return self.env_values["discord_token"] | |
| @property | |
| def gemini_api_key(self): | |
| return self.env_values["gemini_api_key"] | |
| @property | |
| def post_time(self): | |
| return self.env_values["post_time"] | |
| @property | |
| def timezone(self): | |
| return self.env_values["timezone"] | |
| config = DummyConfig() |
Summary
config.toml.envfilesChanges Made
utils/config.pywithConfigManagerclassconfig.toml.exampletemplate with comprehensive settings.envfiles continue to worktomlifor Python < 3.11 TOML supportTest Plan
.envwhenconfig.tomlis missing🤖 Generated with Claude Code