Skip to content

Fix the ty static checks - #1645

Merged
malatewang merged 2 commits into
MemMachine:mainfrom
edwinyyyu:fix/ty-diagnostics
Sep 16, 2026
Merged

malatewang merged 2 commits into
MemMachine:mainfrom
edwinyyyu:fix/ty-diagnostics

Conversation

@edwinyyyu

Copy link
Copy Markdown
Contributor

The lint workflow's six ty jobs (common, client and server, each on the oldest and newest supported Python) fail on every pull request against main — the client jobs on one diagnostic, the server jobs on seventeen. This makes all six pass. It is #1595 applied to main; the diagnostic set is identical, and the ty-fix commit is a clean cherry-pick.

The NebulaGraph half

Nine of the eighteen diagnostics are a real breakage rather than a typing nit. nebula5-python 5.3.0 removed NebulaAsyncClient, SessionConfig and SessionPoolConfig — all three in nebulagraph_python.client.__all__ in 5.2 — so nebula5-python>=5.2.1 resolves to a release whose import the NebulaGraph backend cannot even complete: async_get_nebula_client raises ImportError at its use site, and nebula_graph_vector_graph_store has no client type to annotate.

Porting forward is not available yet. 5.3's AsyncNebulaClient has no public way to open a connection:

  • NebulaAsyncClient.connect(hosts=..., username=..., session_config=..., session_pool_config=...) is gone.
  • AsyncNebulaClient.__init__ leaves connection = None and session_id = -1, and its public surface is close, execute, execute_with_timeout, execute_py, ping, pq, print_query_result, is_closed_client and the get_* accessors — no connect, open or __aenter__.
  • The only initializer left is the private _init_client(), which nothing in the package calls.

Its sync NebulaClient, NebulaPool and ClientPoolFactory are complete, so the ways forward are private API or running blocking gRPC calls off the event loop — a backend rewrite, not a lint fix. This PR caps the extra at <5.3, the range the backend actually supports, and documents why at the declaration. Relocking also drops the runtime dependencies on pytest and pool that 5.3.0 added.

The rest

  • The four missing-argument diagnostics were tests that deliberately omit a required field. They now go through model_validate() with a dict, so pydantic — not a suppression comment — is what rejects the input.
  • test_delete_episode_store_processes_in_batches assigned a mock over a bound method behind a # type: ignore / # ty: ignore pair; it now uses monkeypatch.setattr, and both comments are gone.
  • test_password_mixin_invalid_type loses its blanket # type: ignore the same way.
  • cast(ResponseFunctionToolCall, output) was redundant — ty narrows output on the output.type != "function_call" guard. It is now an annotation, so the narrowing is proved rather than asserted.
  • _format_search_summary sliced values pulled out of a model_dump()ed dict, which are not necessarily str; a non-str value would have raised TypeError at runtime. They are stringified before slicing.

No # type: ignore, # ty: ignore, Any or cast was added.

First commit: the lock on main does not pass uv lock --check

Separate from the ty fix, and needed for this PR's own lock check to pass. uv.lock on main records datasets>=5.0.0 as a requirement of memmachine-server, and locks datasets, dill and multiprocess for it, but no pyproject in the workspace declares datasets. The entry arrived with #1477's lock commit (2026-08-13), whose pyproject changes added only the spaCy group. So uv lock --check has failed on main since then:

$ uv lock --check      # main, uv 0.12.15
Resolved 234 packages
error: The lockfile at `uv.lock` needs to be updated, but `--check` was provided.

Nothing caught it because the "Check uv.lock file" workflow runs only for pull requests that touch a dependency file, and the only such PRs since #1477 have been dependabot's, for which the workflow regenerates the lock instead of checking it. The first commit relocks: the phantom requirement, the three packages that existed only to satisfy it, and the fsspec[http] extra only datasets pulled in go away. No version moves. (The evaluation scripts that from datasets import load_dataset do so lazily and were never covered by the lock.)

Verification

Run with uv 0.12.15, the version setup-uv installs in CI. ty check passes for packages/common (3.10, 3.14), packages/client (3.10, 3.14) and packages/server (3.12, 3.14) — the six CI jobs. ruff check, ruff format --check and uv lock --check pass. Unit suite: server 1869 passed, 3 skipped; client 255 passed.

Out of scope: the repository-root ty check, which CI does not run, still reports diagnostics under evaluation/, examples/, integrations/ and tools/.

Related: #1595 (same fix on speedkick, merged). The dependency refresh that followed it there is ported as a stacked PR on this one.

🤖 Generated with Claude Code

edwinyyyu and others added 2 commits September 15, 2026 13:47
uv.lock records datasets>=5.0.0 as a requirement of memmachine-server,
and locks datasets, dill and multiprocess for it, but no pyproject in
the workspace declares datasets. The entry arrived with MemMachine#1477's lock
(2026-08-13), whose pyproject changes added only the spaCy group, so
`uv lock --check` has failed on main since then. Nothing caught it
because the lock-check workflow runs only for pull requests that touch
a dependency file, and the only such pull requests since have been
dependabot's, for which the workflow regenerates the lock instead of
checking it.

Relocking removes the phantom requirement and the three packages that
existed only to satisfy it (datasets, dill, multiprocess), plus the
fsspec[http] extra that only datasets pulled in. No version moves.
The evaluation scripts that import datasets do so lazily and were
never covered by the lock.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
The lint workflow's ty jobs (common, client and server, each on the
oldest and newest supported Python) fail on every pull request. Nine of
the eighteen diagnostics are a real breakage rather than a typing nit:
nebula5-python 5.3.0 removed NebulaAsyncClient, SessionConfig and
SessionPoolConfig -- all of them in nebulagraph_python.client's __all__
in 5.2 -- so the `>=5.2.1` specifier resolved to a release the
NebulaGraph backend cannot import at all.

5.3's replacement, AsyncNebulaClient, has no public way to open a
connection: NebulaAsyncClient.connect() is gone, __init__ leaves
connection None and session_id -1, and the only initializer left is the
private _init_client(), which nothing in the package calls. Its sync
NebulaClient and NebulaPool are complete, so moving forward means
either private API or running blocking gRPC in the async server. Cap the
extra at <5.3 for now, which is the range the backend actually supports.
Relocking also drops the runtime dependencies on pytest and pool that
5.3.0 added.

The rest:

- Construct the deliberately-invalid language-model parameters and API
  key through model_validate(), so pydantic rejects them and no static
  check has to be suppressed to express the test.
- Set the mocked _cleanup_semantic_history with monkeypatch.setattr
  instead of assigning over the bound method.
- Annotate the narrowed function-call output rather than casting it: ty
  now proves what the cast used to assert.
- Stringify the LangGraph search-summary content before slicing it. It
  comes out of a model_dump()ed dict, so it is not necessarily a str,
  and a non-str value would have raised TypeError at runtime.

Same change as MemMachine#1595 on speedkick, applied to main.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@malatewang
malatewang merged commit 8101f14 into MemMachine:main Sep 16, 2026
45 checks passed
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