Ответ
Да, создавал. Один из последних пакетов — это внутренняя утилита для конфигурации микросервисов. Она автоматически загружала настройки из Consul, валидировала их по Pydantic-схемам и предоставляла готовый объект конфига с кэшированием.
Структура пакета internal_config:
internal_config/
├── pyproject.toml # Современная конфигурация с setuptools
├── src/
│ └── internal_config/
│ ├── __init__.py
│ ├── loader.py # Логика загрузки из Consul/Vault
│ ├── validator.py # Валидация через Pydantic
│ └── exceptions.py
└── tests/
Ключевые шаги и best practices, которые я применял:
pyproject.tomlвместоsetup.py: Использовал современный стандарт для указания зависимостей, entry points и метаданных.- Структура
src/: Это предотвращает случайный импорт из неинсталлированной версии кода. - Типизация и документация: Полностью типизировал публичные функции и использовал docstring в формате Google. Добавил
README.mdс примерами использования. - Тестирование и публикация: Настроил
pytestс покрытием, а публикацию в приватный Artifactory выполнял черезtwine.
Пример фрагмента кода из __init__.py:
from .loader import ConfigLoader
from .validator import AppConfig
from typing import Optional
import cachetools
class ConfigurationManager:
_cache = cachetools.TTLCache(maxsize=10, ttl=300)
def __init__(self, service_name: str):
self.service_name = service_name
def get_config(self) -> AppConfig:
"""Возвращает валидированную конфигурацию для сервиса."""
if self.service_name not in self._cache:
loader = ConfigLoader(self.service_name)
raw_config = loader.fetch()
self._cache[self.service_name] = AppConfig(**raw_config)
return self._cache[self.service_name]
Пакет используется в более чем 10 сервисах нашей команды, что упростило управление настройками и их валидацию на этапе запуска.
Ответ 18+ 🔞
А, ну это я помню, ёпта! Создавал, блядь, конечно. Последняя моя поделка — это внутренняя утилитка для конфигурации микросервисов. Представляешь, эта штука сама лезет в Consul, вытаскивает настройки, прогоняет их через Pydantic-схемы, как через мясорубку, и выдаёт тебе готовый, валидный объект конфига, да ещё и закэшированный. Удобно, сука, до безобразия!
Вот как эта мартышлюшка internal_config устроена:
internal_config/
├── pyproject.toml # Всё по-взрослому, на setuptools
├── src/
│ └── internal_config/
│ ├── __init__.py
│ ├── loader.py # Тут логика, как из Consul/Vault всё сосать
│ ├── validator.py # А тут Pydantic всё проверяет
│ └── exceptions.py
└── tests/ # Без этого никак, а то доверия — ноль ебать
Что я там накрутил, какие best practices соблюдал:
pyproject.tomlвместо старогоsetup.py: Ёперный театр, 21 век на дворе, пора уже на современные стандарты переходить. Там и зависимости, и entry points, и всё прочее.- Структура
src/: Обязательная штука, чувак. Чтобы случайно не импортировать код, который ещё не установлен. Иначе потом волнение ебать — «оно у меня на машине работало!». - Типизация и документы: Все публичные функции затипизировал, docstring накидал.
README.mdс примерами, чтобы даже самый упоротый коллега разобрался. Иначе потом подозрение ебать чувствую — кто и как это использует. - Тесты и публикация:
pytestс покрытием настроил, а в приватный Artifactory черезtwineзаливал. Без этого — пидарас шерстяной, а не разработчик.
Смотри, кусочек кода из __init__.py для наглядности:
from .loader import ConfigLoader
from .validator import AppConfig
from typing import Optional
import cachetools
class ConfigurationManager:
_cache = cachetools.TTLCache(maxsize=10, ttl=300)
def __init__(self, service_name: str):
self.service_name = service_name
def get_config(self) -> AppConfig:
"""Возвращает валидированную конфигурацию для сервиса."""
if self.service_name not in self._cache:
loader = ConfigLoader(self.service_name)
raw_config = loader.fetch()
self._cache[self.service_name] = AppConfig(**raw_config)
return self._cache[self.service_name]
В общем, эта хитрая жопа теперь в десяти с лишним сервисах нашей команды болтается. Управлять настройками стало в разы проще, а валидация на старте сразу отсекает всякий пиздец из-за опечаток в конфигах. Красота, блядь!