Към основното съдържание

bea 0.2.0: една инсталация, целият инструментариум на Beancount

Публикувано 17 минути четенеMike ThriftMike Thrift
bea 0.2.0: една инсталация, целият инструментариум на Beancount
На тази страница

Ако някога сте предавали на колега, на нов лаптоп или на нощна cron задача работеща настройка на Beancount, знаете, че счетоводството никога не е било трудната част. Трудната част беше инструментариумът: съвпадащ Python, bean-check и bean-query в пътя, библиотека за отчети, изтеглена заради един-единствен баланс, и форматиращ инструмент, който пренаписва файловете ви в момента, в който му зададете въпрос. bea 0.2.0, издаден на 12 септември 2026 г., замества този списък с една инсталация. Командата bea вече носи пълния роден инструментариум на Beancount, изпълнява го в управляван двигател, който сама подготвя, и запазва машинночетимия договор, на който скриптовете и AI агентите вече разчитат.

Това е бележката към издание 0.2.0, написана така, както проследяваме едно издание вътрешно: какво беше доставено, какво се промени отдолу, как беше проверено, преди да достигне до пакетен индекс, какво нарочно още не прави и как да обновите. Ако вместо това търсите историята за първото стартиране, публикацията за пускането на 0.1.0 и бързият старт на CLI са по-краткото четене.

Изданието с един поглед

Два канала публикуват една и съща команда. Изберете един, след което потвърдете, че той отговаря с версията си:

$ brew install bex-co/tap/bea        # macOS и Linuxbrew
$ uv tool install beancount-io       # навсякъде с uv и Python 3.12 или по-нов
$ bea --version
bea 0.2.0
bea 0.2.0
cli-v0.2.02026-09-12
двигател
beancount 3.2.3 beanquery 0.2.0
опционално
beangulp 0.2.0 beanprice 2.1.0
python
3.12 3.14

Картата на издание 0.2.0: тагът и датата на публикуване, версиите на Beancount и Beanquery, които управляваният двигател фиксира, двете опционални функции на двигателя и версиите на Python, на които изданието беше инсталирано и тествано.

ПолеСтойност
Версия0.2.0, таг cli-v0.2.0, публикувана в PyPI и в Homebrew tap-а bex-co/homebrew-tap на 2026-09-12
Предишно издание0.1.0, тагнато на 2026-09-09, три дни по-рано
Набор от промени27 комита, засягащи CLI, 119 променени файла, приблизително 12,300 добавени и 2,100 премахнати реда
Фиксирани версии на двигателяBeancount 3.2.3 и Beanquery 0.2.0 в базовия двигател; Beangulp 0.2.0 и Beanprice 2.1.0 като опционални функции
ОсновнотоВсеки роден инструмент на Beancount под един префикс, обслужван от управляван двигател; JSON обвивката и договорът за кодовете на изход от 0.1.0 са непроменени

Какво се промени отдолу: управляваният двигател

В 0.1.0 bea импортираше Beancount в собствения си процес, както би направил всеки Python инструмент. Това работеше, но превръщаше графа на зависимостите на CLI в графа на зависимостите на Beancount и оставяше „първо инсталирайте Beancount“ като неписана стъпка във всяко ръководство.

0.2.0 прокарва линия през средата на програмата. Фронтендът bea, частта, която притежава командите, опциите и визуализирането, никога не зарежда Beancount, Beanquery или вградения код за отчети от Fava. Локалната работа със счетоводната книга се изпълнява в управляван двигател: отделна Python среда, която bea подготвя от заключващ файл с фиксирани хешове и стартира като дъщерен интерпретатор. Фронтендът изпраща JSON заявка през тази граница и визуализира това, което се връща. Не инсталирате Beancount, не слагате bean-* инструменти в пътя си и не мислите кой Python са намерили.

