Skip to content

Add type stub package, type-check batou#546

Draft
dpausp wants to merge 6 commits into
mainfrom
ts-types
Draft

Add type stub package, type-check batou#546
dpausp wants to merge 6 commits into
mainfrom
ts-types

Conversation

@dpausp

@dpausp dpausp commented Apr 22, 2026

Copy link
Copy Markdown
Member

New: separate batou-stubs package (under stubs, mirroring the code package layout) providing type stubs (48 .pyi files, one per code module)
Must be published separately on PyPI — uv add --dev batou-stubs for batou deployments.
With that, deployment authors get IDE autocompletion and type-checking for batou components.

There's a separate new project batou-type which provides type-checking for a deployment as a simple one-liner:

uvx --from git+https://github.com/dpausp/batou-type batou-type check

The stubs are also used to type-check batou itself with ty, integrated in pre-commit/tox environments.

Stubs use Python 3.14+ syntax: The .pyi files use modern type syntax (Self, PEP 695 generics, | unions).
This is fine for stubs — they're consumed by type checkers/LSP/IDE only, not at runtime.
batou itself continues to support Python 3.10+.

  • ty.toml, stubs/stubtest-allowlist.txt — - — makes ty/stubtest form mypy work with the dynamic nature of Batou
  • typing_tests/test_stubs.py — type-level tests using assert_type()
  • Fixed test mocks: autospec=True on all @patch decorators
  • Fixed parameter shadowing in main.py (argsparsed)
  • Fixed tox-gh CI config to run correct env per Python version
  • Updated release-this.sh to publish batou-stubs alongside batou

@dpausp
dpausp force-pushed the ts-types branch 2 times, most recently from df8204a to bf06d2d Compare April 28, 2026 09:28
@dpausp dpausp changed the title type stubs Add type stub package, type-check batou May 5, 2026
dpausp added 6 commits May 5, 2026 15:45
- Add stubs/ directory with 60+ .pyi stub files for batou package
- Add uv workspace support for stubs package (stubs/pyproject.toml, stubs/ruff.toml)
- Add ty type checker config (ty.toml) with per-file overrides
- Add ty-check hook to .pre-commit-config.yaml
- Add mypy config, typing/lint dependency-groups, stubs/typing tox envs
- Add typing_tests/test_stubs.py for static type checking validation
- Add stubtest-allowlist.txt for known runtime/stub divergences
- Update .gitignore for stub artifacts

Fix mysql stub: remove docstring (Y021), allowlist UseSudo sentinel

- Remove docstring from UseSudo class (flake8-pyi Y021)
- Add UseSudo/USE_SUDO to stubtest allowlist (runtime is object(),
  stub uses typed sentinel for narrowing)

Format stubs with 130-char line length

- Remove trailing commas from param lists (libcst codemod) so ruff
  can collapse multi-line signatures into single lines
- Point tox stubs env to stubs/ruff.toml for ruff check + format
- Net reduction of ~700 lines across 31 stub files

Collapse multi-line stub signatures to 130 chars

- Extend libcst codemod to also collapse multi-line signatures that
  fit on one line after trailing comma removal
- Preserve @classmethod/@overload decorators and # type: ignore comments
- Skip collapse when inline comment would exceed line limit

Handle *args trailing commas in stub codemod

- Fix libcst codemod to also remove trailing commas from star_arg
  params (*args), which are Param nodes with star='*', not ParamStar
- Collapse log(*args) in component.pyi and exactly_one(*args) in git.pyi

remove fix script
- Rename local 'args' variable to 'parsed' in main.py to avoid
  shadowing the builtin
- Minor variable rename in utils.py

Fix swapped mock.patch decorator order in owner/group tests

@patch decorators apply bottom-up, so the inner decorator's mock is the
first function parameter. The original code used os.stat.return_value
(module attribute access) so the swap didn't matter. When we changed to
using the local variable names (stat.return_value), the names were bound
to the wrong mocks — setting return_value on os.chown instead of os.stat.

Swap decorator order so os.stat (inner) → first param, os.chown (outer) →
second param, matching the (chown, stat, root) parameter names.
autospec=True ensures mock.call args match real function signatures,
catching typos and API drift at test time.

- test_download: autospec on urlretrieve, hash mocks
- test_file: autospec on os.chown; use real os.stat_result for os.stat
  (plain Mock() breaks genericpath.isfile on Python <3.14)
- test_environment: autospec on Environment.add_root, Output.line
- test_remote_core, test_template, test_utils: minor mock fixes
Before, each matrix version ran all tox envs.

The mapping from matrix versions to used TOXENV is now set explicitly
which avoids extra config outside of the workflow definition.
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