Skip to content

open_doc: don't ask a two-argument handler for a series member (port handlerTakesContext) - #92

Merged
stevevanhooser merged 1 commit into
mainfrom
claude/port-handler-takes-context-gate
Oct 23, 2026
Merged

stevevanhooser merged 1 commit into
mainfrom
claude/port-handler-takes-context-gate

Conversation

@stevevanhooser

@stevevanhooser stevevanhooser commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Closes the divergence recorded on the handlerTakesContext bridge entry in #91.

The divergence

A file-series member has no location of its own. To fetch one, the customFileHandler is given the series manifest's location, and the member's uid travels in the third (context) argument. A handler that takes only (dest_path, source_path) never sees that uid, so it cannot know which member is wanted. Whatever it writes gets cached under the member's uid as the wrong bytes.

  • MATLAB (fetchSeriesMemberBytes, 3299ab8, #188) checks handlerTakesContext and doesn't call such a handler. The member counts as not on this machine.
  • Python (_open_series_member) called any handler. Afterwards it only caught the case where the handler returned the manifest's own bytes. A two-argument handler that returned anything else was accepted and cached.

The change

  • Factored _handler_takes_context(handler) out of _dispatch_custom_file_handler. It mirrors MATLAB's handlerTakesContext: three or more positional parameters, or *args, means the handler takes the context. A callable that can't be inspected answers False, MATLAB's safe default. Dispatch now uses the same function, so the gate and the call can't disagree.
  • _open_series_member raises DID:SQLITEDB:FileSeries:MemberNotHere for a two-argument handler, as it does with no handler, without calling it. The message tells the caller to accept a third, context argument.
  • Updated the bridge entry: handlerTakesContext now maps to _handler_takes_context and records the port.

Behaviour change for callers

A two-argument handler that used to serve series members now gets MemberNotHere when opening a member that isn't local. That matches MATLAB, and those members were being served from a request that never said which member was wanted. The add path is unchanged: two-argument handlers still ingest, as in MATLAB. So does the manifest fetch, which passes the manifest's own uid and location.

test_a_two_argument_handler_is_still_called asserted the old behaviour, so it is flipped to test_a_two_argument_handler_is_not_asked_for_a_member.

Tests

  • tests/test_open_doc_file_series.py:
    • the flipped test above;
    • a *args handler is still asked, with the context;
    • TestHandlerTakesContext covers 2 vs. 3 positional parameters, *args, keyword-only parameters not counting, bound methods (with self excluded), and an uninspectable callable.
  • The gate tests fail with the source change reverted; the *args test passes either way, as it should.
  • Locally: black --check, ruff check (0.16.5), pytest (781 passed), and check_bridge_coverage.py (0 problems).

Not changed

In _dispatch_custom_file_handler, an uninspectable callable is still tried with three arguments and then two on TypeError, rather than given the two-argument contract outright. That only affects the dispatch. The gate follows MATLAB, and the remaining difference is recorded in the bridge entry.

🤖 Generated with Claude Code

https://claude.ai/code/session_012Dn4gCNCU2jUGdmfPVCAGK

Port of DID-matlab's handlerTakesContext gate (3299ab8, #188). A series
member has no location of its own, so the handler is given the series
manifest's location and the member's uid in the context. A handler that
takes only (dest_path, source_path) never sees that uid and cannot know
which member is wanted. Whatever it writes would be cached under the
member's uid as the wrong bytes. MATLAB's fetchSeriesMemberBytes does not
call such a handler. Python did, and only caught the case where the
bytes happened to equal the manifest's.

_handler_takes_context is factored out of _dispatch_custom_file_handler,
mirroring MATLAB's handlerTakesContext. _open_series_member now raises
DID:SQLITEDB:FileSeries:MemberNotHere for a two-argument handler, as it
does with no handler, without calling it.

This changes behaviour for callers: a two-argument handler that used to
serve series members now gets MemberNotHere. The test that asserted the
old behaviour is flipped. The add path is unchanged: two-argument
handlers still ingest, as in MATLAB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Dn4gCNCU2jUGdmfPVCAGK
@stevevanhooser
stevevanhooser merged commit 881a897 into main Oct 23, 2026
7 checks passed
@stevevanhooser
stevevanhooser deleted the claude/port-handler-takes-context-gate branch October 23, 2026 23:22
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.

2 participants