Как пристига двигателят зависи от канала:

  • Homebrew създава средите на фронтенда и на двигателя по време на инсталацията. Локалните команди използват двигателя в собствения keg без допълнително изтегляне.
  • PyPI (uv tool install или pipx) подготвя двигателя при първа употреба. Първата локална команда, която се нуждае от него, изтегля фиксираната комбинация, за което са нужни мрежов достъп и uv в пътя — само веднъж. Следващите команди го използват повторно офлайн от ~/.local/share/bea/engine/<version> или под XDG_DATA_HOME, ако сте го задали.

Три свойства следват от този дизайн, и всяко от тях премахва по един тикет за поддръжка, който вече сме виждали:

  1. Обновяванията остават сдвоени. bea upgrade предава обновяването на пакетния мениджър, който е инсталирал това копие, след което изгражда наново съответстващия двигател, така че фронтенд и двигател никога не могат да се разминат до различни версии.
  2. Повреден двигател се лекува сам. Ако подготовката се провали по средата, управляваната среда се изхвърля и се изгражда наново при следващия успешен опит. Случайни двоични файлове bean-check на други места в пътя се игнорират, вместо да бъдат взети по погрешка.
  3. Тежките опционални части остават опционални. Рамката за импортиране Beangulp се нуждае от системната библиотека libmagic, а Beanprice изтегля зависимости за вземане на котировки. Нито едното не е в базовия двигател. Включвате ги изрично, само в двигателя.
$ bea engine status
$ bea engine enable beangulp     # помощници за импортиране; нужна е системната библиотека libmagic
$ bea engine enable beanprice    # вземане на котировки чрез bean-price

bea engine status съобщава дали двигателят е подготвен и кои опционални функции са включени, и не се нуждае от мрежа, за да го каже. Ако подготовката при първа употреба се провали, оправете мрежата или uv и изпълнете отново която и да е локална команда, например bea check. Не правете pip install beancount до него: фронтендът няма да го използва.

Всеки роден инструмент, един префикс

Двигателят е механизмът. Видимата за потребителя промяна е паритетът: всеки изпълним файл, който upstream проектът Beancount доставя, вече има bea съответствие със същите препращани аргументи и същия запазен изход.

$ bea check                                    # bean-check, плюс --json обвивката на bea
$ bea format main.bean -o clean.bean           # bean-format: stdout по подразбиране, -i пренаписва
$ bea query "SELECT account, sum(position) GROUP BY account"
$ bea doctor context main.bean 2026-01-02      # всичките единадесет операции на bean-doctor
$ bea example --seed 1 -o example.beancount    # bean-example
$ bea treeify < balances.txt                   # treeify
$ bea ingest identify --config ingest.py inbox # Beangulp, след engine enable
$ bea price -e USD:yahoo/AAPL                  # bean-price, след engine enable
bean-check
bea check
bean-format
bea format
bean-query
bea query
bean-doctor
bea doctor
bean-example
bea example
treeify
bea treeify
beangulp
bea ingest bea engine enable beangulp
bean-price
bea price bea engine enable beanprice

Картата на паритета: шестте родни изпълними файла на Beancount над пунктираната линия работят веднага; двата под нея се препращат към Beangulp и Beanprice, след като включите съответната функция в двигателя.

Няколко от тях заслужават повече от един ред в таблица.

bea check е bean-check с наслоена отгоре JSON обвивката на bea: същата валидация, същите съобщения за грешки и под --json същите полета valid и errors, които скриптовете вече анализират.

bea format промени поведението си, и това е единствената промяна в това издание, която може да изненада скрипт. В 0.1.0 bea format PATH пренаписваше файла. Сега командата отпечатва форматирания текст в stdout и не докосва файла. --in-place (-i) е това, което пренаписва, --output FILE (-o) записва на друго място, --check е CI проверката, която излиза с 1, когато файловете имат нужда от форматиране, а --dry-run изброява какво би се променило. Това следва bean-format, чието поведение по подразбиране е безопасното: команда, която чете път и мълчаливо го пренаписва, не може да бъде изпробвана предварително. Форматирането е текстова трансформация, а не анализ, така че вече не отказва файл със синтактична грешка; подравнява това, което разпознава, и оставя останалото. Изпълнете bea check за валидност.

