livery-extensions-mypy 0.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Willem Kokke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: livery-extensions-mypy
3
+ Version: 0.0.0
4
+ Summary: mypy as a check of the livery workshop: the type checker, on every platform, configured by the root mypy.ini.
5
+ Author: Willem Kokke
6
+ Author-email: Willem Kokke <mail@willem.net>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Typing :: Typed
13
+ Requires-Dist: livery-footman>=0.58.0
14
+ Requires-Dist: livery-toolroom>=0.10.0
15
+ Requires-Dist: livery-workshop>=0.6.0
16
+ Requires-Python: >=3.11
17
+ Project-URL: Repository, https://github.com/willemkokke/livery
18
+ Description-Content-Type: text/markdown
19
+
20
+ <!-- Seeded from the package-python seeds at
21
+ birth; this file is the workspace's own. Edit it directly:
22
+ nothing rewrites it.
23
+ -->
24
+ # livery-extensions-mypy
25
+
26
+ mypy as a check of the livery workshop. Listed as `mypy` in a workspace's
27
+ `[workspace] extensions`, it registers `typecheck.mypy`, which checks linux,
28
+ darwin and win32, and writes the root `mypy.ini` the check and a bare `mypy`
29
+ read.
@@ -0,0 +1,10 @@
1
+ <!-- Seeded from the package-python seeds at
2
+ birth; this file is the workspace's own. Edit it directly:
3
+ nothing rewrites it.
4
+ -->
5
+ # livery-extensions-mypy
6
+
7
+ mypy as a check of the livery workshop. Listed as `mypy` in a workspace's
8
+ `[workspace] extensions`, it registers `typecheck.mypy`, which checks linux,
9
+ darwin and win32, and writes the root `mypy.ini` the check and a bare `mypy`
10
+ read.
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "livery-extensions-mypy"
7
+ version = "0.0.0"
8
+ description = "mypy as a check of the livery workshop: the type checker, on every platform, configured by the root mypy.ini."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.11"
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3 :: Only",
17
+ "Typing :: Typed",
18
+ ]
19
+ dependencies = [
20
+ "livery-footman>=0.58.0",
21
+ "livery-toolroom>=0.10.0",
22
+ "livery-workshop>=0.6.0",
23
+ ]
24
+
25
+ [[project.authors]]
26
+ name = "Willem Kokke"
27
+ email = "mail@willem.net"
28
+
29
+ [project.urls]
30
+ Repository = "https://github.com/willemkokke/livery"
31
+
32
+ [project.entry-points."workshop.extensions"]
33
+ mypy = "livery.extensions.mypy"
34
+
35
+ [tool.uv.build-backend]
36
+ module-name = "livery.extensions.mypy"
37
+ namespace = true
@@ -0,0 +1,44 @@
1
+ # Seeded from the package-python seeds at
2
+ # birth; this file is the workspace's own. Edit it directly:
3
+ # nothing rewrites it.
4
+ [build-system]
5
+ requires = ["uv_build>=0.11,<0.13"]
6
+ build-backend = "uv_build"
7
+
8
+ [project]
9
+ name = "livery-extensions-mypy"
10
+ version = "0.0.0"
11
+ description = "mypy as a check of the livery workshop: the type checker, on every platform, configured by the root mypy.ini."
12
+ readme = "README.md"
13
+ license = "MIT"
14
+ license-files = ["LICENSE"]
15
+ requires-python = ">=3.11"
16
+ authors = [{ name = "Willem Kokke", email = "mail@willem.net" }]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Typing :: Typed",
22
+ ]
23
+
24
+ dependencies = [
25
+ "livery-footman>=0.58.0",
26
+ "livery-toolroom>=0.10.0",
27
+ "livery-workshop>=0.6.0",
28
+ ]
29
+
30
+ [project.urls]
31
+ Repository = "https://github.com/willemkokke/livery"
32
+
33
+ # The name a workspace lists in [workspace] extensions, and the package
34
+ # whose extension.toml the workshop mounts it from. Nothing else: the
35
+ # extension adds no verb of its own, and nothing activates by being
36
+ # installed.
37
+ [project.entry-points."workshop.extensions"]
38
+ mypy = "livery.extensions.mypy"
39
+
40
+ [tool.uv.build-backend]
41
+ # PEP 420 namespace: the importable package is livery.extensions.mypy and
42
+ # there is no livery/__init__.py anywhere in this repository.
43
+ module-name = "livery.extensions.mypy"
44
+ namespace = true
@@ -0,0 +1,56 @@
1
+ """mypy's check: the type checker, once per platform, over the python files it claims.
2
+
3
+ The extension's ``extension.toml`` declares it and names the body here.
4
+ ``typecheck.mypy`` narrows by paths: the workshop names the paths a run
5
+ reaches ([livery.workshop.scoped_paths][]) and splits them into
6
+ calls ([livery.workshop.run_batched][]); a run that reaches the
7
+ whole calls mypy with no path, so it reads the ``files`` of
8
+ ``mypy.ini``. mypy has no all-platforms mode, so every call checks
9
+ linux, darwin and win32 in parallel, each with a cache of its own:
10
+ mypy's SQLite cache takes one writer. The check hands mypy the words
11
+ after ``--`` on its own verb (``fm typecheck.mypy -- --strict``), in
12
+ every platform's call. A body resolves its runner on this module when
13
+ it runs, so a test that replaces `run_typecheck` here sees its
14
+ replacement called.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from functools import partial
20
+
21
+ import livery.toolroom.tools as tools
22
+ from livery.footman import parallel, step
23
+ from livery.workshop import WHOLE, GateContext, run_batched, scoped_paths
24
+
25
+ #: The platforms every call checks, linux first: a bare ``mypy`` checks
26
+ #: linux, the platform ``mypy.ini`` names.
27
+ PLATFORMS = ("linux", "darwin", "win32")
28
+
29
+ #: Where the caches live, a directory per platform, with the workshop's
30
+ #: state and never in the root.
31
+ CACHE = ".workshop/.cache/mypy"
32
+
33
+
34
+ def run_typecheck(paths: tuple[str, ...] = (), arguments: tuple[str, ...] = ()) -> None:
35
+ """Type-check *paths* with mypy on every platform, in parallel.
36
+
37
+ No path checks the configured ``files``. Each platform's verdict is
38
+ its own, and every one gates. *arguments* go to mypy before the
39
+ paths.
40
+ """
41
+
42
+ def on(platform: str) -> None:
43
+ tools.mypy(
44
+ *arguments, *paths, platform=platform, cache_dir=f"{CACHE}/{platform}"
45
+ )
46
+
47
+ parallel(*(step(on, title=f"mypy_{platform}")(platform) for platform in PLATFORMS))
48
+
49
+
50
+ def judge_typecheck(ctx: GateContext) -> None:
51
+ """Type-check the paths the run reaches, or the configured files, per platform."""
52
+ chosen = scoped_paths(ctx, "typecheck.mypy")
53
+ if chosen == WHOLE:
54
+ run_typecheck(arguments=ctx.arguments)
55
+ return
56
+ run_batched(chosen, partial(run_typecheck, arguments=ctx.arguments))
@@ -0,0 +1,50 @@
1
+ <!-- Seeded from the package-base seeds at
2
+ birth; this file is the workspace's own. Edit it directly:
3
+ nothing rewrites it.
4
+ -->
5
+ # livery-extensions-mypy
6
+
7
+ mypy as a check of the workshop: `typecheck.mypy` type-checks the python
8
+ files a run reaches on linux, darwin and win32, since mypy has no
9
+ all-platforms mode. A workspace turns it on by listing the extension:
10
+
11
+ ```toml
12
+ [workspace]
13
+ extensions = ["mypy"]
14
+ ```
15
+
16
+ `fm typecheck` then runs it, and `fm check` runs it with the rest of the
17
+ gate. It reads the files its claims reach in the python packages: their
18
+ sources, tests and test support. A run that reaches every package checks
19
+ what the configuration names in `files`, the root's `tasks.py` and tests
20
+ among them; a run that reaches some checks their `src` and `tests`
21
+ directories. Each platform's run has a cache of its own under
22
+ `.workshop/.cache/mypy/`, and each one's verdict gates.
23
+ `fm typecheck.mypy -- --strict` hands mypy the words after `--`, in each
24
+ platform's call.
25
+
26
+ The workspace's namespace is fully strict. The tests and `tasks.py` are
27
+ checked as consumer code, so every test body type-checks without a
28
+ return annotation on every function.
29
+
30
+ ## The configuration
31
+
32
+ `fm sync` writes the root `mypy.ini`, and a bare `mypy` in the repository
33
+ reads the same file the check does: it checks linux and shares the check's
34
+ linux cache. The file names each python member's `src` and `tests` in
35
+ `files` and in `mypy_path`: in a namespace package without an
36
+ `__init__.py`, mypy derives a module's name from the `mypy_path` entries.
37
+
38
+ The file is the extension's: an edit outside its region is drift, which
39
+ `fm check --fix` puts back. The repository's own sections go inside the
40
+ region at the end:
41
+
42
+ ```ini
43
+ # -- workshop: region sections, yours to edit; the render keeps it --
44
+ [mypy-acme.generated.*]
45
+ ignore_errors = True
46
+ # -- workshop: end sections --
47
+ ```
48
+
49
+ The extension adds mypy to the dev group too, since mypy reads the
50
+ members' own stubs from the environment.
@@ -0,0 +1,12 @@
1
+ # This package's section of the workspace site, hand-authored.
2
+ # Labels map to pages relative to this docs/ tree, or to nested
3
+ # lists. Every authored page must appear here, and every entry must
4
+ # name a real page. A generator owns a block between `# nav:begin
5
+ # <name>` and `# nav:end <name>` markers (tasks, tools); the emitter's
6
+ # own sections, changelog, coverage and api, are blocks too: place a
7
+ # pair where one belongs, and a section without one lands after the
8
+ # authored entries, changelog and coverage ahead of the tasks block,
9
+ # api last.
10
+ nav = [
11
+ { "Index" = "index.md" },
12
+ ]
@@ -0,0 +1,61 @@
1
+ # Written by `{{ prog }} sync` from the mypy extension; the gate keeps it
2
+ # matching. Edit inside the region at the end, which is the repository's
3
+ # own; an edit anywhere else is drift.
4
+ #
5
+ # {{ namespace_package }}.* is fully strict; tests and tasks.py run the
6
+ # usage-checking half (check_untyped_defs, on through strict), so every
7
+ # test body type-checks as consumer code without demanding `-> None`
8
+ # on every def. Narrow suppressions live inline as
9
+ # `# type: ignore[code]` with a reason; pyright-only suppressions use
10
+ # `# pyright: ignore` so warn_unused_ignores keeps this checker's set
11
+ # honest.
12
+ [mypy]
13
+ files =
14
+ {% for package in py %} packages/{{ package.dir }}/src,
15
+ packages/{{ package.dir }}/tests,
16
+ {% endfor %}{% for path in root_tests %} {{ path }},
17
+ {% endfor %} tasks.py
18
+ # A PEP 420 namespace in a src layout: mypy derives a module's name
19
+ # from these bases, since no __init__.py trail leads to its root. The
20
+ # tests directories are bases too, as they are on pytest's pythonpath,
21
+ # so a test's helper module resolves for mypy as it does for pytest.
22
+ mypy_path =
23
+ typings{% for package in py %},
24
+ packages/{{ package.dir }}/src,
25
+ packages/{{ package.dir }}/tests{% endfor %}{% for path in root_tests %},
26
+ {{ path }}{% endfor %}
27
+ namespace_packages = True
28
+ explicit_package_bases = True
29
+ # A deterministic world, whatever host runs the check: a bare run
30
+ # checks linux, and the check adds darwin and win32, since mypy has no
31
+ # all-platforms mode.
32
+ platform = linux
33
+ python_version = {{ python_floor }}
34
+ # The cache lives with the workshop's state, never in the root; a bare
35
+ # run shares the check's linux one.
36
+ cache_dir = .workshop/.cache/mypy/linux
37
+ strict = True
38
+ disallow_untyped_defs = False
39
+ disallow_incomplete_defs = False
40
+ disallow_untyped_calls = False
41
+ disallow_untyped_decorators = False
42
+ # The public names' re-exports are the type-completeness check's and
43
+ # the public-surface test's to police.
44
+ implicit_reexport = True
45
+
46
+ [mypy-{{ namespace_package }}.*]
47
+ disallow_untyped_defs = True
48
+ disallow_incomplete_defs = True
49
+ disallow_untyped_calls = True
50
+ disallow_untyped_decorators = True
51
+
52
+ # The generated tool stubs carry the suppressions their generator
53
+ # placed for its own reading of each tool; which of them fire varies
54
+ # with flags this file does not share, and an unused one there is the
55
+ # generator's business, not drift.
56
+ [mypy-*.toolroom.stubs.*]
57
+ warn_unused_ignores = False
58
+
59
+ # The repository's own sections, a `[mypy-<module>]` each.
60
+ # -- workshop: region sections, yours to edit; the render keeps it --
61
+ # -- workshop: end sections --
@@ -0,0 +1,25 @@
1
+ # The mypy extension: the type checker, once per platform, over the python
2
+ # files it claims. Read at every mount; a check's code is imported when
3
+ # the check runs.
4
+
5
+ [extension]
6
+ api-version = 1
7
+ # Listed in the workspace's list alone: one configuration for every member.
8
+ levels = ["workspace"]
9
+
10
+ [checks.mypy.typecheck]
11
+ run = "livery.extensions.mypy._checks:judge_typecheck"
12
+ narrowing = "paths"
13
+ kinds = ["python"]
14
+ tools = ["mypy"]
15
+ arguments = true
16
+ claims = [
17
+ { category = "source", suffixes = [".py", ".pyi"] },
18
+ { category = "test", suffixes = [".py", ".pyi"] },
19
+ { category = "test-support", suffixes = [".py", ".pyi"] },
20
+ ]
21
+
22
+ # mypy reads the members' own stubs from the venv, so it rides the dev
23
+ # group beside the store's copy.
24
+ [contributions]
25
+ "python.dev-group" = ["mypy>=1.14"]