Pendulum пришлось написать самый проклятый оператор + во всём Python

Why Pendulum had to write the most cursed "+" operator in all of Python

Pendulum, популярная библиотека для работы с датами, реализовала оператор + так, что он смотрит в стек вызовов, чтобы решить, какую арифметику применить. Это нужно для совместимости с datetime и корректной работы с переходом на летнее время. Автор библиотеки whenever объясняет, почему это решение было вынужденным, какие ошибки оно вызывает и как его можно исправить.

Ответ зависит от имени функции, которая его вызвала.
  1. shoo

    Ммм. Менять поток управления на основе интроспекции стека вызовов — довольно мерзко.

    Я вспоминаю, как мы нашли изящное применение интроспекции стека вызовов в одном проекте — не для изменения потока управления, а для улучшения логирования. Внутри служебной функции open_db_connection, чтобы автоматически генерировать информативное имя, описывающее, какая часть кодовой базы открыла соединение:

    Например: some_backend_process: main -> ... > grandparent -> parent -> open_db_connection

    Мы использовали информацию из стека вызовов, чтобы сгенерировать строку "some_backend_process grandparent.parent", описывающую место вызова, которую можно передать в postgres как application_name [1] при установлении соединения. Затем на стороне базы данных, если во время выполнения возникали проблемные запросы, у нас было гораздо больше подсказок, чтобы выяснить, какая часть бэкенд-кодовой базы за это отвечает [2].

    Был бы способ сделать что-то эквивалентное без подглядывания в стек вызовов, потребовав от вызывающего явно передавать описательное и уникальное имя, но это делает вещи немного более подверженными ошибкам, особенно потому что некоторые разработчики склонны копировать куски существующего кода и везде использовать одно и то же имя.

    [1] https://www.postgresql.org/docs/current/libpq-connect.html#L...

    [2] https://www.postgresql.org/docs/current/monitoring-stats.htm...

  2. jvolkman

    Я подниму ставку своим хаком, который меняет значение `sys.platform` в зависимости от вызывающего: https://github.com/jvolkman/rules_pycross/blob/main/pycross/...

    Это используется при кросс-компиляции бинарных wheel-пакетов (например, сборка wheel для macos на linux-хосте сборки или наоборот).

  3. ariebovenberg

    Автор здесь. Я наткнулся на это, сравнивая Pendulum с `whenever`, библиотекой для работы с датами и временем, которую я поддерживаю. Я отправил патч, который убирает этот хак, но пост о том, почему лежащий в основе дизайн нельзя исправить таким же образом. Готов ответить на вопросы.

Ещё за этот день

2026-10-07