Python client for ATOL libfptr10 fiscal printer driver
Project description
ORD — Python-клиент драйвера АТОЛ libfptr10
Тонкая обёртка над libfptr10 (драйвер ККТ АТОЛ v10.10.x) для типовых
кассовых сценариев: открытие/закрытие смены, регистрация чека продажи и
возврата, чтение состояния ФН и ОФД-обмена, регистрация ККТ, чтение и
запись device settings.
Используется в backend-проекте online-receipt/online-api (Flask + Celery)
для фискализации чеков на физических кассах АТОЛ 30Ф, ATOL Sigma и
совместимых моделях.
- Текущая версия:
1.12.0 - PyPI:
pip install ORD - Источник истины: GitLab
online-receipt/online-receipt-driver(этот репо) - Зеркало: GitHub
brandshopru/online-receipt-driver - Стек: Python 3.6+,
libfptr10>=10.10.0 - Лицензия: проприетарная, ООО «БШ СТОР» (brandshop.ru)
1. Установка
pip install ORD==1.12.0
Зависимость от libfptr10 (Python wrapper) ставится отдельно из дистрибутива
АТОЛ kit (fptr10-rpc-server*.deb + wrappers/python/libfptr10.py).
Минимальные системные требования:
- Python >=3.6 (3.6 в EOL, рекомендуется 3.8+)
libfptr10.sov10.10.x в/lib64/илиLD_LIBRARY_PATH- USB-устройство ATOL (
Vendor:Product 2912:0005) либо TCP/IP подключение - При работе через
atol-grpc-service— gRPC мост на127.0.0.1:4041/:4042
2. Архитектура
2.1. Структура
ORD/
├── __init__.py # public-экспорт классов
├── ord_core.py # Core (Singleton, IFptr wrapper)
├── ord_cash.py # Cash (state ККТ, регистрация)
├── ord_fn.py # Fn (ФН-операции, ОФД-обмен)
├── ord_receipt.py # Receipt (чек: open/registration/payment/close)
├── ord_shift.py # Shift (open/close смены)
├── ord_setting.py # Setting (device settings R/W)
└── exceptions.py # OrdError, OrdTimeoutError (§6.8 + §6.9, c 1.11.0)
2.2. Класс Core (Singleton)
Core — единая точка инициализации IFptr. Реализован как Singleton через
метакласс SingletonMeta с потокобезопасным threading.Lock. На процесс
гарантированно один экземпляр.
Дефолтные settings при Core():
| Параметр libfptr10 | Значение |
|---|---|
LIBFPTR_SETTING_MODEL |
LIBFPTR_MODEL_ATOL_AUTO (автоопределение) |
LIBFPTR_SETTING_PORT |
LIBFPTR_PORT_USB |
LIBFPTR_SETTING_USB_DEVICE_PATH |
"auto" |
LIBFPTR_SETTING_OFD_CHANNEL |
LIBFPTR_OFD_CHANNEL_AUTO |
LIBFPTR_SETTING_AUTO_TIME_SYNC |
True |
LIBFPTR_SETTING_AUTO_TIME_SYNC_TIME |
15 (секунд) |
Instance-level state Core.casher_info (c 1.10.0):
core = Core(path="", casher_name="Иванов И.И.", casher_inn="500100732259")
# или сменить runtime:
core.set_casher("Петров П.П.", inn="...")
Используется в _set_casher() перед каждой фискальной операцией
(setParam(1021, name), setParam(1203, inn), operatorLogin()). Если
casher_name пуст — operatorLogin пропускается (logon оператора
не происходит, чек/смена пишутся без тегов 1021/1203).
Жизненный цикл соединения:
__init__создаётIFptrinstance, читает версию, применяет settingsopen_connect()→fptr.open()— реальный коннект к ККТclose_connect()→fptr.close()__del__авто-закрывает еслиis_opened() == 1
2.3. Доменные классы
Cash, Fn, Receipt, Shift, Setting — потребители Core. Все принимают
один Core-экземпляр в конструктор и сохраняют self.fptr = core.fptr. Если
соединение закрыто, конструктор автоматически вызывает core.open_connect().
from ORD.ord_core import Core
from ORD.ord_receipt import Receipt
from ORD.ord_fn import Fn
core = Core() # Singleton
core.open_connect()
fn = Fn(core)
receipt = Receipt(core)
# ...
core.close_connect()
3. Типовой жизненный цикл чека
Псевдокод реального флоу из online-api/jobs/handlers.py:
core = Core()
core.open_connect()
# 1. Открыть смену (необязательно — первая фискальная операция откроет автоматически)
Shift(core).open_shift()
# 2. Открыть чек
receipt = Receipt(core)
receipt.open_receipt({
"docType": "SALE", # или "RETURN"
"printReceipt": False, # электронный
"email": "client@example.com",
"taxMode": "OSN", # OSN / USN_INCOME / ...
})
# 3. Регистрация каждой позиции
receipt.receipt_registration({
"name": "Кроссовки Nike",
"price": 10000,
"quantity": "1",
"vatTag": 1102, # 1102 — Сумма НДС по ставке 20%
"vat": 22, # ставка 22 → LIBFPTR_TAX_VAT22
"discSum": 0,
"nomenclatureCode": "0104680001234567...", # КМ Data Matrix, опционально
"codeCheck": "UUID=...&Time=...", # результат ПИоТ-проверки, опционально
})
# 4. Оплата
receipt.receipt_payment({"paymentType": "CARD", "sum": 10000})
# paymentType резолвится через Receipt.payment_type → LIBFPTR_PT_* (с 1.8.26.1)
# 5. Закрытие чека → ФН → ОФД
receipt.receipt_close()
# 6. Получить фискальные реквизиты
last = Fn(core).get_info_last_doc()
# → {"document_number": 123, "fiscal_sign": "1234567890", "date_time": "..."}
Закрытие смены (Z-отчёт): Shift(core).close_shift().
4. API Reference
4.1. Core
| Метод | Возврат | Назначение |
|---|---|---|
Core(path: str = '') |
— | Singleton-инициализация IFptr с дефолтными settings |
open_connect() |
bool |
fptr.open() — коннект к ККТ |
close_connect() |
bool |
fptr.close() |
is_opened() |
int |
0/1, см. §5.1 — не отражает реальное состояние |
get_version_driver() |
str |
версия libfptr10 |
get_current_datetime() |
str |
"%Y-%m-%d %H:%M:%S" от ККТ |
get_setting() |
dict |
текущие device settings |
reboot() |
bool |
fptr.deviceReboot() |
_set_casher() |
bool |
оператор тег 1021 + 1203 + operatorLogin() (приватный) |
_check_document_close() |
bool |
проверка checkDocumentClosed, допечатка (приватный) |
_error_log() |
— | пишет errorCode + errorDescription в журнал libfptr10 |
info_log(msg: str) |
— | пишет INFO в журнал libfptr10 |
4.2. Cash
| Метод | Возврат | Назначение |
|---|---|---|
Cash(core) |
— | Конструктор; авто-open_connect если закрыто |
get_cash_info() |
dict |
13 полей: модель, ФН, версия прошивки, состояние смены, ФФД |
get_cash_info_v2() |
dict |
31 поле: всё из v1 + флаги принтера/бумаги/ФН/блокировок |
get_uptime_cash() |
int |
секунды непрерывной работы ККТ |
cash_registration() |
bool |
Регистрация ККТ (МГМ). Хардкод реквизитов brandshop, см. §5.2 |
shift_stage mapping: 0→CLOSED, 1→OPENED, 2→EXPIRED.
4.3. Fn
| Метод | Возврат | Назначение |
|---|---|---|
Fn(core) |
— | Конструктор |
get_status_fn() |
str |
FNS_INITIAL/CONFIGURED/FISCAL_MODE/POSTFISCAL_MODE/ACCESS_ARCHIVE |
get_info_last_receipt() |
dict |
номер, тип, сумма, ФПД, datetime последнего чека |
get_info_last_doc() |
dict |
то же для последнего фискального документа |
get_version_ffd() |
dict |
device/fn/min/max версии ФФД (есть баг ключа, см. §5.8) |
get_info_doc(number_doc) |
dict |
тип, номер, ФПД, datetime, has_ofd_ticket для номера ФД |
get_ticket_ofd(number_doc) |
dict |
номер, datetime, OFD ФПД (bytearray) квитанции от ОФД |
get_ofd_document_by_number(n) |
list[dict] |
TLV-структуры ФД (tag_number, tag_name, tag_type, tag_value) |
get_fn_error() |
dict |
network / ofd / fn ошибки и их тексты |
get_exchange_status() |
dict |
статус ОФД-обмена, кол-во неотправленных |
get_registration_number() |
str |
РНМ ККТ (тег 1037) |
4.4. Receipt
| Метод | Возврат | Назначение |
|---|---|---|
Receipt(core) |
— | Конструктор |
open_receipt(receipt_data) |
bool |
Открытие чека (см. ниже) |
cancel_receipt() |
bool |
fptr.cancelReceipt() — отмена незакрытого чека |
receipt_registration(product) |
bool |
Регистрация одной позиции |
receipt_payment(money_position) |
bool |
Оплата (paymentType через Receipt.payment_type) |
receipt_total(money_position) |
bool |
Регистрация итога (необязательно) |
receipt_close() |
bool |
fptr.closeReceipt() → запись в ФН |
open_receipt(receipt_data) ожидает:
| Ключ | Тип | Значения |
|---|---|---|
docType |
str | см. Receipt.receipt_type: SALE/RETURN, SALE_CORRECTION/RETURN_CORRECTION, BUY/BUY_RETURN, BUY_CORRECTION/BUY_RETURN_CORRECTION |
printReceipt |
bool | False → electronic чек (LIBFPTR_PARAM_RECEIPT_ELECTRONICALLY=True) |
email |
str | тег 1008 — email клиента |
taxMode |
str | OSN/USN_INCOME/USN_INCOME_OUTCOME/ESN/PATENT |
Жёстко устанавливается тег 1125=1 («признак расчёта в интернете») — это
hard-coded для интернет-магазина brandshop.
receipt_registration(product) ожидает:
| Ключ | Тип | Назначение |
|---|---|---|
name |
str | LIBFPTR_PARAM_COMMODITY_NAME |
price |
int/float | LIBFPTR_PARAM_PRICE |
quantity |
str | LIBFPTR_PARAM_QUANTITY |
vat |
int | см. Receipt.vat_type: 0/5/7/10/20/22 + расчётные 5/105, 7/107, 10/110, 20/120, 22/122 + "NO" (без НДС) |
discSum |
int | LIBFPTR_PARAM_INFO_DISCOUNT_SUM (если > 0) |
nomenclatureCode |
str / None | КМ Data Matrix; запускает beginMarkingCodeValidation + polling + acceptMarkingCode |
codeCheck |
str / None | tag 1265 от ПИоТ; собирает TLV-тег 1260 (отраслевой реквизит предмета расчёта) |
vatTag |
int | поле в payload, но не используется в коде |
Цепочка libfptr10 для маркированного товара (упрощённо):
setParam(MARKING_CODE, km)
setParam(MARKING_CODE_STATUS, 2)
setParam(MARKING_PROCESSING_MODE, 0)
setParam(MEASUREMENT_UNIT, IU_PIECE)
beginMarkingCodeValidation()
while not getParamBool(MARKING_CODE_VALIDATION_READY):
getMarkingCodeValidationStatus()
validation_result = getParamInt(MARKING_CODE_ONLINE_VALIDATION_RESULT)
acceptMarkingCode()
# Если есть codeCheck (tag 1265 от ПИоТ) — формируется TLV-тег 1260.
# С 1.10.0 значения 1262/1263/1264 параметризованы через product['industry']:
setParam(1262, industry['mode']) # режим обработки (например, '030')
setParam(1263, industry['date']) # дата НПА (например, '21.11.2023')
setParam(1264, industry['num']) # номер НПА (например, '1944')
setParam(1265, codeCheck)
utilFormTlv() → tag 1260 TLV
setParam(1260, tlv)
setParam(1212, 33) # признак предмета расчёта: маркированный товар + услуга
4.5. Shift
| Метод | Возврат | Назначение |
|---|---|---|
Shift(core) |
— | Конструктор |
open_shift() |
bool |
_set_casher() → fptr.openShift() → проверка закрытия |
close_shift() |
bool |
_set_casher() → report(LIBFPTR_RT_CLOSE_SHIFT) → Z-отчёт |
4.6. Setting
| Метод | Возврат | Назначение |
|---|---|---|
Setting(core) |
— | Конструктор (composition, не наследуется от Core) |
init_setting() |
bool |
fptr.initSettings() |
get_device_setting_by_id(id, type) |
bool/int/str |
Чтение настройки ККТ (type ∈ int/string) |
set_device_setting_by_id(id, value) |
bool |
Запись настройки |
commit_setting() |
bool |
fptr.commitSettings() |
5. Известные ограничения и hidden behavior
5.1. Core.is_opened() не отражает реальное состояние
Из docstring: «Результат метода не отражает текущее состояние подключения —
если с ККТ была разорвана связь, то метод всё также будет возвращать true».
Это особенность libfptr10.isOpened() — она проверяет только локальный флаг
сессии. Реально упало соединение или нет — узнаётся только на первом
вызове, который вернёт LIBFPTR_ERROR_NO_CONNECTION.
5.2. Хардкод бизнес-данных — устранён в 1.9.0 и 1.10.0
Раньше в коде были захардкожены бизнес-значения:
Cash.cash_registration()— ИНН/адрес/ОФД brandshop. Параметризовано в 1.9.0 (registration_data: dict).Receipt.receipt_registration()для маркированных товаров — теги 1262/1263/1264 ='030' / '21.11.2023' / '1944'. Параметризовано в 1.10.0 (полеindustryв payload позиции).Core.casher_infoclass-level"СИС. АДМИНИСТРАТОР". Параметризовано в 1.10.0:Core(casher_name, casher_inn)+Core.set_casher(name, inn). Дефолт пустой →_set_casher()пропускаетoperatorLogin.
5.3. Setting наследуется от Core — исправлено в 1.10.0
Setting наследуется от CoreРаньше class Setting(Core) + одновременно self.core = core — двойственная связь, бьётся с SingletonMeta. С 1.10.0 — чистая композиция: class Setting: с делегированием логирования через self.core._error_log(). См. §6.6.
5.4. cash_registration пишет в FN
Метод реально вызывает fptr.fnOperation() с LIBFPTR_FNOP_REGISTRATION —
это необратимая операция перерегистрации ФН. Использовать только для
первоначальной активации новой ККТ или замены ФН, никогда не дёргать в
тестах. Логирования предупреждения нет.
5.5. casher_info class-level
Реквизиты кассира (name, inn) — это class-level переменная Core,
а не instance. Это значит, что изменение из одного места приложения
повлияет на все будущие вызовы _set_casher(). Для multi-tenant сценариев
(несколько касс в одном процессе) — баг.
5.6. Молчаливая обработка ошибок
Все методы возвращают False при ошибке libfptr10 и пишут описание через
logWrite. Никаких исключений. Это удобно для batch-обработки чеков, но
затрудняет отладку — приходится парсить логи libfptr10 (/var/log/...) и
коррелировать с приложением. См. §6.8.
5.7. _check_document_close infinite loop
Цикл while self.fptr.checkDocumentClosed() < 0: ... без timeout. Если ККТ
отвалилась (LIBFPTR_ERROR_NO_CONNECTION) — поток зависнет навсегда.
Аналогично для while self.fptr.continuePrint() < 0. См. §6.9.
5.8. get_version_ffd баг ключа
В строке 334 ord_fn.py:
version_ffd.update({"document_number": self.ffd_version.get(min_ffd_version)})
Ключ должен быть "min_ffd_version", а не "document_number". Опечатка
скрывает значение min_ffd_version в возвращаемом dict.
6. Задачи на доработку (TODO)
Сделанные задачи:
- ✅ §6.1 paymentType маппинг — в
1.8.26.1(Receipt.payment_typedict) - ✅ §6.2 VAT mapping — в
1.8.27.0(Receipt.vat_typedict, 0/5/7/10/20/22 + расчётные + NO) - ✅ §6.3 docType коррекции и расход — в
1.8.27.0(Receipt.receipt_typedict с 8 типами) - ✅ §6.4 Cash.cash_registration параметризация — в
1.9.0. Принимаетregistration_data: dict(inn/address/org_name/email/place/reg_number/ofd_inn/ofd_name + tax_system/agent_type/ffd_version/tax_site/flags). Breaking change: дефолтов brandshop больше нет, ValueError при отсутствии обязательных полей. - ✅ §6.5 Параметризация отраслевого реквизита (тег 1260) — в
1.10.0.Receipt.receipt_registrationпринимает полеindustry({mode, date, num}для тегов 1262/1263/1264). Breaking change: при наличииcodeCheckблокindustryобязателен, иначе ValueError. - ✅ §6.6
Setting(Core)→Setting— в1.10.0. Убрано наследование от Core, теперь composition (self.core._error_log()), убран__del__(Setting не владеет соединением). - ✅ §6.7
casher_infoinstance-level — в1.10.0.Core(path, casher_name='', casher_inn='')+ методCore.set_casher(name, inn=''). Класс-атрибут с brandshop-хардкодом удалён. Backward-compat: при пустомcasher_nameметод_set_casherпропускаетoperatorLogin(фискальные операции работают без logon оператора). - ✅ §6.8 Опциональные исключения — в
1.11.0.Core(..., raise_on_error=True)поднимаетOrdError(code, description, method)вместо тихогоreturn False. HelperCore._handle_error(method)объединяет log + raise/return. Дефолтraise_on_error=False— backward compatible. - ✅ §6.9 Timeout в
_check_document_close— в1.11.0. Бесконечныеwhile ... < 0: continueзаменены на deadline-loop с параметромtimeout: float = 30.0. При превышении —OrdTimeoutError(всегда, независимо отraise_on_error). - ✅ §6.10 Тесты — в
1.11.0. Структураtests/unit/*.pyс 17 unit-тестами (Core/Receipt/Cash, ~70% покрытия публичного API).libfptr10.IFptrподменяется MagicMock'ом в conftest.py — тесты идут без реальной кассы. Dev-зависимости вrequirements-dev.txt. Integration-тесты против реальной АТОЛ 30Ф — отдельным этапом. - ✅ §6.11
pyproject.toml— в1.12.0. Перевели проект на PEP 517 build (setuptools.build_meta).setup.py+setup.cfgудалены, метаданные вpyproject.toml. Сборка черезpython -m build. - ✅ §6.12 Type hints (частично) — в
1.12.0. Добавленыreturn-аннотации публичным методам Core/Cash/Fn/Receipt/Shift/Setting и type hints параметров.TypedDictдля CashInfo/FnDocInfo — не делали (низкий приоритет, оставляемdict). - ✅ §6.16 Контекст-менеджеры — в
1.12.0.Core.__enter__/__exit__—with Core(...) as core:гарантируетclose_connect()даже при exception между open и close. - ✅ §6.17 Thread-safety — в
1.12.0. Документировано «один процесс, один поток» как требование. ДобавленCore._operation_lock = threading.Lock()для опционального оборачивания критической секции извне:with core._operation_lock: .... Каждый публичный метод НЕ оборачивается мьютексом, чтобы не платить за однопоточные сценарии. - ✅ §6.18 AutoTimeSyncTime — в
1.12.0.LIBFPTR_SETTING_AUTO_TIME_SYNC_TIME = 3600(раз в час, было 15с). Компромисс между «реже трогаем ФН» и «успеваем поймать drift». - ✅ §6.19 Стандартный logging — в
1.12.0. Добавленlogging.getLogger("ORD"), ошибки и info-сообщения теперь пишутся и в журнал libfptr10, и в системный logger приложения. - ✅ §6.20 Документация кода (частично) — в
1.12.0. Docstrings главных методов Core/Receipt приведены к единому стилю (Russian-comment + :param/:return), новые публичные методы (_handle_error,set_casher,__enter__/__exit__) задокументированы. Полное прохождение по Fn/Cash — оставляем (низкий приоритет). - ✅ §6.21 Опечатка
cancel_reciept.py— файл не существует (был удалён ранее). Закрываем без изменений. - ✅ §6.22 .gitignore — в
1.11.0(__pycache__/,*.pyc,*.egg-info/,dist/,build/,.pytest_cache/,venv/).
6.8. Опциональные исключения вместо False — done в 1.11.0
FalseПриоритет: P2.
Добавить параметр Core(raise_on_error=True). При активации все методы
поднимают OrdError(error_code, error_description) вместо return False.
Сохранить дефолт False для обратной совместимости. Это даст:
- Stacktrace в логах приложения
- Возможность
except OrdErrorдля конкретных кодов libfptr10 - Прекращение «тихих фейлов» когда
Falseигнорируется вызывающим кодом
6.9. Timeout в _check_document_close / continuePrint — done в 1.11.0
_check_document_close / continuePrintПриоритет: P1.
Бесконечные while ... < 0: continue без выхода. Заменить на:
import time
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
if self.fptr.checkDocumentClosed() >= 0:
break
self._error_log()
time.sleep(0.5)
else:
raise OrdTimeoutError(...)
6.10. Тесты — done в 1.11.0
Приоритет: P0.
ORD/test/ORD_test.py сейчас 207 байт (пустой шаблон). Добавить:
- Unit-тесты с моком
IFptr— каждый метод проверяет правильность setParam-цепочки (без реальной кассы). Минимум 30 тестов. - Integration-тесты против реальной АТОЛ 30Ф (cashdev,
172.16.0.7) — реальные пробития чеков, чтение ФН. Маркер@pytest.mark.real_kkt, skip-by-default. - Покрытие минимум 70%.
Использовать pytest + pytest-mock. Сейчас вообще нет покрытия.
Все задачи раздела §6 закрыты в 1.12.0.
7. Версионирование и релизы
Используется semver: MAJOR.MINOR.PATCH[.HOTFIX].
MAJOR— несовместимое API изменениеMINOR— новый функционал, обратно совместимыйPATCH— багфиксы
Процесс релиза:
- Внести изменения в feature-ветке
- Merge в
masterпосле ревью - Bump версии в
setup.py(потом — вpyproject.toml) - Поставить tag:
git tag X.Y.Z && git push origin --tags - Сборка:
python -m build - Публикация:
twine upload dist/*
Текущая ситуация (на 2026-06-25):
| Источник | Версия master |
|---|---|
Локально (IdeaProjects/online-receipt-driver) |
1.8.26.0 |
| GitLab origin (master) | 1.8.26.0 |
| GitHub зеркало (master) | 1.8.26.0 |
| PyPI ORD | 1.8.26.0 |
Production: online-api/venv на cashdev |
1.8.26.0 |
Все источники синхронизированы.
История версий:
1.8.x— текущая линия (НДС 22%, AutoTimeSync, разрешительный режим 030)1.6.x(веткаlegacy-1.6.xв GitLab) — заброшенная ветка с устаревшим API, оставлена для исторической справкиdenis— старая ветка экспериментов, не мерджена
8. Тестирование
До настоящего момента тесты для ORD делались только в проекте-потребителе
online-api (см. online-api/tests/unit/test_piot_client_mock.py,
tests/e2e/test_fn_real.py). Прогон против реальной АТОЛ 30Ф на cashdev:
ssh volodya@cashdev 'cd /var/www/api/current && \
./venv/bin/pytest tests/e2e/ -m e2e -v'
После §6.10 тесты переедут в этот репо.
9. Контакты
- Автор: Vladimir Smirnov (volodya@brandshop.ru)
- Баги/MR: GitLab
online-receipt/online-receipt-driver
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ord-1.12.0.tar.gz.
File metadata
- Download URL: ord-1.12.0.tar.gz
- Upload date:
- Size: 36.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d79d4582c77ca2463bd1cb8acbcea1f58762f61290c6ac3f88d4aefac0014c5
|
|
| MD5 |
1e64902849edc73f84b0e8ff74b84704
|
|
| BLAKE2b-256 |
f4fa4147c230beb664d0eed1a5116da1f574106c7bb966d40ce073bc83fdb0f1
|
File details
Details for the file ord-1.12.0-py3-none-any.whl.
File metadata
- Download URL: ord-1.12.0-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5b0aff45ad4856bdbb5483a9c771ccc8c8918b8628979be935e894aa2495bbb
|
|
| MD5 |
f56a199cb111b5e817a0fc47e9a609a8
|
|
| BLAKE2b-256 |
03c92dd2e36215381261216c8ee0656c81a23ac3327bbcb8de2c6575cefb34ba
|