Всем привет, вот и заканчивается лето :(
Мой прошлый дайджест неожиданным образом зашел, а значит - людям такое интересно. В августе было много новых интересных PEP’ов (например, PEP 805: Safe Parallel Python), которые я поревьюил, было много новых релизов, было много новых опенсорс проектов чуваков из нашего сообщества, пару интересных подкастов и множество другого интересного!
С меня как всегда статья без нейрослопа и ИИ, с вас как всегда интересные комментарии и лайки! Но немного нейрослопа я все же добавил в некоторые свои проекты. Но осторожно и с пользой для всех.
Погнали смотреть, что у нас в питоне происходило!
CPython
После долгих споров и обсуждений про наш PEP-841 и синтаксис f{1: 2} для frozendict, я решил сделать небольшую паузу от питона. В опенсорсе важно уметь переключать свое внимение, чтобы не ловить усталось и выгорание.
Потому, единственное, чем я занимался в CPython: ревью и обсуждение PEPов.
PEP 805
Я хочу показать самый интересный из них: PEP 805: Safe Parallel Python. Марк Шенон предлагает сделать ОЧЕНЬ много всего для того, чтобы Free-Threading в CPython наконец начал нормально работать. Он буквально пишет: если мы оставим все как есть сейчас, то Free-Threading будет очень сложно использовать.
В чем суть предложения?
Главная идея PEP’а, что VM питона должна контролировать доступ к объектам из разных потоков. И контролировать корректность такого доступа. Чтобы такого добиться, предлагается добавить довольно много новых частей Python
Как? Самое главное - добавить каждому объекту
__shareable__атрибут: Immutable - которые нельзя менять и можно шарить в рамкахThreadGroup, Local - существующие только в рамках однойThreadGroup(можно смело мутировать), Protected - можно мутировать с мьютексом, Synchronized - специальный маркер для билтинов (им ненужна внешняя синхронизация, они умеют сами)Добавить
threading.ThreadGroupобъекты, по сути - группа тредов, которые вместе работают над какими-то общими данными. Что позволит упростить синхронизацию общих объектов для нихДобавить функции для управления стейтом объектов:
freeze(),syncronize()
Пример:
class State: def __init__(self, value): self.value = value class Counter: def __init__(self): self.mutex = Lock() with self.mutex: self.number = self.mutex.protect(State(0)) self.__freeze__() def value(self): with self.mutex: return self.number.value def increment(self): with self.mutex: self.number.value += 1
Как оно работает? Да ктож его знает ?️️
И хоть я оставил всего два мелких замечания, было очень интересно почитать. Скажу честно, что сесть и проанализировать каждый нюанс предложения у меня не было ни времени, ни сил. Но у нас в сообществе есть замечательный @zzzzzzerg, который уделил ПЕПу куда больше внимания. Очень жду его развернутого мнения в комментариях под данной статьей.
Обсуждение: Что вы думаете про PEP-805? Сложно? Или наоборот?
Самый короткий crash в питоне
Попробуйте запустить такое в Python 3.14.0:
__conditional_annotations__ = 0 a: 1
Все упадет. Не с исключением, а с core-dumped. Почему?
Когда в CPython добавляли поддержку ленивых аннотаций в PEP-649, то нужно было как-то поддержать такой код:
>>> import dis >>> dis.dis(''' ... if int(): ... x: int = 0 ... else: ... x: str = '' ... ''') -- MAKE_CELL 0 (__conditional_annotations__) 0 RESUME 0 2 LOAD_CONST 1 (<code object __annotate__ at 0x10cfe2710, file "<dis>", line 2>) MAKE_FUNCTION STORE_NAME 3 (__annotate__) BUILD_SET 0 STORE_NAME 0 (__conditional_annotations__) LOAD_NAME 1 (int) PUSH_NULL CALL 0 TO_BOOL POP_JUMP_IF_FALSE 9 (to L1) NOT_TAKEN 3 LOAD_SMALL_INT 0 STORE_NAME 2 (x) LOAD_NAME 0 (__conditional_annotations__) LOAD_SMALL_INT 0 SET_ADD 1 POP_TOP LOAD_COMMON_CONSTANT 7 (None) RETURN_VALUE 5 L1: LOAD_COMMON_CONSTANT 8 ('') STORE_NAME 2 (x) LOAD_NAME 0 (__conditional_annotations__) LOAD_SMALL_INT 1 SET_ADD 1 POP_TOP LOAD_COMMON_CONSTANT 7 (None) RETURN_VALUE Disassembly of <code object __annotate__ at 0x10cfe2710, file "<dis>", line 2>: 2 RESUME 0 LOAD_FAST_BORROW 0 (format) LOAD_SMALL_INT 2 COMPARE_OP 132 (>) POP_JUMP_IF_FALSE 3 (to L1) NOT_TAKEN LOAD_COMMON_CONSTANT 1 (NotImplementedError) RAISE_VARARGS 1 L1: BUILD_MAP 0 3 LOAD_SMALL_INT 0 LOAD_GLOBAL 0 (__conditional_annotations__) CONTAINS_OP 0 (in) POP_JUMP_IF_FALSE 10 (to L2) NOT_TAKEN LOAD_GLOBAL 2 (int) COPY 2 LOAD_CONST 1 ('x') 2 STORE_SUBSCR 5 L2: LOAD_SMALL_INT 1 LOAD_GLOBAL 0 (__conditional_annotations__) CONTAINS_OP 0 (in) POP_JUMP_IF_FALSE 10 (to L3) NOT_TAKEN LOAD_GLOBAL 4 (str) COPY 2 LOAD_CONST 1 ('x') 2 STORE_SUBSCR L3: RETURN_VALUE
Вот такая сложная машинерия для простого резолвинга аннотаций получается. Что тут происходит? Здесь мы определяем, как будет создаваться байткод для резолва аннотации:
3 LOAD_SMALL_INT 0 LOAD_GLOBAL 0 (__conditional_annotations__) CONTAINS_OP 0 (in) POP_JUMP_IF_FALSE 10 (to L2) NOT_TAKEN LOAD_GLOBAL 2 (int) COPY 2 LOAD_CONST 1 ('x')
{'x': int} если if int() будет True,
5 L2: LOAD_SMALL_INT 1 LOAD_GLOBAL 0 (__conditional_annotations__) CONTAINS_OP 0 (in) POP_JUMP_IF_FALSE 10 (to L3) NOT_TAKEN LOAD_GLOBAL 4 (str) COPY 2 LOAD_CONST 1 ('x')
и {'x': str} если False. Проверим на чуть другом примере:
>>> if int(): ... x: int = 0 ... else: ... x: str = '' ... >>> __annotate__(1) {'x': <class 'str'>}
и
>>> if int() == 0: ... x: int = 0 ... else: ... x: str = '' ... >>> __annotate__(1) {'x': <class 'int'>}
Я проревьюил фикс, очень забавно получилось!
Обсуждение: Знали ли вы про __conditional_annotations__? Не кажется ли вам, что такая фича - уже прям сильно сложно?
А еще поговорили про CPython и его будущее в подкасте у Монтаны:
wemake-python-styleguide
Лучший тул для качества кода на питоне: для вас и ваших агентов!
Выпустил wemake-python-styleguide@1.8.0!
Что в новом релизе?
Поддержка Python3.15 и запрещены
lazy importконструкцииУлучшена поддержка
tстрок, теперь мы считаем их сложность (как вfстроках). Например, строкаt'Hello, {user.profile.get_name()}'теперь будет запрещена, аt'Hello, {user}'- нетДобавлена поддержка ИИ: мы сделали скилл
/wpsдля написания кода агентами так, чтобы агент сразу писал код с контекстом будущих проверок и не тратил лишние токены на исправленияДобавили локальный MCP, теперь агент может сам его стартануть, может его спрашивать про коды ошибок, как их исправлять. Меньше токенов жжется!

Обсуждение: Пробовали ли вы использовать wemake-python-styleguide с агентами? Довольны ли вы результатом?
Немного стыдного нейрослопа
Как и обещал в начале статьи.
Пока я делал MCP и прочее, мне конечно требовалось поставить агент локально. А как его можно безопасно локально запустить? А никак! Пришлось костылить запуск агента в докере:
claude () { # How it works: # 1. First run: the native installer drops the binary into ~/.local # (volume `claude-bin`), then you go through the normal login / # onboarding flow in the CLI. # 2. Everything Claude Code writes — auth, settings, .claude.json, # session history, memory — lands in `claude-settings`, because # CLAUDE_CONFIG_DIR redirects all of it there. # 3. Later runs: binary and config are already in the volumes, so no # reinstall and no re-auth. `claude update` inside the container # also persists, since it writes to ~/.local/share/claude. # 4. The project is mounted at its host path (not /workspace), so # each repo keeps its own per-project sessions and memory. local project="$(readlink -f '.')" local image='buildpack-deps:bookworm-scm' # has curl, git, bash docker run -it --rm \ -e CLAUDE_CONFIG_DIR=/claude-config \ -e PATH="/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \ -v claude-settings:/claude-config \ -v claude-bin:/root/.local \ -v "$project":"$project" \ -w "$project" \ "$image" \ bash -c ' if [ ! -x "$HOME/.local/bin/claude" ]; then curl -fsSL https://claude.ai/install.sh | bash fi exec claude "$@" ' _ "$@" }
Можно посмотреть все мои дотфайлы: https://github.com/sobolevn/dotfiles Там много полезного.
Обсуждение: А как вы запускаете агентов локально? Что еще можно обезопасить?
Кстати про нейрослоп. Провели стрим с @Propan671, пытались решить задачки из django-modern-rest полностью при помощи агентов. Только вайбкодом. И очень сложные. И security-related.
Получилось ли? Посмотрите стрим или прочитайте итоговый пост!
django-modern-rest
Выпустили релиз django-modern-rest@0.14.0!
Что добавили?
Официальную поддержку нового тайпчекера
tyДобавили полезностей для
Router, теперь можно включатьRouterвurlpatternsпросто какrouter.to_urlpatterns(), сильно меньше кодаДобавили поддержку
@validateдля создания переиспользуемых контроллеров
Сейчас работаем над релизом 0.15.0, там будет очень много изменений. А еще завтра начнется событие в нашем сообществе: #opensource_september, следить за ним можно будет у меня в тг.
А еще я записал подкаст про django-modern-rest с уважаемым @PyLounge
Обсуждение: Появилось желание попробовать после подкаста?
django-stubs
Выпустили django-stubs@6.1.0! Релиз с поддержкой django@6.1.
А еще мы теперь поддерживаем pyrefly и ty в качестве официальных тайпчекеров. Конечно, силы плагинов mypy там нет, но базовые вещи - работают. Мы теперь гоняем тесты и проверяем.
Обсуждение: а каким тайпчекером пользуетесь вы?
Проекты сообщества
https://github.com/dshein-alt/rusty -
Resultкак вRust, но только для питонаhttps://github.com/dshein-alt/serde - Библиотека для сериализации моделей на базе
NamedTuplehttps://github.com/dshein-alt/ropds - Быстрый и лёгкий сервер персональной электронной библиотеки с каталогом OPDS 1.2 / 2.0 и веб-интерфейсом.
https://github.com/th0r3nt/JAWL (Just A While Loop) - ИИ-фреймворк для автономных ИИ-агентов через ReAct-циклы.
https://github.com/fomenko-ai/pytest-hardware-template - шаблон автоматизации тестирования оборудования на основе pytest. Основная идея - сделать как можно более общий универсальный шаблон и развивать его как библиотеку, адаптируя будущие обновления шаблона во внутренние проекты компании с помощью AI скиллов.
https://github.com/brilliance-admin/backend-python - админ панели на vue под sqlalchemy/django/любой источник данных с backend
https://github.com/goduni/unissh - современный, опенсорсный SSH клиент с selfhosted zero-knowledge сервером для синхронизации данных
https://github.com/kap-sh/capo - нормальный Python SDK для Amazon, поверх zapros, вместо ужасного
boto. Про него на канале вышел постhttps://github.com/pomponchik/incontext - плагин для Hermes agent, который делает переменную max_tokens динамической, зависящей от остатка эффективного контекстного окна (т.е. с учетом запаса на сжатие)
https://github.com/rtugov/agentcontext - В общем история такая - неделю назад угорел по ИИшкам и локальным инференсам. В итоге понял что нет тулинга чтобы посмотреть контекст того же codex в риалтайме. В итоге я сделал свой proxy который встает между codex, claude, opencode, pi, etc. и просто показывает контекст запуска по шагам
https://github.com/mutating/skelet - Работа с несколькими источниками конфига, в разных форматах (в т.ч. перечисленные переменные окружения, YAML-файлы и другие), типизация (как на рантайме, так и в статик тайп чек тайме), и работа с секретами
https://github.com/pomponchik/autofission - По сути управляет одной настройкой - MaxScale в кластере Куба при использовании lambda функций. Теперь она не хардкодится, а определяется по реальной загрузке кластера, которая информация о которой регулярно обновляется
https://github.com/OlegYurchik/metaorm - Асинхронный слой работы с БД поверх SQLModel
https://github.com/Khabib73/open-source-playbook - Гайд для корректно, вежливого и продуктивного общения в опенсорсе. Многим бы пригодилось!
Хотите оказаться в списке? Пишите про свой проект с тегом #opensource к нам в чат.
Одной строкой
Сделали папку со всеми крутыми телеграм каналами все нагих чуваков из сообщества. Очень много годноты! Подпишитесь, если интересно читать про питон с разных сторон
Горячо обсуждали у меня в канале пост про то, что
uv- такая себе технология. Хайпа было много, а толку не очень.JIT могут удалить из CPython. Вот тут хроника истории
У нашего товарища Amazon отжал имена пакетов на PyPI
Починил поддержку старых версий Django в
pytest-djangoВышел returns@0.29.0 с поддержкой новых версий mypy и несколькими фиксами багов
Правил баги, ревьил PRы и не давал нейрослопу попасть внутрь
litestar
Выводы
А если вы думаете, что я делаю что-то полезное для мира, то поддержать можно по ссылкам:
Я там ничего не продаю, просто делаю свою работу, если считаете, что я делаю полезное - можно поддержать. Если нет, то я все равно продолжу ее делать.
Подписывайтесь на главный канал сообщества, если вам нравится такое читать. И возможно даже захочется поучаствовать! Буду рад видеть вас частью нашего опенсорс сообщеста :)
До встречи в сентябре!
PyLounge
Братан, хорош, давай, давай, вперёд! Контент в кайф, можно ещё? Вообще красавчик! Можно вот этого вот почаще?