Skip to content

Gradually introduce mypy type checking (Phases 1-3)#48

Merged
pskeshu merged 8 commits into
gently-project:developmentfrom
subindevs:46-gradual-mypy-typing
Jun 15, 2026
Merged

Gradually introduce mypy type checking (Phases 1-3)#48
pskeshu merged 8 commits into
gently-project:developmentfrom
subindevs:46-gradual-mypy-typing

Conversation

@subindevs

Copy link
Copy Markdown
Collaborator

Summary

Implements the incremental mypy-typing plan from #46: a lenient [tool.mypy]
config plus an explicit [[tool.mypy.overrides]] ignore-list for currently
failing modules, wired into CI and pre-commit (#42's mypy scope), and then
progressively shrinking that list:

  • Setup: add mypy config/CI/pre-commit, document the incremental policy in
    CONTRIBUTING.md (per Gradually introduce mypy type checking #46's task list).
  • Phase 1: fix implicit-Optional parameter defaults (def f(x: str = None))
    across 45 modules, plus gently/harness/bridge.py.
  • Phase 2: add a StoreProtocol for the ContextStore memory mixins and
    fix the remaining errors it surfaced.
  • Phase 3: retype the tool-execution context dict — new ctx_get()
    helper plus retyped require_agent/require_microscope/etc. in
    gently/harness/tools/helpers.py — clearing all 16 gently.app.tools.*
    modules.

Results

  • mypy override list: 113 → 79 modules
  • Underlying error count (overrides stripped): 1070 → 369
  • mypy . passes cleanly against the remaining override list (300 source files)

Test plan

  • .venv/bin/mypy . — success, no issues found in 300 source files
  • .venv/bin/ruff check . — all checks passed
  • .venv/bin/ruff format --check . — 300 files already formatted
  • .venv/bin/pre-commit run --all-files — all hooks pass

Progress on #46 — 79 modules / 369 errors remain, scoped as a follow-up phase
in a separate issue.

🤖 Generated with Claude Code

subindevs and others added 6 commits June 14, 2026 22:12
…t#46)

Adds a lenient [tool.mypy] config with an explicit ignore_errors
override list for the 113 modules that don't yet pass, runs mypy in
the lint CI job and as a pre-commit hook, and adds mypy to the dev
dependency group. New code is held to the standard; the override
list shrinks as modules are cleaned up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Annotates two implicit-Optional defaults and fixes a str/Path
arg-type mismatch in create_timelapse_video. Removes the file from
the mypy override list before it's even added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes def f(x: T = None) to def f(x: T | None = None) to match
PEP 484 / mypy's no_implicit_optional, matching the pattern already
applied to bridge.py in gently-project#42. Removes 14 modules from the mypy
ignore_errors override list (113 -> 99) that are now fully clean.
…errors

The four ContextStore mixins (_intentions, _plans, _understanding,
_ml_pipelines) call methods/attributes defined on the host class or
sibling mixins (_conn, _tx, _now, _gen_id, get_plan_items,
create_campaign, etc.), which mypy couldn't see on the mixins
themselves. Add gently/harness/memory/_protocols.py declaring a
StoreProtocol with these members and have each mixin inherit from it
for typing only.

Also fixes the remaining errors this didn't cover: two untyped dict
literals in _plans.py needed explicit dict[str, Any] annotations, and
three _ml_pipelines.py methods returning an Optional lookup right
after an insert now assert the row exists.

All four mixins are now mypy-clean; removes them from the
ignore_errors override list (99 -> 95).
…y overrides

Adds ctx_get(context, key) and retypes the require_* helpers in
harness/tools/helpers.py to accept context: dict | None and return
non-Optional success values, eliminating the dominant union-attr/arg-type
pattern across the tool modules. Applies the same fix to memory_tools'
local _get_memory and a handful of independent var-annotated/type issues.

Removes all 16 gently.app.tools.* modules from the mypy override list
(95 -> 79), cutting the underlying error count from 610 to 369.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ent crash and remaining type gaps

- volume_tools.view_image: guard against a disconnected microscope client
  via require_microscope() instead of crashing on client.capture_bottom_image()
- file_store/store register_volume: volume_data: np.ndarray = None ->
  np.ndarray | None = None (implicit-Optional missed in the earlier pass)
- StoreProtocol: mark @runtime_checkable for consistency with
  gently.harness.protocols
- TimelapseOrchestrator.start: embryo_ids: list[str] -> list[str] | None = None
  to match its actual None-handling and the docstring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@subindevs subindevs requested a review from pskeshu June 15, 2026 13:35
…onal

CI installed mypy unpinned (`pip install mypy`) while the pre-commit hook
pinned mirrors-mypy v2.1.0, so the two would diverge the moment a newer
mypy released — "passes my pre-commit" would stop implying "passes CI".
Pin all three sources to 2.1.0 (CI install, pyproject dev group, and the
pre-commit rev) and cross-reference them so they move together.

Also convert the one implicit-Optional missed in Phase 1: `view_image`'s
`image: np.ndarray = None` in dispim/client.py (the other three params in
that same signature were already converted).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pskeshu pskeshu merged commit 97e3d25 into gently-project:development Jun 15, 2026
1 check 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