Initial commit

This commit is contained in:
KamilM1205 2026-01-19 23:32:11 +04:00
commit 9795660e1f
43 changed files with 2757 additions and 0 deletions

152
config/environment.py Normal file
View 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()