Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ jobs:
run: uvx --from check-jsonschema==0.38.2 check-jsonschema --builtin-schema vendor.dependabot .github/dependabot.yml
- name: Run complete mocked test suite
run: uv run pytest
- name: Check configured mypy target and API compatibility (Python 3.8)
if: matrix.python == '3.8'
run: uv run --extra dev python checks/mypy_compatibility.py -v
- name: Check configured mypy target and API compatibility (Python 3.13)
if: matrix.python == '3.8'
run: uv run --isolated --python 3.13 --extra dev python checks/mypy_compatibility.py -v
- name: Build wheel and source distribution
run: uv build
- name: Require both package artifacts
Expand Down
88 changes: 88 additions & 0 deletions agent-notes/repair/task6-installer-mypy-range.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Goal

Preserve configured Python 3.8 target/API compatibility in original same-org
installer_builder PR #4 without combining its dependency change with the
separate unresolved full-package typing characterization in draft #5.

# State

Local-only repair/task6-installer-mypy-range starts directly at verified actual
merged master 11ec654ac80ef0bd7423156e76a22aa1d8e3a453. It changes the optional
mypy range from >=0.991,<1.0 to >=0.991,<1.15, copies the exact authored
three-case checks/mypy_compatibility.py probe, and invokes it on tool Python
3.8 and 3.13 in the existing Windows Python 3.8 CI leg. Current default
tests/build, support >=3.8.6, target 3.8, strict flags, action pins, permissions
and every existing step remain.

# Decisions and why

- Original #4 at 62d473dd04ad154d3b4aade2b8723dc76ce73909 proposes <3.0.
Actual mypy 2.4.0 on tool Python 3.13 replaces the configured 3.8 target after
warning and accepts the 3.9-only str.removeprefix API. The positive startswith
control and negative untyped-definition control distinguish target behavior
from an unloaded configuration. The same three assertions are copied intact.
- The first local successor wired only the 3.8 tool runtime, which would select
an older compatible mypy even with the original <3.0 proposal. That missed the
demonstrated modern-tool regression. Add a separately named 3.13 invocation
of the identical probe with actual --extra dev resolution, not a pinned tool.
Its uv run --isolated --python 3.13 uses a fresh project environment rather
than changing the existing 3.8 .venv. No step-level environment override
persists. The following build keeps the existing setup-uv runtime selection.
Separate steps preserve ordinary failure propagation for both invocations.
- The installed uv run help supports --isolated, --python and --extra. The
official CLI reference documents fresh isolated project environments:
https://docs.astral.sh/uv/reference/cli/#uv-run
- Official mypy 1.15 release notes drop tool runtime 3.8. Mypy 1.14.1 declares
both tool and target minimum 3.8. The <1.15 cap permits that proven endpoint
without changing the package floor or substituting a newer checker target.
- This explicit target/API/config probe checks generated snippets through the
public mypy.api.run with the actual project config. It does not check package
source or establish whole-package typing correctness. It is outside ordinary
pytest collection, so default mocked tests do not import an optional tool.
- Draft #5 remains open/unmerged and retains its full configured package gate
on its own branch. Its historical 115 diagnostics are annotation/import/stub
debt plus separately classified helper issues; they are not suppressed here.
Current default has no full package gate to remove. This independent change
does not claim that the separate full-package baseline is green or landed.

# Evidence and limits

Historical focused execution before the true rebases, with isolated dependencies
and --no-project, exercised only this identical authored check file:

- Old <1.0, mypy 0.991 / Python 3.8.20: three passed in 6.924s.
- Original <3.0, mypy 2.4.0 / Python 3.13.15: two failed in 4.350s; target 3.8
warning requires 3.10 or higher and removeprefix incorrectly returns success.
- Narrowed <1.15, mypy 1.14.1 / Python 3.8.20: three passed in 9.228s.
- Same narrowed range / Python 3.13.15: three passed in 6.305s.

An initial blanket stderr assertion failed the old control because configured
unused override warnings apply to snippet-only checks. The positive assertion
was narrowed to target warnings before the recorded broad-range red/narrowed
greens. No config flag or negative API/strictness assertion was disabled.
Those focused results are historical, not execution at this new branch head.
Hosted execution is pending; no aggregate or full-package-green claim is made.
No local full checker, package install, tests/build or native installer ran.
Actionlint 1.7.12 passed with optional shellcheck/pyflakes disabled. Zizmor
1.31.1 offline pedantic reported no findings, including after the 3.13 workflow
correction. No local probe, source tests or full checker were rerun. SHA256 of
the copied probe and the preserved stacked probe is identical:
AE3B6AAB59F9B34C92501F8CE0B0DA42B39E66DB32077CFB0FD363FA08EE63A5.

# Preservation

Original #4 remains unchanged in backup/task6-installer-mypy-original-pr.
archive/task6-installer-mypy-baseline-before-11ec retains old 748ddadf;
archive/task6-installer-mypy-compatibility-before-11ec retains old e89bff68.
The genuine rebased baseline 2f18a792 and stacked probe fd0103dc remain intact.
The coordinator has published the rebased #5; its fresh run 39552363115 failed,
with exact new diagnostics assessed separately. It remains unmerged.
Canonical master 099ceb3 and all canonical dirty/untracked user work are intact.
No remote branch, PR description, settings or model route was changed.

# Next step

Return complete local head/diff and static workflow audits for coordinator
review before any publication. Any hosted probe/test/build green must describe
that exact scope; draft #5's full-package typing characterization stays separate
and unresolved after its fresh hosted failure. No publication, model or merge.
43 changes: 43 additions & 0 deletions checks/mypy_compatibility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Check mypy's configured target and strictness, not package-wide typing."""
from pathlib import Path
import sys
from tempfile import TemporaryDirectory
import unittest

from mypy import api
from mypy.version import __version__


class MypyCompatibilityTests(unittest.TestCase):
def check_code(self, source):
config = Path(__file__).resolve().parents[1] / "pyproject.toml"
with TemporaryDirectory() as cache:
return api.run([
"--config-file", str(config), "--no-incremental",
"--cache-dir", cache, "-c", source,
])

def test_python38_api_is_accepted_with_configured_target(self):
output, errors, status = self.check_code(
"def has_prefix(value: str) -> bool:\n"
" return value.startswith('prefix')\n")
self.assertEqual(status, 0, output + errors)
self.assertNotIn("python_version:", errors)

def test_python39_only_api_is_rejected(self):
output, errors, status = self.check_code(
"def remove_prefix(value: str) -> str:\n"
" return value.removeprefix('prefix')\n")
self.assertEqual(status, 1, output + errors)
self.assertIn('has no attribute "removeprefix"', output)

def test_config_still_rejects_untyped_definitions(self):
output, errors, status = self.check_code(
"def identity(value):\n return value\n")
self.assertEqual(status, 1, output + errors)
self.assertIn("[no-untyped-def]", output)


if __name__ == "__main__":
print("mypy {} on Python {}".format(__version__, sys.version.split()[0]))
unittest.main()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [

[project.optional-dependencies]
dev = [
"mypy>=0.991,<1.0",
"mypy>=0.991,<1.15",
]

[dependency-groups]
Expand Down