Skip to content

fix: refuse a negated named amount, and one read where there is no coordinate - #63

Merged
FBumann merged 1 commit into
fix/window-width-rulesfrom
fix/named-amount-sign-and-reach
Aug 25, 2026
Merged

FBumann merged 1 commit into
fix/window-width-rulesfrom
fix/named-amount-sign-and-reach

Conversation

@FBumann

@FBumann FBumann commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Two of the three rules in #62. The third is split out — see below. Base is fix/window-width-rules (#61), stacked on #59 → #56.

1. A negated named amount crashed instead of being refused

shift(x, over=hour, offset=-lead, edge='wrap')
→ load:    OK
→ typeset: AssertionError          (empty message, no constraint name)

_amount matches a unary minus and asserts the operand is a NumberNode, so a negated parameter trips the assert. It was reading a rule the language stated and never enforced.

That rule is load-bearing. walk.py renders a named offset as always-backward because a negated one is refused; #56's argument that sum_forward can't be a composition is that offset=-(p-1) is refused. Both were true by convention only.

Now refused at load, in a sentence, so the assert documents a guaranteed precondition. Windows get the same rule with their own wording — a width counts positions and has no direction to negate; sum_back/sum_forward is how the language says which way.

Also fixed: _amount's docstring said by= throughout. That was the kwarg's name two renames ago, and by= is now a different kwarg on the same operator — actively misleading since #59.

2. An amount read where there is no coordinate

shift(x, over=hour, offset=lead_day, edge='wrap')    # lead_day is over `day`; x is over [unit, hour]
→ renders: x_{u,h ⊖ lead^{day}}

lead_day is a column with a value per day, and x carries no day dim, so there is no coordinate at which to read it. It rendered as a bare symbol — which on the page says "one number" about a column. Same failure as the unchecked width in #61, arriving through dims instead of dtype.

by= is the rescue, and now for windows too

The rule admits dims a partition maps into, so a by= makes such a parameter readable again — one amount per group:

shift(x, over=hour, offset=lead_day, edge='wrap', by=day_of)   # legal: one lag per day
sum_back(x, over=hour, within=lead_day, by=day_of)             # legal: one width per day

The second line is new capability rather than just a check: #59 gave the windows a partition, and this rule is what makes a per-group width mean something. A representative day with its own window length now says so.

Split out of #62

The third rule — a named offset requires an edge= — is deliberately not here, and is now #64. Its justification is a downstream frame limitation and the docs hedge it ("cannot yet say"). Enforcing it would bake a consuming lane's current constraint into a package that is deliberately lane-independent. That's a design decision, not a bug fix.

Review notes

  • Five new cases in test_dimensions.py: three rejections, two positive (by= rescuing both operators). Fixture gains bus_lead and a snap_bus lookup over snapshot, each with a comment saying why.
  • No docs changes — all of this was already documented. That was the problem.
  • 451 passing, lint clean.

🤖 Generated with Claude Code

@read-the-docs-community

read-the-docs-community Bot commented Aug 24, 2026 •

Copy link
Copy Markdown

…ordinate

Two of the three rules #62 collected, and the first is why it was filed.
`shift(offset=-lead)` loaded clean and then raised a bare
`AssertionError` out of the typesetter, because `_amount` matches a unary
minus and asserts the operand is a number. That assert was reading a
rule the language stated and never enforced --- and it is the rule the
whole treatment of a named offset rests on: `walk.py` renders one as
always-backward *because* a negated one is refused. It is refused now,
at load, in a sentence, so the assert is a precondition rather than a
hope. Its docstring said `by=` throughout, which was the kwarg's name
two renames ago and is now a different kwarg on the same operator.

The second rule is the dim half of the same idea: an amount is read at
the coordinate its operator walks, so a parameter varying over a dim
that coordinate does not carry has nowhere to be read from. It rendered
as a bare symbol, which on the page says "one number" about a column ---
the same way an unchecked width did before #58, and wrong in the same
direction.

`by=` is what makes such a parameter readable again, one amount per
group, so the rule admits the dims a partition maps into. That half was
`shift`'s alone until #59 gave the windows a partition too; both get it
here, and a width per representative day now says what it means.

Refs #62

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@FBumann
FBumann force-pushed the fix/named-amount-sign-and-reach branch from b731ebf to 6672353 Compare August 25, 2026 05:41
@FBumann
FBumann marked this pull request as ready for review August 25, 2026 05:48
@FBumann
FBumann requested a review from brynpickering as a code owner August 25, 2026 05:48
@FBumann
FBumann merged commit 15d9c25 into main Aug 25, 2026
5 checks passed
@FBumann
FBumann deleted the fix/named-amount-sign-and-reach branch September 9, 2026 06:45
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.

1 participant