bea query придоби цялата родна повърхност. Приема BQL като аргумент, от stdin или в интерактивния shell, който вече е родният upstream shell на Beanquery, стартиран като дъщерен процес с непокътнати команди .format, .output, .run и .set. --format избира визуализация text, csv или beancount, --numberify разделя сумите в по една колона за валута, -o записва във файл, а --source URI предава роден Beanquery източник директно.

bea doctor излага всичките единадесет операции на bean-doctor: lex, parse, roundtrip, directories, list-options, print-options, context, linked, region, missing-open и display-context. Ако някога сте отстранявали проблем с осчетоводяването с bean-doctor context, това е същият инструмент на същия адрес.

bea example и bea treeify са родният генератор и родният визуализатор на дървета, препратени както са.

bea ingest и bea price препращат съответно към identify, extract и archive на Beangulp и към bean-price, след bea engine enable. Пътят за CSV без Python, bea import --csv, не се нуждае от нито едното и е непроменен.

Едно правило свързва препращаните команди: doctor, example, treeify, price и ingest предават аргументите си на upstream непроменени и запазват изхода и статуса на изход на upstream. Това също означава, че приемат счетоводната книга като собствен позиционен аргумент, като в bea doctor lex main.bean, а не чрез глобалния --file. Обвивката и категориите на кодовете за изход по-долу описват собствените команди на bea.

Договорът, на който скриптовете могат да продължат да вярват

Нищо в машинночетимата повърхност не се е преместило. Глобалният --json все така поставя една обвивка в stdout с bea, target, data и truncated, плюс limit при ограничени списъци и page при хостваните списъци със страници. Сумите са десетични низове, никога числа с плаваща запетая, а датите са ISO YYYY-MM-DD. --json подразбира --no-input; същото прави и нетерминален stdin или истинна променлива CI, така че необслужвана задача никога не чака човек. --strict отказва частични отговори дори в терминал, а --allow-errors на всяка команда за четене връща това поведение обратно.

Грешка не записва нищо в stdout и точно един обект в stderr:

{
  "error": {
    "category": "validation",
    "message": "Ledger has 3 error(s). Pass --allow-errors to report anyway.",
    "exit_code": 1,
    "details": ["main.bean:1: Transaction does not balance: (2.50 USD)"]
  }
}
0
ok
1
validation
2
usage
3
auth
4
conflict

Петте кода за изход и низът category, който всеки от тях носи в JSON обекта за грешка. Скриптът разклонява по числото; човекът чете категорията.

КодКатегорияЗначение
0нямаУспех, включително предварителни прегледи и умишлено пропуснати дубликати
1validationГрешка в счетоводната книга или при валидация, както и общата категория за всяка друга грешка по време на изпълнение
2usageЛоши аргументи, липсваща или излишна цел, или нужда от вход под --no-input
3authНеуспешно удостоверяване или липса на права, включително дестинация само за четене
4conflictЕдновременна промяна, импорт, който изисква преглед на дубликати, или запис с неизвестен резултат

Два детайла имат значение за всеки, който повтаря опита при грешка. Ненулев изход не означава универсално, че нищо не се е променило: add transactions --partial може да запише приетите редове, format -i върху няколко файла може да пренапише някои, преди да се провали на един, а cloud ledger create --clone може да създаде счетоводната книга, преди клонирането да се провали. Прочетете error.result, преди да повторите мутация. А хостваните команди съпоставят HTTP статуса на сървъра със същата таблица, запазвайки собственото съобщение на сървъра: 401 и 403 излизат с 3, 400 излиза с 2, 409 излиза с 4, а всичко останало, включително ограничаването на заявките, излиза с 1. Запис, чийто резултат CLI не може да знае, например таймаут по средата на изтриване, излиза с 4 и го казва, вместо да гадае.

