Skip to content
Apothem
Архитектура

Стратегия внутреннего встраивания зависимостей

Какие сторонние пакеты Apothem встраивает внутрь под src/apothem/_vendor/, какие остаются системными предварительными требованиями и как обновляются внутренние копии.

Стратегия внутреннего встраивания зависимостей

Политика

Самодостаточная среда выполнения Apothem требует, чтобы сторонние зависимости движка были импортируемы из самого дерева исходников. Поэтому каждая зависимость времени выполнения обрабатывается одним из трёх способов:

  • Внутренне встроена как чистый исходный код Python под src/apothem/_vendor/. Bootstrap помещает этот каталог в начало sys.path, перед site-packages, так что внутренняя копия выигрывает гонку разрешения импортов у любой версии, установленной в системе.
  • Заменена шимом на чистом Python, когда вышестоящий дистрибутив включает скомпилированное расширение, которое не может путешествовать в виде переносимого исходного кода.
  • Сохранена как задокументированное системное предварительное требование, когда внутреннее встраивание несло бы больше поверхности, чем экономит.

Правило размещения строгое: только дистрибутивы на чистом Python живут в _vendor/. Скомпилированное расширение (C, Rust/PyO3, Cython) специфично для платформы и ABI и никогда там не место. Каждый внутренне встроенный пакет несёт свой вышестоящий файл лицензии рядом с исходным кодом.

Что встраивается внутрь

ПакетПримечания
yamlПарсер/эмиттер на чистом Python. Опциональное C-расширение libyaml — это ускорение, а не требование, и не переносится; импорты остаются import yaml.
jsonschemaВалидатор схем, используемый для валидации profile, конфигурации и golden-фикстур.
attrs (и его псевдоним attr)Требуется для jsonschema.
referencingТребуется для jsonschema.
jsonschema_specificationsТребуется для jsonschema.
rpdsШим на чистом Python, а не вышестоящий дистрибутив — см. ниже.
typing_extensionsТребуется внутренне встроенной цепочкой валидации.

Шим rpds

Вышестоящий jsonschema зависит от rpds-py — библиотеки персистентных структур данных, реализованной на Rust (PyO3), которая поставляет скомпилированный .pyd/.so лишь с тонкой обёрткой .py. Переносимого исходного кода на чистом Python для копирования нет, поэтому его нельзя встроить внутрь.

Вместо этого src/apothem/_vendor/rpds/ — это шим на чистом Python, который переопределяет ровно то подмножество API, которое задействуют jsonschema и referencingHashTrieMap, HashTrieSet и List — опираясь на встроенные типы dict / frozenset / tuple. Шим соблюдает вышестоящий контракт персистентности: мутирующие методы возвращают новый экземпляр и оставляют получателя без изменений, на что полагаются потребители, когда хранят эти структуры как значения полей по умолчанию у замороженных классов. Схемы Apothem малы, поэтому разница в производительности по сравнению с реализацией на Rust несущественна.

Что не встраивается внутрь

  • click — фреймворк CLI. Он большой, ориентирован на терминал и широко доступен, поэтому остаётся системным предварительным требованием, которое проверяют установщики.
  • rich — библиотека рендеринга терминала, сохранённая как системное предварительное требование по тем же причинам.
  • rpds-py — скомпилировано; заменено шимом выше.
  • C-расширение libyaml — опциональное; внутренне встроенный пакет yaml на чистом Python никогда его не требует.

Установщики проверяют, что click и rich импортируемы под выбранным интерпретатором, прежде чем делать что-либо; если одного из них не хватает, они называют его и предлагают установить его для вас — с вашим подтверждением или автоматически с --yes / APOTHEM_AUTO_INSTALL_DEPS=1.

Обновление внутренне встроенного пакета

Чтобы обновить внутренне встроенный пакет до более новой вышестоящей версии:

  1. Получите вышестоящий дистрибутив исходного кода целевой версии.
  2. Скопируйте каталог пакета на чистом Python в src/apothem/_vendor/, заменив предыдущую копию, и обновите соседний файл лицензии.
  3. Обновите src/apothem/_vendor/vendor.txt — закреплённое замыкание — так, чтобы его строка name==version для пакета соответствовала новой вышестоящей версии, и обновите блок [[annotations]] пакета в корневом REUSE.toml, если его вышестоящая лицензия или авторское право изменились. Оба обязательны в том же наборе изменений, что и копирование (мандат живых зависимостей); аудиторы цепочки поставок и гейт reuse lint их читают.
  4. Оставьте пути импорта нетронутыми — потребители импортируют канонические имена, а приоритет sys.path у bootstrap делает остальное.
  5. Запустите набор тестов и гейт соответствия; поведение стека валидации покрыто тестами валидации profile и схемы.

Шим rpds обновляется иначе: он отслеживает подмножество API, которое используют его потребители, поэтому обновление jsonschema/referencing проверяется по отношению к реализованной поверхности шима, и шим растёт только тогда, когда появляется новая точка вызова.

Рекомендуемый следующий шаг

Прочтите страницу самодостаточной среды выполнения, чтобы узнать, как внутренне встроенное дерево, модель вызова PYTHONPATH=src и bootstrap дерева плагина сочетаются во время выполнения.

On this page