Initial commit
This commit is contained in:
commit
9795660e1f
43 changed files with 2757 additions and 0 deletions
152
config/environment.py
Normal file
152
config/environment.py
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class EnvironmentLoader:
|
||||
"""Класс для загрузки переменных окружения из .env файлов"""
|
||||
|
||||
# Порядок загрузки файлов .env (от более специфичного к общему)
|
||||
ENV_FILES_ORDER = [
|
||||
'.env.local', # Локальные переопределения (не в git)
|
||||
f'.env.{os.getenv("ENV", "development")}', # Окружение: .env.test, .env.production
|
||||
'.env', # Основной файл
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def load_environment(cls, env_file: Optional[str] = None):
|
||||
"""
|
||||
Загрузка переменных окружения.
|
||||
|
||||
Args:
|
||||
env_file: Конкретный файл для загрузки (если None, используется порядок из ENV_FILES_ORDER)
|
||||
"""
|
||||
if env_file:
|
||||
# Загрузка конкретного файла
|
||||
env_path = Path(env_file)
|
||||
if env_path.exists():
|
||||
logger.info(f"Loading environment from specified file: {env_path}")
|
||||
load_dotenv(dotenv_path=env_path, override=True)
|
||||
else:
|
||||
logger.warning(f"Specified env file not found: {env_path}")
|
||||
return
|
||||
|
||||
# Автоматическая загрузка в определенном порядке
|
||||
env_loaded = False
|
||||
|
||||
for env_filename in cls.ENV_FILES_ORDER:
|
||||
env_path = find_dotenv(env_filename, usecwd=True)
|
||||
if env_path:
|
||||
logger.info(f"Loading environment from: {env_path}")
|
||||
load_dotenv(dotenv_path=env_path, override=True)
|
||||
env_loaded = True
|
||||
|
||||
if not env_loaded:
|
||||
logger.warning("No .env files found, using system environment variables")
|
||||
|
||||
@classmethod
|
||||
def get_env_variable(cls, key: str, default: Any = None, required: bool = False) -> Any:
|
||||
"""
|
||||
Получение переменной окружения с проверкой.
|
||||
|
||||
Args:
|
||||
key: Ключ переменной окружения
|
||||
default: Значение по умолчанию, если переменная не найдена
|
||||
required: Обязательна ли переменная (вызывает исключение, если не найдена)
|
||||
|
||||
Returns:
|
||||
Значение переменной окружения
|
||||
|
||||
Raises:
|
||||
ValueError: Если переменная required=True и не найдена
|
||||
"""
|
||||
value = os.getenv(key)
|
||||
|
||||
if value is None:
|
||||
if required:
|
||||
raise ValueError(f"Required environment variable '{key}' is not set")
|
||||
return default
|
||||
|
||||
# Автоматическое преобразование типов
|
||||
if value.lower() in ('true', 'false'):
|
||||
return value.lower() == 'true'
|
||||
elif value.isdigit():
|
||||
return int(value)
|
||||
elif cls._is_float(value):
|
||||
return float(value)
|
||||
elif value.startswith('[') and value.endswith(']'):
|
||||
# Список значений, разделенных запятыми
|
||||
return [item.strip() for item in value[1:-1].split(',') if item.strip()]
|
||||
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def _is_float(value: str) -> bool:
|
||||
"""Проверка, можно ли преобразовать строку в float"""
|
||||
try:
|
||||
float(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def validate_environment(cls):
|
||||
"""Валидация обязательных переменных окружения"""
|
||||
required_vars = [
|
||||
# 'API_BASE_URL',
|
||||
# 'UI_BASE_URL',
|
||||
]
|
||||
|
||||
missing_vars = []
|
||||
for var in required_vars:
|
||||
if not os.getenv(var):
|
||||
missing_vars.append(var)
|
||||
|
||||
if missing_vars:
|
||||
raise EnvironmentError(
|
||||
f"Missing required environment variables: {', '.join(missing_vars)}\n"
|
||||
f"Please set them in .env file or system environment."
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def print_environment_info(cls):
|
||||
"""Вывод информации о текущем окружении (для отладки)"""
|
||||
env_info = {
|
||||
'ENV': os.getenv('ENV', 'development'),
|
||||
'API_BASE_URL': os.getenv('API_BASE_URL'),
|
||||
'UI_BASE_URL': os.getenv('UI_BASE_URL'),
|
||||
'DEBUG': os.getenv('DEBUG', 'False'),
|
||||
'LOG_LEVEL': os.getenv('LOG_LEVEL', 'INFO'),
|
||||
}
|
||||
|
||||
logger.info("Current environment configuration:")
|
||||
for key, value in env_info.items():
|
||||
logger.info(f" {key}: {value}")
|
||||
|
||||
@classmethod
|
||||
def get_all_env_variables(cls, prefix: str = '') -> Dict[str, Any]:
|
||||
"""
|
||||
Получение всех переменных окружения с опциональным префиксом.
|
||||
|
||||
Args:
|
||||
prefix: Фильтр по префиксу (например, 'API_' для всех API настроек)
|
||||
|
||||
Returns:
|
||||
Словарь переменных окружения
|
||||
"""
|
||||
env_vars = {}
|
||||
|
||||
for key, _ in os.environ.items():
|
||||
if len(prefix) == 0 and not key.startswith(prefix):
|
||||
continue
|
||||
|
||||
env_vars[key] = cls.get_env_variable(key)
|
||||
|
||||
return env_vars
|
||||
|
||||
# Инициализация при импорте модуля
|
||||
EnvironmentLoader.load_environment()
|
||||
Loading…
Add table
Add a link
Reference in a new issue