Ръководството за автоматизация превежда jq конвейер през тази обвивка от край до край.

Поправки, които дойдоха с изданието

Издание за паритет е и шанс да се затворят дефектите, които първото издание изважда на повърхността. Тези бяха включени между двата тага, всяка с регресионен тест:

  • Числата се записват като текст с фиксирана запетая, никога в научен запис, включително началните салда, които bea init генерира. Счетоводна книга, в която пише 1E+3, е технически валидна и практически нечетима.
  • Лотовете по себестойност преживяват JSON сериализацията с непокътнати дати и етикети, а етикетите на лотовете се екранират правилно при записване на транзакция.
  • Изричните нулеви записи са истински суми при импортиране, вместо да се четат като „пропуснато, моля балансирай ме“.
  • CSV импортите минават през един строг четец. Откриването на заглавния ред премахваше празните места около имената на колоните, докато извличането пазеше суровите ключове, така че заглавен ред с отстояния, който документацията обещаваше да приеме, се проваляше като липсваща колона. Сега имената се почистват веднъж, съпоставена колона трябва да се появи точно веднъж, а незатворена кавичка се проваля с номера на своя ред, преди нещо да бъде записано.
  • BQL зарежда точния път до счетоводната книга вместо низ за връзка, анализиран като URL, така че необичайни пътища се разрешават по същия начин, както останалата част от CLI ги разрешава.
  • bea balance <term> сумира само това, което показва. Запазен родителски елемент вече не отчита сумите на изключените съседи, несвързан неоценен актив вече не проваля селекция в USD, а обвивката съобщава приложения филтър. Невалиден шаблон --account при отчети излиза с 2 като грешката при употреба, каквато е.
  • stderr в JSON режим винаги е един обект, дори когато толерирани предупреждения предхождат грешката.
  • Хостваните удостоверения се провалят рано и последователно: BEA_TOKEN, съдържащ празни знаци, се отхвърля преди всяка заявка, отменено удостоверение се съобщава по един и същ начин от cloud status и от командите за счетоводни книги, а owner/name се валидира преди подкана за потвърждение или удостоверено извикване. cloud logout не пипа BEA_TOKEN, а cloud ledger list --json връща страницата, която действително е обслужила.
  • Формулата за Homebrew фиксира точния URL на артефакта в PyPI, така че инсталация от tap-а и инсталация от PyPI са доказуемо едни и същи байтове.

Как беше проверено, преди да го видите

Едно издание е твърдение, а конвейерът е доказателството. Таг cli-v0.2.0 трябва да сочи комит в main, чиято версия в pyproject.toml съвпада точно; работният поток отказва всичко друго, включително суфикси за предварителни издания. Оттам нататък:

  1. Първо се изпълнява пълният набор от проверки. make check-all покрива lint, форматиране, строг mypy, откриване на мъртъв код, проверката за разминаване на генерираната справка и тестовия набор. Pull request-ът за изданието отчита 635 преминали теста.
  2. Заключващият файл на двигателя се експортира и фиксира с хешове, а дистрибуцията на изходния код и wheel-ът се изграждат веднъж. Всяка следваща стъпка тества точно тези артефакти, а не повторно изграждане.
  3. Чисти инсталации на три операционни системи и два Python-а. Wheel-ът се инсталира чрез uv tool, а sdist-ът чрез pip на Linux, macOS и Windows, на Python 3.12 и 3.14, включително опционалната AI екстра. Homebrew задача инсталира sdist-а чрез временен tap на macOS и Linux.
  4. Публикуването е последователно и без токени. PyPI получава артефактите чрез доверено публикуване, така че не съществува дълготраен API токен, който да изтече; GitHub Release-ът се създава с прикачени атестации за публикуване; а Formula/bea.rb се изпраща в публичния tap с URL и хеш на sdist-а, които PyPI действително е обслужил.
  5. Smoke тестовете след публикуване инсталират от истинските индекси. Отделни задачи инсталират фиксираната версия от PyPI и от публичния tap и изпълняват същите клиентски smoke тестове срещу инсталирания изпълним файл. Провал там не връща нищо назад, но означава, че изданието се нуждае от внимание, преди някой да бъде уведомен за него.

