Wire admin add-account endpoint into the UI #46

Merged
padreug merged 12 commits from feat/add-account-ui into main 2026-06-18 10:03:10 +00:00
2 changed files with 29 additions and 4 deletions
Showing only changes of commit 3adb3d356a - Show all commits

fix(accounts): match Beancount's DATE grammar in duplicate detection (libra-#48)

_open_directive_exists hardcoded '^YYYY-MM-DD open ' (dash-only, 2-digit,
single-space), but Beancount's DATE token (parser/lexer.l) is
(17|18|19|20)[0-9]{2}[-/][0-9]+[-/][0-9]+ and inter-token whitespace is any
[ \t\r] run. So a validly-formatted existing Open written as '2024/3/5 open X'
or '2020-01-01  open  X' escaped detection → duplicate Open appended →
bean-check rejects the file. Anchor on Beancount's actual date pattern and
[ \t]+ separators. Adds parametrized coverage for slash/single-digit/multi-
space/tab variants.

Found in a coherence pass over the Beancount source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Padreug 2026-06-17 10:27:18 +02:00

View file

@ -60,11 +60,21 @@ def _escape_beancount_string(value: str) -> str:
) )
# Beancount's DATE token (parser/lexer.l): (17|18|19|20)[0-9]{2}[-/][0-9]+[-/][0-9]+
# — '-' OR '/' separators, 1+ digit month/day. Inter-token whitespace is any
# run of [ \t\r] (ignored by the lexer). The duplicate-detection regex must
# mirror this, or a validly-formatted existing Open (e.g. '2024/3/5 open X' or
# '2020-01-01 open X') escapes detection and a duplicate Open is appended,
# which bean-check then rejects — breaking every later write.
_OPEN_DATE = r"(?:17|18|19|20)\d\d[-/]\d+[-/]\d+"
def _open_directive_exists(source: str, account_name: str) -> bool: def _open_directive_exists(source: str, account_name: str) -> bool:
"""Return True if `source` already contains an Open directive for exactly """Return True if `source` already contains an Open directive for exactly
`account_name`. `account_name`.
Anchored to a real `YYYY-MM-DD open <account>` directive line (re.MULTILINE) Anchored to a real `<date> open <account>` directive line (re.MULTILINE),
with `<date>` and the inter-token whitespace matching Beancount's grammar,
so the account name can't match text inside another account's description so the account name can't match text inside another account's description
metadata or a comment (false positive spurious 409). The trailing metadata or a comment (false positive spurious 409). The trailing
negative-lookahead `(?![\\w:-])` requires the next char not to be an negative-lookahead `(?![\\w:-])` requires the next char not to be an
@ -72,12 +82,11 @@ def _open_directive_exists(source: str, account_name: str) -> bool:
- a prefix (Expenses:Gas) does not match a longer sibling - a prefix (Expenses:Gas) does not match a longer sibling
(Expenses:GasStation / Expenses:Gas:Vehicle), and (Expenses:GasStation / Expenses:Gas:Vehicle), and
- a real directive with an inline comment and no space - a real directive with an inline comment and no space
(`open Expenses:Gas;legacy`) is still detected (`;` ends the name), (`open Expenses:Gas;legacy`) is still detected (`;` ends the name).
which the previous `(?:\\s|$)` boundary missed duplicate write.
""" """
return bool( return bool(
re.search( re.search(
rf"^\d{{4}}-\d{{2}}-\d{{2}} open {re.escape(account_name)}(?![\w:-])", rf"^{_OPEN_DATE}[ \t]+open[ \t]+{re.escape(account_name)}(?![\w:-])",
source, source,
re.MULTILINE, re.MULTILINE,
) )

View file

@ -84,6 +84,22 @@ def test_open_directive_exists_does_not_match_deeper_child():
assert fc._open_directive_exists(src, "Expenses:Vehicle:Gas") is False assert fc._open_directive_exists(src, "Expenses:Vehicle:Gas") is False
@pytest.mark.parametrize(
"line",
[
"2024/3/5 open Expenses:Vehicle:Gas", # slash date, single-digit M/D
"2020-1-1 open Expenses:Vehicle:Gas", # dash date, single-digit M/D
"2020-01-01 open Expenses:Vehicle:Gas", # multiple spaces
"2020-01-01\topen\tExpenses:Vehicle:Gas", # tab separators
"1970-01-01 open Expenses:Vehicle:Gas EUR", # currency-constrained
],
)
def test_open_directive_exists_matches_beancount_date_and_whitespace_variants(line):
# All of these are valid Beancount Open directives per lexer.l's DATE token
# and ignored inter-token whitespace; each must be detected as existing.
assert fc._open_directive_exists(line + "\n", "Expenses:Vehicle:Gas") is True
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# beancount_format.sanitize_link # beancount_format.sanitize_link
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------