- PVSM.RU - https://www.pvsm.ru -

Находки в опенсорсе: мир питона за сентябрь 2026

Добро пожаловать в мир находок в опенсорсе!

Добро пожаловать в мир находок в опенсорсе!

Вот и наступила золотая осень!

В сентябре я каждый день почему‑то вспоминал поговорку «от работы дохнут кони, ну а я бессмертный пони». Сделано было просто куча всего! Новые релизы, библиотеки, крутые фичи, доклад на конференции. А еще наше сообщество сделало кучу интересных проектов в опенсорсе.

С меня как всегда статья без нейрослопа и ИИ, с вас как всегда интересные комментарии и лайки! А вот тут ссылка на прошлый дайджест [1] за август.

Погнали смотреть, что у нас в питоне происходило!


CPython

Мой маленький вклад за месяц

Я очень активно занимался django-modern-rest, но в CPython успел влить вот такой приятный коммит [2] (с помощью от Pablo): теперь при опечатках в именах __future__ импортов, будет красивая ошибка. Было так:

>>> from __future__ import anotations
  File "<python-input-0>", line 1
    from __future__ import anotations
                           ^^^^^^^^^^
SyntaxError: future feature anotations is not defined

Стало так:

>>> from __future__ import anotations
  File "<python-input-0>", line 1
    from __future__ import anotations
                           ^^^^^^^^^^
SyntaxError: future feature 'anotations' is not defined. Did you mean: 'annotations'?

Я всегда и везде топлю за красивые сообщения об ошибках.

Обсуждения PEP'ов

В основном канале вышло два поста (раз [3], два [4]) про новые PEP'ы в Python. Остановлюсь подробнее на PEP-823 [5] и PEP-824 [6]. Остальные можно почитать в канале [7]. Они предлагают добавить «монадические выражения для обработки None значений».

Первый PEP посвящен двум новым операторам ?. и?[], которые семантически идентичны для some?.field следующим кодом:

if some is not None:
    field = some.field
else:
    field = None

Аналогично some?['field'] делает доступ через __getitem__, вместо __getattr__ в варианте выше. На реалистичном примере выглядит еще лучше:

def get_customer_name(data: Data) -> str | None:
    return data.customer?.user?.name.lower()

Вот такой простой код разворачивается вот в такую бандуру:

def get_customer_name(data: Data) -> str | None:
    """Get customer name in lower case if it exists."""
    customer = data.customer
    if customer is not None:
        user = customer.user
        if user is not None:
            return user.name.lower()
    return None

Второй PEP добавляет оператор ??, который заменяет проверку is not None в тернарном выражении на более удобное:

def func(param: int | None = None):
    print(-1 if param is None else param)

# =>

def func(param: int | None = None):
    print(param ?? -1)

Многие в комментариях под постом спрашивают: а почему не использовать просто param or -1? Потому что or проверяет на bool, то есть 0 не будет выведен, даже если будет явно отправлен.

Мне кажется, что первый пункт — обязательный; второй — под вопросом. Хорошо, что авторы разделили ПЕПы на две штуки. Очень жду принятие первого, равнодушен по поводу второго.

Обсуждение: Что вы думаете по поводу данного PEP? Хочется ли такой синтаксис?

Развитие сообщества

Номинировали [8] нашего уважаемого Сергея Мирянова (@zzzzzzerg [9]) на пост CPython Core Developer. Потому что нам нужно больше людей, кто работает над GC. Опрос закончится завтра. Очень надеемся и верим!

А пока можете посмотреть его доклад с прошедшего PyCon:

Шутки про сбор мусора пайтон разработчиками, потому что всех заменили на ИИ — приветствуются в комментариях!

msgspec

Наконец‑то я сделал релиз 0.22.0 версии [10]!

Внутри очень много улучшений. Я бы хотел остановиться подробно на одном (остальные можно посмотреть самостоятельно по ссылке). Поговорим про ускорение сериализации dataclass объектов за счет изменения логики [11]получения __dataclass_field__ из инстанса. Посмотрим на код изменения:

// Было:
PyObject *fields = PyObject_GetAttr(obj, self->mod->str___dataclass_fields__);

А вот так стало:

static MS_INLINE PyObject *
ms_type_lookup_ref(PyTypeObject *type, PyObject *name) {
#if PY313_PLUS
    return _PyType_LookupRef(type, name);
#else
    PyObject *out = _PyType_Lookup(type, name);
    Py_XINCREF(out);
    return out;
#endif
}

static PyObject *
ms_get_dataclass_fields(MsgspecState *mod, PyTypeObject *type, PyObject *obj) {
    PyObject *fields = ms_type_lookup_ref(type, mod->str___dataclass_fields__);
    if (fields == NULL) return NULL;
    if (MS_LIKELY(
        PyDict_CheckExact(fields) &&
        type->tp_getattro == PyObject_GenericGetAttr
    )) {
        return fields;
    }
    Py_DECREF(fields);
    fields = PyObject_GetAttr(obj, mod->str___dataclass_fields__);
    if (fields == NULL) PyErr_Clear();
    return fields;
}

