Skip to content

Support Beancount v3 (and v2.3+) via beangulp/beanquery - #263

Merged
Zburatorul merged 8 commits into
jbms:masterfrom
Zburatorul:feature/beancount-v3-support
Jun 6, 2026
Merged

Zburatorul merged 8 commits into
jbms:masterfrom
Zburatorul:feature/beancount-v3-support

Conversation

@Zburatorul

Copy link
Copy Markdown
Collaborator

Summary

Adds support for Beancount v3 while staying compatible with v2.3+.

v3 extracted the import framework into beangulp and the query engine into beanquery, and removed beancount.ingest, beancount.query, and beancount.ops.prices. This PR migrates the code that used those APIs onto the new packages.

Both beangulp and beanquery support beancount 2.3+ as well as 3.x, so the constraint is relaxed to beancount>=2.3.5 rather than forcing v3 — existing v2 users are unaffected.

Fixes #253. This is an alternative to #256 that additionally accepts native beangulp.Importer subclasses (not only legacy ImporterProtocol) and covers the rest of the v3 surface (query CLIs, posting metadata, typing, packaging/CI).

Changes (8 focused commits)

  • generic_importer_source — accept native beangulp.Importer and wrap legacy ImporterProtocol importers via beangulp's Adapter, so importers written against either interface work (Beangulp compatible? #253).
  • delete_transactions / rename_account — migrate the two BQL utilities from the removed beancount.query to beanquery.
  • journal_editor — ignore v3's __automatic__ / __residual__ posting metadata so it doesn't leak into the posting-match key and break matching.
  • webserver — read the bundled frontend via stdlib importlib.resources instead of the deprecated pkg_resources.
  • mypy — treat the now-py.typed beancount/beangulp/beanquery as untyped, preserving the project's existing type-check behavior.
  • packaging/CI — add the beangulp/beanquery deps, python_requires>=3.9, a Python 3.9–3.12 test matrix, and an import smoke test guarding against import-time regressions.

Testing

  • Full test suite passes on both beancount 2.3.6 and 3.2.x.
  • CI green across Python 3.9–3.12 on Ubuntu / Windows / macOS.
  • Manually validated by loading a large real-world ledger (OFX / Venmo / Amazon / PayPal sources) under beancount 3.2.x.

🤖 Generated with Claude Code

Zburatorul and others added 8 commits May 31, 2026 22:05
beancount v3 extracted the import framework into beangulp and the query
engine into beanquery. Add both as dependencies (pinned to the tested 0.2.0)
and relax the beancount constraint to >=2.3.5 (both companion packages support
2.3+, so v2 users are not forced to upgrade). Bump python_requires to >=3.9.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap legacy ImporterProtocol importers in beangulp's Adapter and accept native
beangulp.Importer subclasses directly, so importers written against either
interface work. Importers receive absolute paths instead of _FileMemo objects,
name is read as a property, and extract() takes existing entries positionally.

Fixes jbms#253.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
beancount.query and beancount.ops.prices were removed in v3. Reimplement the
two BQL admin utilities on beanquery's public run_query API, mapping result
rows back to directives/postings via hash_entry (rename_account keys on
account+position+price+posting_flag so a WHERE targeting one of several
same-account postings renames only that one). delete_transactions now matches
Transaction directives only; this is documented in its docstring/CLI help.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v3 attaches __automatic__ to interpolated postings and __residual__ to
account_rounding postings. Add both to META_IGNORE so they do not enter the
posting-match tuple and break matching against imported counterparts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v3 ships py.typed, so mypy newly type-checks the whole codebase against
beancount's Directive union. Treat beancount/beangulp/beanquery as untyped
(follow_imports=skip) to preserve pre-v3 behavior, and silence pre-existing
BeautifulSoup/lxml false-positives surfaced by current mypy/bs4 versions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pkg_resources (setuptools) is deprecated and absent from minimal/isolated
environments (tox venv, Python >=3.12). Use importlib.resources (stdlib, 3.9+)
to read the frontend assets, removing the runtime setuptools dependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
beancount v3 requires Python >=3.9, so drop 3.8 and extend to 3.12; set
fail-fast: false. Install setuptools and setuptools_scm explicitly since 3.12
no longer bundles setuptools and setup.py needs them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Parametrized test importing every beancount_import module, to catch
import-time regressions such as removed v3 APIs before they surface at runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Trigun27

Trigun27 commented Jun 2, 2026

Copy link
Copy Markdown

This is great! Is there anything I can do to help get this PR merged? Thank you.

@Zburatorul

Copy link
Copy Markdown
Collaborator Author

@Trigun27 can you test it on your setup?

@Trigun27

Trigun27 commented Jun 6, 2026

Copy link
Copy Markdown

@Trigun27 can you test it on your setup?

Sorry for the delay. I refactored it to use the new PR methods. Works on my end now: parsers and dedup are both good.

@Zburatorul
Zburatorul merged commit 024f6ce into jbms:master Jun 6, 2026
13 checks passed
@Zburatorul

Copy link
Copy Markdown
Collaborator Author

Thanks for testing @Trigun27.

@slashformotion

Copy link
Copy Markdown

Thanks for this

@Zburatorul
Zburatorul deleted the feature/beancount-v3-support branch June 7, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Beangulp compatible?

3 participants