PyCall
Обёртки над libpython (аналог LibPython::Helpers + LibPython::API в гемме).
Constants
Глобальная блокировка на ВЕСЬ доступ к Python из Crystal.
CPython GIL (PyGILState_Ensure/Release) защищает отдельные C-вызовы, но составные операции (getattr → call → convert, обход dict и т.п.) без неё могли чередоваться между фиберами на разных тредах. Этот мьютекс сериализует операции целиком — один глобальный замок на весь шард, как require GVL в MRI.
Вложенные вызовы PyCall.gil на том же треде идут по быстрому пути: если тред уже держит GIL (внешний захват или трамплин колбэка), повторный захват мьютекса не выполняется — иначе нереентерабельный Mutex дал бы дедлок. Порядок проверок критичен: колбэк из Python (трамплин) держит GIL, НЕ держит мьютекс — и не должен его брать, пока другой тред ждёт GIL под мьютексом.
Class methods
Обёртка Proc → python callable (см. PyCall::Callable).
Примитивы (конвертированные из Python) не-callable по определению.
Взять GIL на блок (PyGILState_Ensure/Release) под глобальным мьютексом. Реентерабелен на том же треде (см. комментарий у MUTEX).
Инициализация интерпретатора — PyCall.init в гемме. Идемпотентна; вызывается автоматически при первом обращении к API.