// Стало:
PyObject *fields = ms_get_dataclass_fields(self->mod, type, obj);

Что изменилось? Раньше мы проверяли наличие __dataclass_fields__ прямо у каждого инстанса, что часто вызывало python код в __getattr__ инстанса. Теперь, мы сначала смотрим только на атрибут type(instance).__dataclass_fields__, и только если нам ничего не вернулось (или вернулось не то), то мы идем на старый медленный путь. Результат?

Какие-то кейсы ускорились аж на 73%, какие-то только на 5%

Какие‑то кейсы ускорились аж на 73%, какие‑то только на 5%

Круто? Круто. Старайтесь всегда делать так в вашем C‑API коде, избегайте PyObject_GetAttr везде, где можно.

Релиз вышел отличным, очень много полезного! Если еще не пробовали msgspec — самое время!

Обсуждение: Довольны ли вы скоростью pydantic? Замечаете ли вы деградацию скорости при увеличении объема данных?

django‑modern‑rest

Самый большой блок работы конечно же был тут! За месяц удалось сделать два больших релиза в рамках #opensource_september, было такое сообытие в нашем сообществе [12], в рамках него:

  • Создано 92 задачи на GithHub [13]

  • Из них решено 85

  • Достигнута цифра в 150 уникальных контрибьюторов

  • Почти 50 новых контрибьюторов за месяц

Особую благодарность хочется выразить Ольге Пичужкиной [14] за активный вклад в оба релиза.

Релиз 0.15.0

Полный список изменений [15].

Самое интересное: теперь можно создавать ленивые декларации для методов в переиспользуемых контроллерах, они будут выполняться уже только в финальном контроллере, что дает возможность менять любую мета‑информацию на лету:

class LoginController(Controller[_SerializerT]):
    status_code: ClassVar[HTTPStatus] = HTTPStatus.OK

    @classmethod
    def lazy_spec(cls) -> ModifyAnyCallable:
        return modify(status_code=cls.status_code)

    @modify.lazy(lazy_spec)
    def get(self) -> str:
        return 'login'


class CreatedLogin(LoginController[PydanticSerializer]):
    status_code = HTTPStatus.CREATED

Теперь CreatedLogin будет использовать свой собственный статус код для ответов. Удобно!

Релиз 0.16.0

Полный список изменений [16].

Самое интересное: улучшения производительности. Фреймворк стал значительно быстрее в разных местах. Вот сводная таблица.

Мы и дальше продолжим ускорять django-modern-rest!

Мы и дальше продолжим ускорять django‑modern‑rest!

По нашим бенчам мы уже на уровне FastAPI [17] (где‑то чуть быстрее, где‑то чуть медленее). Дальше будет еще быстрее, еще лучше, еще удобнее. И FastAPI можно будет закапывать!

Внутри очень много всего:

  • Поработали над DX

  • Улучшили AI тулинг для пользователей

  • Кратно прокачали OpenAPI схему и процесс генерации. Теперь поддерживаем даже x- атрибуты в типо‑безопасном API!

  • Провели масштабный аудит безопасности

  • Улучшили API для расширения фреймворка

Коллеги из core‑команды django-modern-rest доложились на PyCon о проделанной работе:

Обсуждение: Какие фичи вы бы хотели увидеть в новых релизах django-modern-rest?

pustota

Релизнули тему pustota для codex [18], вот так выглядит оригинал [19]:

pustota для vscode: https://github.com/pustota-theme/pustota

pustota для vscode: https://github.com/pustota‑theme/pustota [19]

А вот так выглядит pustota.codex:

https://github.com/pustota-theme/pustota.codex

Спасибо Александру [20] за тему!

Обсуждение: Нравятся ли вам минималистичные темы? Какие ваши любимые?

