Pull to refresh

Comments 12

Какие хорошие библиотеки (фреймворки) выбрал автор. Давно за ними наблюдаю, очень надеюсь на их развитие и популяризацию, нравятся заложенные концепции.

Есть опыт использования в проде? Есть ли какие-то неочевидные особенности по эксплуатации?

На прод только планируем затаскивать для одного из сервисов.
Единственное, что вместо pydantic планируем использовать msgspec.

Из неочевидных особенностей хочу отметить, что тащить все батарейки из Litestar к себе в проект не стоит, лучше ограничиться только функционалом http фреймворка.

А с чем связан уход от Pydantic?

На самом деле у нас pydantic то и не было, у нас была своё самописная библиотека для этих целей. Просто поддерживать её не представляется возможным.

Если выделить, чем нам pydantic не нравится, то:
- Не позволяет создавать один и тот же класс из нескольких источников или отдавать в разном виде.
- При создании модели вручную, нужно передавать поля по алиасам, allow_population_by_name не решает эту проблему.
- Неявные преобразование типов
- По мелочи какое-то неявное поведение

Имеем на проде Litestar для обслуживания небольшого функционала бэкофиса. Сначала были воодушевлены, затем расстроились.

Репозитории, которые предлагает использовать advanced alchemy (батарейка, не включена, но рекомендуется разработчиками), годятся разве что для круда. Мало-мальски сложных агрегатов с пятиэтажными джойнами с ним не построить, а итоге мы используем фасад к обычной алхимии, где пишем чуть не не raw-sql, в итоге выгоды никакой.

DI работает только в тех местах, где решили разработчики, а это ровно три слоя. Для под-зависимостей нужно собирать контейнер в контроллере. Причем, контейнер это сильное слово, потому что просто неявно заполняем globals. Их того следует, что все аннотации должны быть вычислены на этапе сборки, иначе не сработает.

Там, где мы думали, что быстро проскочит с его батарейками, в основном боролись именно с фреймворком и его имплементацией. Сильно не сэкономили.

Как уже отметили, лучше использовать его как http фреймворк. Но такой сценарий использования не делает его лучше, чем какой-то fast-api.

Ну если говорить о том, чем он лучше FastAPI, то тут можно выделить несколько моментов:
1. Гвоздями не прибит pydantic
2. Есть ClassView (мне нравится)
3. Depends от FastAPI отражается в OpenAPI схеме, в Litestar - нет

Ещё очень важный, возможно самый важный момент - разработка lightstar ведётся сообществом, более чем из одного человека. К сожалению, мы знаем истории библиотек, у которых был единственный мейнтейнер, а потом с ним что-то случилось :(

@Tishka17писал Stub класс для исключения проброса зависимостей в OpenAPI схему, продублирую тут.

Код
class Stub:
    """
    This class is used to prevent FastAPI from digging into
    real dependencies attributes detecting them as request data

    So instead of
    `interactor: Annotated[Interactor, Depends()]`
    Write
    `interactor: Annotated[Interactor, Depends(Stub(Interactor))]`

    And then you can declare how to create it:
    `app.dependency_overrides[Interactor] = some_real_factory`

    """

    def __init__(self, dependency: Callable, **kwargs) -> None:
        self._dependency = dependency
        self._kwargs = kwargs

    def __call__(self) -> None:
        raise NotImplementedError

    def __eq__(self, other) -> bool:
        if isinstance(other, Stub):
            return (
                self._dependency == other._dependency
                and self._kwargs == other._kwargs
            )
        return False if self._kwargs else self._dependency == other

    def __hash__(self) -> int:
        if not self._kwargs:
            return hash(self._dependency)
        serial = (
            self._dependency,
            *self._kwargs.items(),
        )
        return hash(serial)


SMSDep = Annotated[SMSServiceAbstract, Depends(Stub(TwilioService))]

Ну я повозился с этим Stub и сделал dishka, который прекрасно можно юзать с FastAPI.

Лучше бы джангу взял и побольше денег дяде приносил

сарказм

А зачем в примере с интерфейсами где описаны протоколы используют декоратор @abstractmethod на методах?

Я потом наследуюсь от протокола вот тут.
Это нужно для того, чтобы быть уверенным, что какой-то класс удовлетворяет протоколу.
Когда у вас много протоколов и объектов которые имплементируют их, то такое поведение очень удобно

PEP 544

Sign up to leave a comment.