livery-extensions-basedpyright 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-basedpyright
3
+ Version: 0.0.0
4
+ Summary: basedpyright as a check of the livery workshop: the type checker, and type completeness as its option.
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-toolroom>=0.10.0
14
+ Requires-Dist: livery-workshop>=0.6.0
15
+ Requires-Python: >=3.11
16
+ Project-URL: Repository, https://github.com/willemkokke/livery
17
+ Description-Content-Type: text/markdown
18
+
19
+ <!-- Seeded from the package-python seeds at
20
+ birth; this file is the workspace's own. Edit it directly:
21
+ nothing rewrites it.
22
+ -->
23
+ # livery-extensions-basedpyright
24
+
25
+ basedpyright as a check of the livery workshop. Listed as `basedpyright` in
26
+ a workspace's `[workspace] extensions`, it registers `typecheck.basedpyright`
27
+ and writes the root `pyrightconfig.json` the check and the editor read;
28
+ listed as `basedpyright[typecomplete]`, it also registers
29
+ `typecomplete.basedpyright`.
@@ -0,0 +1,11 @@
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-basedpyright
6
+
7
+ basedpyright as a check of the livery workshop. Listed as `basedpyright` in
8
+ a workspace's `[workspace] extensions`, it registers `typecheck.basedpyright`
9
+ and writes the root `pyrightconfig.json` the check and the editor read;
10
+ listed as `basedpyright[typecomplete]`, it also registers
11
+ `typecomplete.basedpyright`.
@@ -0,0 +1,36 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "livery-extensions-basedpyright"
7
+ version = "0.0.0"
8
+ description = "basedpyright as a check of the livery workshop: the type checker, and type completeness as its option."
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-toolroom>=0.10.0",
21
+ "livery-workshop>=0.6.0",
22
+ ]
23
+
24
+ [[project.authors]]
25
+ name = "Willem Kokke"
26
+ email = "mail@willem.net"
27
+
28
+ [project.urls]
29
+ Repository = "https://github.com/willemkokke/livery"
30
+
31
+ [project.entry-points."workshop.extensions"]
32
+ basedpyright = "livery.extensions.basedpyright"
33
+
34
+ [tool.uv.build-backend]
35
+ module-name = "livery.extensions.basedpyright"
36
+ namespace = true
@@ -0,0 +1,43 @@
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-basedpyright"
10
+ version = "0.0.0"
11
+ description = "basedpyright as a check of the livery workshop: the type checker, and type completeness as its option."
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-toolroom>=0.10.0",
26
+ "livery-workshop>=0.6.0",
27
+ ]
28
+
29
+ [project.urls]
30
+ Repository = "https://github.com/willemkokke/livery"
31
+
32
+ # The name a workspace lists in [workspace] extensions, and the package
33
+ # whose extension.toml the workshop mounts it from. Nothing else: the
34
+ # extension adds no verb of its own, and nothing activates by being
35
+ # installed.
36
+ [project.entry-points."workshop.extensions"]
37
+ basedpyright = "livery.extensions.basedpyright"
38
+
39
+ [tool.uv.build-backend]
40
+ # PEP 420 namespace: the importable package is livery.extensions.basedpyright and
41
+ # there is no livery/__init__.py anywhere in this repository.
42
+ module-name = "livery.extensions.basedpyright"
43
+ namespace = true
@@ -0,0 +1,69 @@
1
+ """basedpyright's two checks: the type checker, and type completeness as its option.
2
+
3
+ The extension's ``extension.toml`` declares both and names the bodies
4
+ here. ``typecheck.basedpyright`` narrows by paths: the workshop names the
5
+ paths a run reaches ([livery.workshop.scoped_paths][]) and splits
6
+ them into calls ([livery.workshop.run_batched][]). A run that
7
+ reaches the whole calls basedpyright with no path, since basedpyright
8
+ reads ``.`` as every file under the root and ignores the configured
9
+ ``include`` then. ``typecomplete.basedpyright`` narrows by packages
10
+ ([livery.workshop.scoped_packages][]) and verifies the modules each
11
+ one declares public ([livery.workshop.public_modules][]); it
12
+ registers only when the workspace lists ``basedpyright[typecomplete]``.
13
+ Each check hands basedpyright the words after ``--`` on its own verb
14
+ (``fm typecheck.basedpyright -- --level error``). A body resolves its
15
+ runner on this module when it runs, so a test that replaces
16
+ `run_typecheck` or `run_typecomplete` here sees its replacement called.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from functools import partial
22
+
23
+ import livery.toolroom.tools as tools
24
+ from livery.workshop import (
25
+ WHOLE,
26
+ GateContext,
27
+ public_modules,
28
+ run_batched,
29
+ scoped_packages,
30
+ scoped_paths,
31
+ )
32
+
33
+
34
+ def run_typecheck(paths: tuple[str, ...] = (), arguments: tuple[str, ...] = ()) -> None:
35
+ """Type-check *paths* with basedpyright, its warnings gating as errors.
36
+
37
+ No path checks the configured whole: what ``pyrightconfig.json``
38
+ includes, less what it excludes. *arguments* go to basedpyright
39
+ before the paths.
40
+ """
41
+ tools.basedpyright(*arguments, *paths, warnings=True)
42
+
43
+
44
+ def run_typecomplete(modules: tuple[str, ...], arguments: tuple[str, ...] = ()) -> None:
45
+ """Verify that each of *modules* is 100% type-complete.
46
+
47
+ Every public symbol needs a fully known type; the exit code is the
48
+ verdict. The verifier reads the ``py.typed`` at the distribution's
49
+ root and follows what a module declares public, so a public package
50
+ a root's ``__init__`` declares is verified through it.
51
+ *arguments* go to basedpyright in each module's call.
52
+ """
53
+ for module in modules:
54
+ tools.basedpyright(*arguments, verifytypes=module, ignoreexternal=True)
55
+
56
+
57
+ def judge_typecheck(ctx: GateContext) -> None:
58
+ """Type-check the paths the run reaches, or the configured whole."""
59
+ chosen = scoped_paths(ctx, "typecheck.basedpyright")
60
+ if chosen == WHOLE:
61
+ run_typecheck(arguments=ctx.arguments)
62
+ return
63
+ run_batched(chosen, partial(run_typecheck, arguments=ctx.arguments))
64
+
65
+
66
+ def judge_typecomplete(ctx: GateContext) -> None:
67
+ """Verify the public modules of each package the run reaches."""
68
+ for package in scoped_packages(ctx, "typecomplete.basedpyright"):
69
+ run_typecomplete(public_modules(package), ctx.arguments)
@@ -0,0 +1,75 @@
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-basedpyright
6
+
7
+ basedpyright as a check of the workshop: `typecheck.basedpyright`
8
+ type-checks the python files a run reaches, its warnings gating as errors.
9
+ A workspace turns it on by listing the extension:
10
+
11
+ ```toml
12
+ [workspace]
13
+ extensions = ["basedpyright"]
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 includes, the root's `tasks.py` and tests among it;
20
+ a run that reaches some checks their `src` and `tests` directories.
21
+ `fm typecheck.basedpyright -- --level error` hands basedpyright the words
22
+ after `--`.
23
+
24
+ ## Type completeness
25
+
26
+ Listed with its option, the extension also registers
27
+ `typecomplete.basedpyright`:
28
+
29
+ ```toml
30
+ [workspace]
31
+ extensions = ["basedpyright[typecomplete]"]
32
+ ```
33
+
34
+ It verifies that each package's public API has a fully known type, through
35
+ `basedpyright --verifytypes`. A package's public API is what its roots
36
+ declare: a root that is a regular package declares it in its `__init__`,
37
+ its public packages too (imported under `TYPE_CHECKING` and listed in
38
+ `__all__`). A namespace root, one with no `__init__`, has nothing public
39
+ and verifies nothing. The verifier reads the `py.typed` at the
40
+ distribution's root.
41
+
42
+ A package turns either check off in its own contract:
43
+
44
+ ```toml
45
+ [checks.basedpyright.typecomplete]
46
+ enabled = false
47
+ ```
48
+
49
+ ## The configuration
50
+
51
+ `fm sync` writes the root `pyrightconfig.json`, and a bare `basedpyright`
52
+ in the repository, and the editor's language server, read the same file
53
+ the check does. It names what the whole includes and excludes, the
54
+ environment in `.venv`, the stubs in `typings/`, the python version the
55
+ workspace supports, and the checking mode.
56
+
57
+ The file is the extension's: an edit outside its region is drift, which
58
+ `fm check --fix` puts back. The repository's own settings go inside the
59
+ region at the end, each line ending with a comma. A key set there wins
60
+ over the same key above it, since basedpyright reads the last one:
61
+
62
+ ```json
63
+ // -- workshop: region settings, yours to edit; the render keeps it --
64
+ "executionEnvironments": [
65
+ { "root": "packages/acme/tests", "reportPrivateImportUsage": false },
66
+ ],
67
+ // -- workshop: end settings --
68
+ ```
69
+
70
+ A workspace that lists the extension recommends basedpyright's editor
71
+ extension, `detachhead.basedpyright`, in `.vscode/extensions.json`, and
72
+ turns the editor's default python language server off in
73
+ `.vscode/settings.json` (`"python.languageServer": "None"`): the type
74
+ checker that answers in the editor is the one this file configures, and
75
+ no second one answers with settings of its own.
@@ -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,29 @@
1
+ {
2
+ // Written by `{{ prog }} sync` from the basedpyright extension; the
3
+ // gate keeps it matching. Edit inside the region at the end, which is
4
+ // the repository's own; an edit anywhere else is drift.
5
+ "include": [{% if packages %}"packages", {% endif %}{% for path in root_tests %}"{{ path }}", {% endfor %}"tasks.py"],
6
+ // A conan recipe is conan's input, read by conan's own interpreter
7
+ // where the conan package lives; the workspace venv never has it, so
8
+ // the checker that reads the whole tree skips the recipes. The cpp
9
+ // members are skipped whole: their kind type-checks nothing. A
10
+ // documentation example is judged for its names by lint and run by
11
+ // the examples check; it is not typed code.
12
+ "exclude": [{% for package in native %}"packages/{{ package.dir }}", {% endfor %}"packages/**/conanfile.py", "packages/**/docs/examples"],
13
+ // The editor and the command line resolve the same environment: the
14
+ // workspace members are editable installs in .venv, so basedpyright
15
+ // looks there whatever interpreter the editor has selected.
16
+ "venvPath": ".",
17
+ "venv": ".venv",
18
+ // The tool stubs `{{ runner_prog }} tools.restub` writes; the default
19
+ // stub path, named so every type checker visibly reads one directory.
20
+ "stubPath": "typings",
21
+ "pythonVersion": "{{ python_floor }}",
22
+ "typeCheckingMode": "standard",
23
+ "reportMissingModuleSource": false,
24
+ // What the listed extensions contribute.
25
+ {{ contributed_entries }} // The repository's own settings, each line ending with a comma. A key
26
+ // set here wins over the same key above: basedpyright reads the last.
27
+ // -- workshop: region settings, yours to edit; the render keeps it --
28
+ // -- workshop: end settings --
29
+ }
@@ -0,0 +1,42 @@
1
+ # The basedpyright extension: the type checker, and type completeness as
2
+ # its option. Read at every mount; a check's code is imported when the
3
+ # 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
+ # Off unless the workspace lists it, `basedpyright[typecomplete]`.
11
+ [options]
12
+ typecomplete = "verifies that every package's public API is type-complete"
13
+
14
+ [checks.basedpyright.typecheck]
15
+ run = "livery.extensions.basedpyright._checks:judge_typecheck"
16
+ narrowing = "paths"
17
+ kinds = ["python"]
18
+ tools = ["basedpyright"]
19
+ arguments = true
20
+ editor-extension = "detachhead.basedpyright"
21
+ claims = [
22
+ { category = "source", suffixes = [".py", ".pyi"] },
23
+ { category = "test", suffixes = [".py", ".pyi"] },
24
+ { category = "test-support", suffixes = [".py", ".pyi"] },
25
+ ]
26
+
27
+ # The type checker that answers in the editor is the one this workspace
28
+ # configures: the editor's default python language server is off, so it
29
+ # adds no second verdict with settings of its own.
30
+ [checks.basedpyright.typecheck.fragments]
31
+ ".vscode/settings.json" = '''
32
+ {"python.languageServer": "None"}
33
+ '''
34
+
35
+ [checks.basedpyright.typecomplete]
36
+ run = "livery.extensions.basedpyright._checks:judge_typecomplete"
37
+ narrowing = "packages"
38
+ kinds = ["python"]
39
+ tools = ["basedpyright"]
40
+ arguments = true
41
+ listed-with = "typecomplete"
42
+ claims = [{ category = "source", suffixes = [".py", ".pyi"] }]