Проекты сообщества

  • Использование готовых DTO (pydantic / adaptix / dataclasses) в качестве JSON поля в Django моделях: https://github.com/skv0zsneg/django‑dto‑field [21]

  • Yara ORM — async ORM для Python с движком на Rust. Хотелось привычный Django/Tortoise API, но чтобы горячий путь (пул, биндинг, декодинг строк) крутился в компилированном коде на Rust: https://github.com/vsdudakov/yara‑orm [22]

  • FastAdmin — админка в духе Django Admin, но для FastAPI, Flask и Django, для разных orm — Tortoise, Django ORM, SQLAlchemy, Pony или Yara ORM: https://github.com/vsdudakov/fastadmin [23]

  • Yara Code — терминальный редактор под работу с кодинг‑агентами (Claude Code, Codex, Cursor CLI): https://github.com/vsdudakov/yara‑code [24]

  • Скилл для Claude Code и других агентов, позволяющий писать лучшие программы на Go. Внутри — выжимка из 13 источников: гайды Google и Uber, четыре Go‑скилла и четыре донора по агентам и MCP. Всё сведено в один непротиворечивый свод с явной лестницей приоритетов, так что на конфликтах побеждает архитектура, а не линтер: https://github.com/Djarvur/go‑ultimate [25]

  • Rust бекенд для Asr для GigaAm v3: https://github.com/deeray‑ltd/gigaam‑v3-runtime [26]

  • Клиент для протокола MQTT (широко используется в IoT): https://github.com/faststream‑community/zMQTT [27]

  • Для внутренних нужд создаём бинарные патчи, недавно выкатил интерактивную пошаговую иллюстрацию того как работает алгоритм создания патчей (чтобы не объяснять коллегам). Можно менять данные, константы: https://github.com/tochka‑public/bitcut [28]

  • DB STAT — это веб‑приложение для мониторинга PostgreSQL, Greenplum и Greengage. В одном интерфейсе можно посмотреть состояние баз данных, размеры таблиц, использование памяти, активные запросы, сессии и блокировки: https://github.com/OlegEgoism/DB_STAT [29]

  • Cотни навыков у агента без раздутого промпта, в 4,4 раза меньше входных токенов: 113k → 25,8k за ход на каталоге из 236 навыков: https://github.com/deyna256/langchain‑skill‑router [30]

  • Библиотека на Python, созданная для упрощения и ускорения асинхронной разработки. Ее декоратор @appoint_limit_async безопасно защищает от состояния гонки и ограничивает частоту вызовов функций, что крайне полезно для работы с лимитированными API: https://gitlab.com/asurnovsurnov/asynctoolspy [31]

  • Локальный k8s cluster одной строкой: https://github.com/prostoLavr/libvirtd‑tf‑infra [32]

  • Markdown Preview Editor — редактор Markdown с живым предпросмотром, работает полностью в браузере: файлы никуда не загружаются, бэкенда нет. Умеет GFM, формулы, Mermaid, вкладки, перетаскивание папок с картинками, экспорт в HTML и PDF: https://github.com/ovasendin/markdown_preview_editor [33]

Хотите попасть в следующий дайджест? Пишите о своем проекте в нашем чате [34], добавляйте тег #opensource, я обязательно им поделюсь!

Одной строкой

  • Вышел новый релиз mypy с поддержкой sentinel и TypeForm, читаем полный набор изменений для 2.4.0 тут [35]

  • Вышел новый релиз wemake-python-styleguide с несколькими фиксами багов @ 1.8.1 [36]

  • У django-stubs вышло два релиза: 6.1.1 [37] и 6.1.2 [38], в 6.1.1 мы поменяли правильную типизацию ReleatedManager, а в 6.1.2 добавили официальную поддержку mypy@2.4.0

  • У django-test-migrations вышел новый релиз 1.7.0 [39] с поддержкой новых версий Django

  • Вышел новый релиз нашей Dependency Injection библиотеки punq, в версии 0.9.0 [40] мы поправили то, как работают синглтоны зависимостей

  • Вышел новый 1.8.0 релиз [41] у библиотеки dump-env, она нужна для слияния .env.template файла и ENV переменных в один финальный .env файл, в новой версии мы поддержали полную шаблонизацию значений с флагом --interpolate

  • Съездил в Суздаль [42] в пресс‑тур с другими блогерами и коллегами из Magnit Tech [43]. Было очень круто. Приятно видеть, как развивается ритейл. Обсудил с коллегами умные кассы, внедрение ИИ, новые способы оплаты, предиктивную аналитику спроса, интересное в логистике, предложил им внедрить wps [44]

  • Продолжаем активно готовиться к нашей большой встрече сообщества [45]: 17 октября, Нижний Новгород. Бесплатное меропритие от сообщества и для сообщества. Будут очень крутые доклады от ваших любимых ютюберов и опенсорсеров. Ну и конечно тусовка нашего сообщества в баре и до утра. Ждем всех желающих!

Выводы

А если вы думаете, что я делаю что‑то полезное для мира, то поддержать можно по ссылкам:

Я там ничего не продаю, просто делаю свою работу, если считаете, что я делаю полезное — можно поддержать. Если нет, то я все равно продолжу ее делать.

Подписывайтесь на главный канал [48] сообщества, если вам нравится такое читать. И возможно даже захочется поучаствовать [49]! Буду рад видеть вас частью нашего опенсорс сообщества:)

До встречи в следующем дайджесте и в нашем сообществе!

Автор: sobolevn

Источник [50]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/459646

