Находки в опенсорсе: мир питона за август 2026. ai.. ai. Claude.. ai. Claude. django.. ai. Claude. django. github.. ai. Claude. django. github. opensource.. ai. Claude. django. github. opensource. python.. ai. Claude. django. github. opensource. python. python3.. ai. Claude. django. github. opensource. python. python3. агенты.. ai. Claude. django. github. opensource. python. python3. агенты. агенты ии.. ai. Claude. django. github. opensource. python. python3. агенты. агенты ии. Веб-разработка.. ai. Claude. django. github. opensource. python. python3. агенты. агенты ии. Веб-разработка. ИИ.. ai. Claude. django. github. opensource. python. python3. агенты. агенты ии. Веб-разработка. ИИ. Программирование.

Всем привет, вот и заканчивается лето :(

Мой прошлый дайджест неожиданным образом зашел, а значит – людям такое интересно. В августе было много новых интересных 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 будет очень сложно использовать.

В чем суть предложения?

  1. Главная идея PEP’а, что VM питона должна контролировать доступ к объектам из разных потоков. И контролировать корректность такого доступа. Чтобы такого добиться, предлагается добавить довольно много новых частей Python

  2. Как? Самое главное – добавить каждому объекту __shareable__ атрибут: Immutable – которые нельзя менять и можно шарить в рамках ThreadGroup, Local – существующие только в рамках одной ThreadGroup (можно смело мутировать), Protected – можно мутировать с мьютексом, Synchronized – специальный маркер для билтинов (им ненужна внешняя синхронизация, они умеют сами)

  3. Добавить threading.ThreadGroup объекты, по сути – группа тредов, которые вместе работают над какими-то общими данными. Что позволит упростить синхронизацию общих объектов для них

  4. Добавить функции для управления стейтом объектов: 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!

Что в новом релизе?

  1. Поддержка Python3.15 и запрещены lazy import конструкции

  2. Улучшена поддержка t строк, теперь мы считаем их сложность (как в f строках). Например, строка t'Hello, {user.profile.get_name()}' теперь будет запрещена, а t'Hello, {user}' – нет

  3. Добавлена поддержка ИИ: мы сделали скилл /wps для написания кода агентами так, чтобы агент сразу писал код с контекстом будущих проверок и не тратил лишние токены на исправления

  4. Добавили локальный MCP, теперь агент может сам его стартануть, может его спрашивать про коды ошибок, как их исправлять. Меньше токенов жжется!

Установка  в Claude

Пример установки плагина в Claude

Обсуждение: Пробовали ли вы использовать 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/rustyResult как в Rust, но только для питона

  • https://github.com/dshein-alt/serde – Библиотека для сериализации моделей на базе NamedTuple

  • https://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 к нам в чат.

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

Выводы

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

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

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

До встречи в сентябре!

Автор: sobolevn

Источник