Тази публикация се пише от другата страна на стъпка пет.

Обновяване от 0.1.0

Изпълнете обновяването през мениджъра, който е инсталирал вашето копие, или оставете bea да го направи:

$ bea upgrade --check      # съобщава инсталираната и последната версия и командата, която ще се изпълни
$ bea upgrade              # brew upgrade bea, uv tool upgrade beancount-io или pipx upgrade beancount-io

След като мениджърът приключи, bea upgrade опреснява управлявания двигател, така че двете да останат сдвоени. После проверете три неща:

  • Всеки скрипт, който изпълняваше bea format PATH, за да пренапише файл, сега се нуждае от bea format -i PATH. Старото поведение по подразбиране не можеше да се прегледа предварително, а новото може.
  • Всеки скрипт, който разчиташе на format, за да улови синтактична грешка, трябва да извиква bea check за това, защото форматирането вече не анализира.
  • Инсталациите от PyPI се нуждаят от мрежа и uv веднъж за първата локална команда след обновяването, за да може двигателят да бъде подготвен. Инсталациите от Homebrew не се нуждаят от нищо.

Всичко, което скриптовете ви вече анализират — ключовете на обвивката, десетичните низове и кодовете за изход — е непроменено. Полето bea в обвивката сега гласи 0.2.0.

Какво това издание не прави

  • Хостваното насочване не е реализирано. Няма флаг --ledger; локалните команди четат локални файлове и никога не качват такъв имплицитно. Хостваните счетоводни книги се управляват под bea cloud и се обработват като git клонове.
  • bea ask все още се нуждае от екстрата ask и от удостоверения за Beancount.io, и не поддържа --json. Инсталацията по подразбиране не носи AI зависимости.
  • Beangulp и Beanprice са опционални, а Beangulp се нуждае от системната библиотека libmagic. bea import --csv покрива банкови експорти без нито едното.
  • Препращаните родни команди не издават обвивката. Ако имате нужда от структуриран изход от doctor операция, това е заявка, която бихме искали да чуем.

От тага насам main вече е поел първия кръг QA върху 0.2.0, и той ще влезе в следващото издание: bea format чете stdin като филтър, а режимът му -o FILE отговаря с обвивка, назоваваща какво е записал; --json check отказва флагове, които са само за bean-check, а --json се отказва изцяло за doctor, example и treeify, така че скрипт да не може да сбърка роден текст с обвивка; --json query -o FILE записва обвивката във файла атомарно, с --numberify, приложен и към JSON; bea engine status назовава кое ниво на двигателя обслужва; BQL заявка, започваща с коментар, се изпълнява; родният пропускащ --help работи преди двигателят да е подготвен; а .output на shell-а за заявки възстановява оригиналния поток след неуспешно пренасочване.

Къде да продължите

Водете книгите си като код

Инструментариум, който можете да инсталирате с един ред, е инструментариум, който можете да дадете на всеки: съосновател, счетоводител, CI изпълнител, AI агент. Beancount.io предлага счетоводство в обикновен текст, което остава прозрачно, с контрол на версиите и възпроизводимо, с bea като командата, която пази локалната счетоводна книга честна, и хостваната услуга като мястото, където екипът ви, телефонът ви и асистентът ви срещат едни и същи книги. Инсталирайте bea и изпълнете първата си проверка, а ако изданието направи нещо, което не сте очаквали, GitHub хранилището е мястото, където искаме да го чуем.

Споделете тази статия

Източник: https://beancount.io/bg/blog/2026/09/16/bea-0-2-0-one-install-whole-beancount-toolchain

Публикувано: 16 септември 2026 г.