Ссылки в тексте:

[1] ссылка на прошлый дайджест: https://habr.com/ru/articles/1076694/

[2] в CPython успел влить вот такой приятный коммит: https://github.com/python/cpython/pull/154347

[3] раз: https://t.me/opensource_findings/987

[4] два: https://t.me/opensource_findings/988

[5] PEP-823: https://peps.python.org/pep-0823

[6] PEP-824: https://peps.python.org/pep-0824

[7] почитать в канале: https://t.me/opensource_findings

[8] Номинировали: https://discuss.python.org/t/vote-to-promote-sergey-miryanov/109283

[9] @zzzzzzerg: https://habr.com/users/zzzzzzerg

[10] я сделал релиз 0.22.0 версии: https://github.com/msgspec/msgspec/releases/tag/0.22.0

[11] за счет изменения логики : https://github.com/msgspec/msgspec/pull/1196

[12] такое сообытие в нашем сообществе: https://t.me/opensource_findings/985

[13] 92 задачи на GithHub: https://github.com/wemake-services/django-modern-rest/issues?q=is%3Aissue+state%3Aopen+label%3A%22opensource+september%22

[14] Ольге Пичужкиной: https://t.me/set_link_later

[15] Полный список изменений: https://github.com/wemake-services/django-modern-rest/releases#release-0.15.0

[16] Полный список изменений: https://github.com/wemake-services/django-modern-rest/releases#release-0.16.0

[17] на уровне FastAPI: https://github.com/wemake-services/django-modern-rest/tree/master/benchmarks#results

[18] для codex: https://github.com/pustota-theme/pustota.codex

[19] оригинал: https://github.com/pustota-theme/pustota

[20] Александру: https://github.com/kondratevdev

[21] https://github.com/skv0zsneg/django‑dto‑field: https://github.com/skv0zsneg/django-dto-field

[22] https://github.com/vsdudakov/yara‑orm: https://github.com/vsdudakov/yara-orm

[23] https://github.com/vsdudakov/fastadmin: https://github.com/vsdudakov/fastadmin

[24] https://github.com/vsdudakov/yara‑code: https://github.com/vsdudakov/yara-code

[25] https://github.com/Djarvur/go‑ultimate: https://github.com/Djarvur/go-ultimate

[26] https://github.com/deeray‑ltd/gigaam‑v3-runtime: https://github.com/deeray-ltd/gigaam-v3-runtime

[27] https://github.com/faststream‑community/zMQTT: https://github.com/faststream-community/zMQTT

[28] https://github.com/tochka‑public/bitcut: https://github.com/tochka-public/bitcut

[29] https://github.com/OlegEgoism/DB_STAT: https://github.com/OlegEgoism/DB_STAT

[30] https://github.com/deyna256/langchain‑skill‑router: https://github.com/deyna256/langchain-skill-router

[31] https://gitlab.com/asurnovsurnov/asynctoolspy: https://gitlab.com/asurnovsurnov/asynctoolspy

[32] https://github.com/prostoLavr/libvirtd‑tf‑infra: https://github.com/prostoLavr/libvirtd-tf-infra

[33] https://github.com/ovasendin/markdown_preview_editor: https://github.com/ovasendin/markdown_preview_editor

[34] в нашем чате: https://t.me/opensource_findings_chat/

[35] полный набор изменений для 2.4.0 тут: https://github.com/python/mypy/blob/master/CHANGELOG.md#mypy-24

[36] фиксами багов @ 1.8.1: https://github.com/wemake-services/wemake-python-styleguide/releases/tag/1.8.1

[37] 6.1.1: https://github.com/typeddjango/django-stubs/releases/tag/6.1.1

[38] 6.1.2: https://github.com/typeddjango/django-stubs/releases/tag/6.1.2

[39] вышел новый релиз 1.7.0: https://github.com/wemake-services/django-test-migrations/releases/tag/1.7.0

[40] в версии 0.9.0: https://github.com/bobthemighty/punq/releases/tag/v0.9.0

[41] Вышел новый 1.8.0 релиз: https://github.com/wemake-services/dump-env/releases/tag/1.8.0

[42] Съездил в Суздаль: https://t.me/magnittech/865

[43] Magnit Tech: https://www.pvsm.ru/company/magnit

[44] wps: https://github.com/wemake-services/wemake-python-styleguide

[45] к нашей большой встрече сообщества: https://itgorky.ru/bolshaya-vstrecha

[46] https://boosty.to/sobolevn: https://boosty.to/sobolevn

[47] https://github.com/sponsors/wemake‑services: https://github.com/sponsors/wemake-services

[48] главный канал: https://telegram.me/opensource_findings

[49] поучаствовать: https://telegram.me/opensource_findings_python

[50] Источник: https://habr.com/ru/articles/1091038/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1091038