typecheck-runner 0.1.2__py3-none-any.whl

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
+ """
2
+ Top level API (:mod:`typecheck_runner`)
3
+ =======================================
4
+ """
5
+
6
+ from importlib.metadata import PackageNotFoundError
7
+ from importlib.metadata import version as _version
8
+
9
+ try:
10
+ __version__ = _version("typecheck-runner")
11
+ except PackageNotFoundError: # pragma: no cover
12
+ __version__ = "999"
13
+
14
+
15
+ __author__ = """William P. Krekelberg"""
16
+ __email__ = "wpk@nist.gov"
17
+
18
+
19
+ __all__ = [
20
+ "__version__",
21
+ ]
@@ -0,0 +1,7 @@
1
+ """Make callable via `python -m typecheck_runner`"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typecheck_runner.typecheck_runner import main
6
+
7
+ raise SystemExit(main())
File without changes
@@ -0,0 +1,426 @@
1
+ """
2
+ Interface to type checkers (mypy, (based)pyright, ty, pyrefly).
3
+
4
+ This handles locating python-version and python-executable. This allows for
5
+ running centrally installed (or via uvx) type checkers against a given virtual
6
+ environment.
7
+ """
8
+ # pylint: disable=duplicate-code
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ import os
14
+ import shlex
15
+ import shutil
16
+ import subprocess
17
+ import sys
18
+ from argparse import ArgumentParser
19
+ from pathlib import Path
20
+ from time import perf_counter
21
+ from typing import TYPE_CHECKING
22
+
23
+ from packaging.requirements import Requirement
24
+
25
+ if TYPE_CHECKING:
26
+ from collections.abc import Sequence
27
+ from logging import Logger
28
+
29
+
30
+ FORMAT = "[typecheck-runner %(levelname)s] %(message)s"
31
+ logger: Logger = logging.getLogger(__name__)
32
+
33
+
34
+ # * Utilities -----------------------------------------------------------------
35
+ def _setup_logging(
36
+ verbosity: int = 0,
37
+ stdout: bool = False,
38
+ ) -> None: # pragma: no cover
39
+ """Setup logging."""
40
+ level_number = max(0, logging.WARNING - 10 * verbosity)
41
+ logger.setLevel(level_number)
42
+
43
+ # Silence noisy loggers
44
+ logging.getLogger("sh").setLevel(logging.WARNING)
45
+
46
+ if stdout:
47
+ handler = logging.StreamHandler(sys.stdout)
48
+ logging.basicConfig(level=logging.WARNING, format=FORMAT, handlers=[handler])
49
+ else:
50
+ logging.basicConfig(level=logging.WARNING, format=FORMAT)
51
+
52
+
53
+ # * Runner --------------------------------------------------------------------
54
+
55
+
56
+ def _infer_venv_location() -> Path:
57
+ for var in ("VIRTUAL_ENV", "CONDA_PREFIX"):
58
+ if venv := os.getenv(var, ""):
59
+ logger.debug("Inferred venv location %s", venv)
60
+ return Path(venv).absolute()
61
+
62
+ for d in (".venv",):
63
+ if (path := Path(d)).is_dir():
64
+ logger.debug("Inferred venv location %s", path)
65
+ return path.absolute()
66
+
67
+ msg = "Could not infer virtual environment"
68
+ raise ValueError(msg)
69
+
70
+
71
+ def _get_python_executable_from_venv(
72
+ location: Path,
73
+ ) -> Path:
74
+ executable = "python.exe" if sys.platform.startswith("win") else "python"
75
+ for d in ("bin", "Scripts"):
76
+ if (path := location / d / executable).exists():
77
+ logger.debug("Inferred python-executable %s", path)
78
+ return path.absolute()
79
+
80
+ msg = f"No virtual environment found under {location}"
81
+ raise ValueError(msg)
82
+
83
+
84
+ def _get_python_executable(
85
+ python_executable: Path | None, venv: Path | None, infer_venv: bool
86
+ ) -> Path | None:
87
+ if venv is None and infer_venv:
88
+ venv = _infer_venv_location()
89
+
90
+ if venv is not None:
91
+ return _get_python_executable_from_venv(venv)
92
+
93
+ return python_executable
94
+
95
+
96
+ def _get_python_values(
97
+ python_version: str | None,
98
+ python_executable: Path | None,
99
+ no_python_version: bool,
100
+ no_python_executable: bool,
101
+ ) -> tuple[str | None, Path | None]:
102
+ if python_version is None and not no_python_version:
103
+ if python_executable is not None:
104
+ # infer python version from python_executable
105
+ logger.debug(
106
+ "Calculate python-version from executable %s", python_executable
107
+ )
108
+ script = "import sys; info = sys.version_info; print(f'{info.major}.{info.minor}')"
109
+ python_version = (
110
+ subprocess.check_output([python_executable, "-c", script])
111
+ .decode("utf-8")
112
+ .strip()
113
+ )
114
+ else:
115
+ python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
116
+
117
+ if python_executable is None and not no_python_executable:
118
+ python_executable = Path(sys.executable)
119
+
120
+ return python_version, python_executable
121
+
122
+
123
+ def _maybe_add_check_argument(checker: str, args: list[str]) -> list[str]:
124
+ if checker in {"ty", "pyrefly"} and "check" not in args:
125
+ return ["check", *args]
126
+ return args
127
+
128
+
129
+ def _parse_command(
130
+ command: str,
131
+ no_uvx: bool,
132
+ uvx_delimiter: str,
133
+ uvx_options: Sequence[str],
134
+ ) -> tuple[str, list[str]]:
135
+ command, *args = shlex.split(command)
136
+
137
+ if no_uvx:
138
+ path = Path(command).expanduser()
139
+ checker = path.name
140
+ path_str = str(path)
141
+ return checker, [
142
+ shutil.which(path_str) or path_str,
143
+ *_maybe_add_check_argument(checker, args),
144
+ ]
145
+
146
+ req = Requirement(command)
147
+ checker = req.name
148
+
149
+ idx = args.index(uvx_delimiter) if uvx_delimiter in args else len(args)
150
+ checker_args = args[:idx]
151
+ uvx_args = args[idx + 1 :]
152
+
153
+ args = [
154
+ "uvx",
155
+ *uvx_options,
156
+ *uvx_args,
157
+ command,
158
+ *_maybe_add_check_argument(checker, checker_args),
159
+ ]
160
+ return checker, args
161
+
162
+
163
+ PYRIGHT_LIKE_CHECKERS = {"pyright", "basedpyright"}
164
+
165
+
166
+ def _get_python_flags(
167
+ checker: str,
168
+ python_version: str | None,
169
+ python_executable: str | Path | None,
170
+ ) -> list[str]:
171
+ out: list[str] = []
172
+ if python_version is not None:
173
+ version_flag = (
174
+ "pythonversion" if checker in PYRIGHT_LIKE_CHECKERS else "python-version"
175
+ )
176
+ out.append(f"--{version_flag}={python_version}")
177
+
178
+ if python_executable is not None:
179
+ if checker in PYRIGHT_LIKE_CHECKERS:
180
+ python_flag = "pythonpath"
181
+ elif checker == "ty":
182
+ python_flag = "python"
183
+ elif checker == "pyrefly":
184
+ python_flag = "python-interpreter-path"
185
+ elif checker == "mypy":
186
+ # default to mypy
187
+ python_flag = "python-executable"
188
+ else:
189
+ msg = f"Unknown checker {checker}"
190
+ raise ValueError(msg)
191
+ out.append(f"--{python_flag}={python_executable}")
192
+
193
+ return out
194
+
195
+
196
+ def _run_checker(
197
+ *args: str,
198
+ dry_run: bool = False,
199
+ ) -> int:
200
+ cleaned_args = [os.fsdecode(arg) for arg in args]
201
+ full_cmd = shlex.join(cleaned_args)
202
+ logger.info("Command: %s", full_cmd)
203
+
204
+ if dry_run:
205
+ return 0
206
+
207
+ start_time = perf_counter()
208
+ returncode = subprocess.call(cleaned_args)
209
+ logger.info("Execution time: %s", perf_counter() - start_time)
210
+ if returncode:
211
+ logger.error("Failed with exit code: %s", returncode)
212
+
213
+ return returncode
214
+
215
+
216
+ # * Application ---------------------------------------------------------------
217
+ def get_parser() -> ArgumentParser:
218
+ """Get argparser."""
219
+ parser = ArgumentParser(description="Run executable using uvx.")
220
+ _ = parser.add_argument("--version", action="store_true", help="Display version.")
221
+
222
+ _ = parser.add_argument(
223
+ "-c",
224
+ "--check",
225
+ dest="checkers",
226
+ default=[],
227
+ action="append",
228
+ help="""
229
+ Checker to run. This can be a string with options to the checker. For
230
+ example, ``--check "mypy --verbose"`` runs the checker the command
231
+ ``mypy --verbose``. Options after ``uvx_delimiter`` (default ``"--"``,
232
+ see ``--uvx-delimiter`` options) are treated as ``uvx`` options. For
233
+ example, passing ``--check "mypy --verbose -- --reinstall"`` will run
234
+ ``uvx --reinstall mypy --verbose``. Can be specified multiple times.
235
+ """,
236
+ )
237
+ _ = parser.add_argument(
238
+ "--python-executable",
239
+ dest="python_executable",
240
+ default=None,
241
+ type=Path,
242
+ help="""
243
+ Path to python executable. Defaults to ``sys.executable``. This is
244
+ passed to ``--python-executable`` (mypy), ``--pythonpath`` in
245
+ ((based)pyright), ``--python`` (ty), ``--python-interpreter-path``
246
+ (pyrefly), and ignored for pylint.
247
+ """,
248
+ )
249
+ _ = parser.add_argument(
250
+ "--python-version",
251
+ dest="python_version",
252
+ default=None,
253
+ type=str,
254
+ help="""
255
+ Python version (x.y) to typecheck against. Defaults to
256
+ ``{sys.version_info.major}.{sys.version_info.minor}``. This is passed
257
+ to ``--pythonversion`` in pyright and ``--python-version`` otherwise.
258
+ """,
259
+ )
260
+ _ = parser.add_argument(
261
+ "--no-python-executable",
262
+ action="store_true",
263
+ help="""
264
+ Do not infer ``python_executable``
265
+ """,
266
+ )
267
+ _ = parser.add_argument(
268
+ "--no-python-version",
269
+ action="store_true",
270
+ help="""
271
+ Do not infer ``python_version``.
272
+ """,
273
+ )
274
+
275
+ _ = parser.add_argument(
276
+ "--venv",
277
+ type=Path,
278
+ help="""
279
+ Use specified vitualenvironment location
280
+ """,
281
+ )
282
+ _ = parser.add_argument(
283
+ "--infer-venv",
284
+ action="store_true",
285
+ help="""
286
+ Infer virtual environment location. Checks in order environment variables ``VIRTUAL_ENV``, ``CONDA_PREFIX``, directory ``.venv``.
287
+ """,
288
+ )
289
+ _ = parser.add_argument(
290
+ "--constraints",
291
+ dest="constraints",
292
+ default=[],
293
+ action="append",
294
+ type=Path,
295
+ help="""
296
+ Constraints (requirements.txt) specs for checkers. Can specify multiple
297
+ times. Passed to ``uvx --constraints=...``.
298
+ """,
299
+ )
300
+ _ = parser.add_argument(
301
+ "-v",
302
+ "--verbose",
303
+ dest="verbosity",
304
+ action="count",
305
+ default=0,
306
+ help="Set verbosity level. Pass multiple times to up level.",
307
+ )
308
+ _ = parser.add_argument(
309
+ "--stdout", action="store_true", help="logger information to stdout"
310
+ )
311
+ _ = parser.add_argument(
312
+ "--allow-errors",
313
+ action="store_true",
314
+ help="""
315
+ If passed, return ``0`` regardless of checker status.
316
+ """,
317
+ )
318
+ _ = parser.add_argument(
319
+ "--fail-fast",
320
+ action="store_true",
321
+ help="""
322
+ Exit on first failed checker. Default is to run all checkers, even if
323
+ they fail.
324
+ """,
325
+ )
326
+ _ = parser.add_argument(
327
+ "--dry-run", action="store_true", help="""Perform dry run."""
328
+ )
329
+ _ = parser.add_argument(
330
+ "--no-uvx",
331
+ dest="no_uvx",
332
+ action="store_true",
333
+ help="""
334
+ If ``--no-uvx`` is passed, assume typecheckers are in the current
335
+ python environment. Default is to invoke typecheckers using `uvx`.
336
+ """,
337
+ )
338
+ _ = parser.add_argument(
339
+ "--uvx-options",
340
+ default="",
341
+ help="""
342
+ Extra options to pass to ``uvx``. Note that you may have to escape the
343
+ first option. For example, ``--uvx-options "\\--verbose --reinstall"
344
+ """,
345
+ )
346
+ _ = parser.add_argument(
347
+ "--uvx-delimiter",
348
+ default="--",
349
+ help="""
350
+ Delimiter between typechecker command arguments and ``uvx`` arguments.
351
+ See ``--check`` option.
352
+ """,
353
+ )
354
+ _ = parser.add_argument(
355
+ "args",
356
+ type=str,
357
+ nargs="*",
358
+ default=[],
359
+ help="Extra files/arguments passed to all checkers.",
360
+ )
361
+
362
+ return parser
363
+
364
+
365
+ def main(args: Sequence[str] | None = None) -> int:
366
+ """Main script."""
367
+ parser = get_parser()
368
+ options = parser.parse_args(args)
369
+
370
+ if options.version:
371
+ from typecheck_runner import __version__
372
+
373
+ print("typecheck-runner", __version__) # noqa: T201
374
+ return 0
375
+
376
+ if not options.checkers:
377
+ parser.print_help()
378
+ return 2
379
+
380
+ _setup_logging(options.verbosity, options.stdout)
381
+
382
+ # possibly infer python executable from location
383
+ python_version, python_executable = _get_python_values(
384
+ python_version=options.python_version,
385
+ python_executable=_get_python_executable(
386
+ options.python_executable, options.venv, options.infer_venv
387
+ ),
388
+ no_python_version=options.no_python_version,
389
+ no_python_executable=options.no_python_executable,
390
+ )
391
+
392
+ logger.info("python_executable %s", python_executable)
393
+ logger.info("python_version %s", python_version)
394
+ logger.debug("checkers: %s", options.checkers)
395
+ logger.debug("args: %s", options.args)
396
+
397
+ uvx_options = [
398
+ *shlex.split(options.uvx_options),
399
+ *(f"--constraints={c}" for c in options.constraints),
400
+ ]
401
+
402
+ code = 0
403
+ for command in options.checkers:
404
+ checker, args = _parse_command(
405
+ command,
406
+ no_uvx=options.no_uvx,
407
+ uvx_delimiter=options.uvx_delimiter,
408
+ uvx_options=uvx_options,
409
+ )
410
+ logger.info("Checker: %s", checker)
411
+ checker_code = _run_checker(
412
+ *args,
413
+ *_get_python_flags(checker, python_version, python_executable),
414
+ *options.args,
415
+ dry_run=options.dry_run,
416
+ )
417
+ if options.fail_fast and checker_code:
418
+ return checker_code
419
+
420
+ code += checker_code
421
+
422
+ return 0 if options.allow_errors else code
423
+
424
+
425
+ if __name__ == "__main__":
426
+ raise SystemExit(main())
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: typecheck-runner
3
+ Version: 0.1.2
4
+ Summary: Unified api to multiple typecheckers
5
+ Keywords: typecheck-runner
6
+ Author: William P. Krekelberg
7
+ Author-email: William P. Krekelberg <wpk@nist.gov>
8
+ License-Expression: NIST-PD
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: Implementation :: CPython
20
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
21
+ Classifier: Topic :: Utilities
22
+ Classifier: Typing :: Typed
23
+ Requires-Dist: packaging>=25.0
24
+ Requires-Python: >=3.10
25
+ Project-URL: Homepage, https://github.com/wpk-nist-gov/typecheck-runner
26
+ Description-Content-Type: text/markdown
27
+
28
+ <!-- markdownlint-disable MD041 -->
29
+
30
+ <!-- prettier-ignore-start -->
31
+ [![Repo][repo-badge]][repo-link]
32
+ [![PyPI license][license-badge]][license-link]
33
+ [![PyPI version][pypi-badge]][pypi-link]
34
+ [![Code style: ruff][ruff-badge]][ruff-link]
35
+ [![uv][uv-badge]][uv-link]
36
+
37
+ <!--
38
+ For more badges, see
39
+ https://shields.io/category/other
40
+ https://naereen.github.io/badges/
41
+ [pypi-badge]: https://badge.fury.io/py/typecheck-runner
42
+ -->
43
+
44
+ [ruff-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
45
+ [ruff-link]: https://github.com/astral-sh/ruff
46
+ [uv-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json
47
+ [uv-link]: https://github.com/astral-sh/uv
48
+ [pypi-badge]: https://img.shields.io/pypi/v/typecheck-runner
49
+ [pypi-link]: https://pypi.org/project/typecheck-runner
50
+ [repo-badge]: https://img.shields.io/badge/--181717?logo=github&logoColor=ffffff
51
+ [repo-link]: https://github.com/wpk-nist-gov/typecheck-runner
52
+ [license-badge]: https://img.shields.io/pypi/l/typecheck-runner?color=informational
53
+ [license-link]: https://github.com/wpk-nist-gov/typecheck-runner/blob/main/LICENSE
54
+ [changelog-link]: https://github.com/wpk-nist-gov/typecheck-runner/blob/main/CHANGELOG.md
55
+
56
+ <!-- other links -->
57
+
58
+ [mypy]: https://github.com/python/mypy
59
+ [pyright]: https://github.com/microsoft/pyright
60
+ [basedpyright]: https://github.com/DetachHead/basedpyright
61
+ [ty]: https://github.com/astral-sh/ty
62
+ [pyrefly]: https://github.com/microsoft/pyright
63
+ <!-- [pre-commit]: https://pre-commit.com/ -->
64
+ <!-- [prek]: https://github.com/j178/prek -->
65
+
66
+ <!-- prettier-ignore-end -->
67
+
68
+ # `typecheck-runner`
69
+
70
+ A unified way to run globally installed typecheckers against a specified virtual
71
+ environment.
72
+
73
+ ## Overview
74
+
75
+ I prefer to invoke globally managed type checkers against specified virtual
76
+ environments. For cases where python versions are checked against (with, for
77
+ example tox or nox), this prevents each virtual environment from having to
78
+ contain a type checker. Each type checker ([mypy], [pyright], [basedpyright],
79
+ [ty], and [pyrefly]) has it's own particular flags to specify the python
80
+ executable and the python version. `typecheck-runner` unifies these flags. Also,
81
+ by default, `typecheck-runner` invokes the type checker using
82
+ [`uvx`](https://docs.astral.sh/uv/guides/tools/), which installs the type
83
+ checker if needed.
84
+
85
+ ## Usage
86
+
87
+ ### Install into virtual environment
88
+
89
+ The easiest way to use `typecheck-runner` is to install it into the virtual
90
+ environment you'd like to test against using something like
91
+
92
+ ```bash
93
+ pip install typecheck-runner
94
+ ```
95
+
96
+ from the virtual environment of interest. To invoke a type checker against the
97
+ virtual environment, assuming the python executable of the virtual environment
98
+ is located at `/path/to/venv/bin` with python version `3.13`, use
99
+
100
+ ```bash
101
+ typecheck-runner --check mypy
102
+ # runs: uvx mypy --python-version=3.13 --python-executable=/path/to/venv/bin
103
+ ```
104
+
105
+ Where the commented line shows the command run. Specifying `--no-uvx` will
106
+ instead invoke the type checker without `uvx`, so the type checker must already
107
+ be installed.
108
+
109
+ You can specify multiple checkers with multiple `--check` flags. To specify
110
+ options to `uvx` for each checker, pass options after `--uvx-delimiter` which
111
+ defaults to `--`. For example:
112
+
113
+ ```bash
114
+ typecheck-runner --check "mypy --verbose -- --reinstall"
115
+ # runs: uvx --reinstall mypy --verbose
116
+ ```
117
+
118
+ You can specify `uvx` options to all checkers using the `--uvx-options` flag.
119
+
120
+ ### Specify virtual environment
121
+
122
+ You can also use a globally installed `typecheck-runner` and specify which
123
+ virtual environment to test over using `--venv` or `--infer-venv` options. For
124
+ example, you can use:
125
+
126
+ ```bash
127
+ uvx typecheck-runner --venv .venv --check mypy
128
+ # run for example (if .venv current directory with version 3.14)
129
+ # uvx mypy --python-version=3.14 --python-executable=.venv/bin/python
130
+ ```
131
+
132
+ Using `--infer-venv` will attempt to infer the virtual environment from, in
133
+ order, environment variables `VIRTUAL_ENV`, `CONDA_PREFIX`, and finally `.venv`
134
+ in current directory.
135
+
136
+ ## Options
137
+
138
+ <!-- markdownlint-disable-next-line MD013 -->
139
+ <!-- [[[cog
140
+ import sys
141
+ sys.path.insert(0, ".")
142
+ from tools.cog_utils import wrap_command, get_pyproject, run_command, cat_lines
143
+ sys.path.pop(0)
144
+ ]]] -->
145
+ <!-- [[[end]]] -->
146
+
147
+ <!-- prettier-ignore-start -->
148
+ <!-- markdownlint-disable MD013 -->
149
+ <!-- [[[cog run_command("typecheck-runner --help", include_cmd=False, wrapper="restructuredtext")]]] -->
150
+
151
+ ```restructuredtext
152
+ usage: typecheck-runner [-h] [--version] [-c CHECKERS]
153
+ [--python-executable PYTHON_EXECUTABLE]
154
+ [--python-version PYTHON_VERSION] [--no-python-executable]
155
+ [--no-python-version] [--venv VENV] [--infer-venv]
156
+ [--constraints CONSTRAINTS] [-v] [--stdout] [--allow-errors]
157
+ [--fail-fast] [--dry-run] [--no-uvx] [--uvx-options UVX_OPTIONS]
158
+ [--uvx-delimiter UVX_DELIMITER]
159
+ [args ...]
160
+
161
+ Run executable using uvx.
162
+
163
+ positional arguments:
164
+ args Extra files/arguments passed to all checkers.
165
+
166
+ options:
167
+ -h, --help show this help message and exit
168
+ --version Display version.
169
+ -c, --check CHECKERS Checker to run. This can be a string with options to the
170
+ checker. For example, ``--check "mypy --verbose"`` runs the
171
+ checker the command ``mypy --verbose``. Options after
172
+ ``uvx_delimiter`` (default ``"--"``, see ``--uvx-delimiter``
173
+ options) are treated as ``uvx`` options. For example, passing
174
+ ``--check "mypy --verbose -- --reinstall"`` will run ``uvx
175
+ --reinstall mypy --verbose``. Can be specified multiple times.
176
+ --python-executable PYTHON_EXECUTABLE
177
+ Path to python executable. Defaults to ``sys.executable``. This
178
+ is passed to ``--python-executable`` (mypy), ``--pythonpath`` in
179
+ ((based)pyright), ``--python`` (ty), ``--python-interpreter-
180
+ path`` (pyrefly), and ignored for pylint.
181
+ --python-version PYTHON_VERSION
182
+ Python version (x.y) to typecheck against. Defaults to
183
+ ``{sys.version_info.major}.{sys.version_info.minor}``. This is
184
+ passed to ``--pythonversion`` in pyright and ``--python-
185
+ version`` otherwise.
186
+ --no-python-executable
187
+ Do not infer ``python_executable``
188
+ --no-python-version Do not infer ``python_version``.
189
+ --venv VENV Use specified vitualenvironment location
190
+ --infer-venv Infer virtual environment location. Checks in order environment
191
+ variables ``VIRTUAL_ENV``, ``CONDA_PREFIX``, directory
192
+ ``.venv``.
193
+ --constraints CONSTRAINTS
194
+ Constraints (requirements.txt) specs for checkers. Can specify
195
+ multiple times. Passed to ``uvx --constraints=...``.
196
+ -v, --verbose Set verbosity level. Pass multiple times to up level.
197
+ --stdout logger information to stdout
198
+ --allow-errors If passed, return ``0`` regardless of checker status.
199
+ --fail-fast Exit on first failed checker. Default is to run all checkers,
200
+ even if they fail.
201
+ --dry-run Perform dry run.
202
+ --no-uvx If ``--no-uvx`` is passed, assume typecheckers are in the
203
+ current python environment. Default is to invoke typecheckers
204
+ using `uvx`.
205
+ --uvx-options UVX_OPTIONS
206
+ Extra options to pass to ``uvx``. Note that you may have to
207
+ escape the first option. For example, ``--uvx-options
208
+ "\--verbose --reinstall"
209
+ --uvx-delimiter UVX_DELIMITER
210
+ Delimiter between typechecker command arguments and ``uvx``
211
+ arguments. See ``--check`` option.
212
+ ```
213
+
214
+ <!-- [[[end]]] -->
215
+ <!-- prettier-ignore-end -->
216
+
217
+ ## Status
218
+
219
+ This package is actively used by the author. Please feel free to create a pull
220
+ request for wanted features and suggestions!
221
+
222
+ <!-- end-docs -->
223
+
224
+ ## Installation
225
+
226
+ <!-- start-installation -->
227
+
228
+ Use one of the following
229
+
230
+ ```bash
231
+ pip install typecheck-runner
232
+ uv pip install typecheck-runner
233
+ uv add typecheck-runner
234
+ ...
235
+ ```
236
+
237
+ <!-- end-installation -->
238
+
239
+ ## What's new?
240
+
241
+ See [changelog][changelog-link].
242
+
243
+ ## License
244
+
245
+ This is free software. See [LICENSE][license-link].
246
+
247
+ ## Related work
248
+
249
+ Any other stuff to mention....
250
+
251
+ ## Contact
252
+
253
+ The author can be reached at <wpk@nist.gov>.
254
+
255
+ ## Credits
256
+
257
+ This package was created using
258
+ [Cookiecutter](https://github.com/audreyr/cookiecutter) with the
259
+ [usnistgov/cookiecutter-nist-python](https://github.com/usnistgov/cookiecutter-nist-python)
260
+ template.
@@ -0,0 +1,9 @@
1
+ typecheck_runner/__init__.py,sha256=bN5LuK_PNk5YFr2rdgX1CwJWHRMtspp30M1SHd2uhbE,423
2
+ typecheck_runner/__main__.py,sha256=rRzOwUCzMPhYnn4hruIKPM_vSOddm9rCZ6dF5SW4_m0,167
3
+ typecheck_runner/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ typecheck_runner/typecheck_runner.py,sha256=o21akaFiaacdkki2dRbZ7fdTvZ2hqIUzEd1Yg2JmNF8,12588
5
+ typecheck_runner-0.1.2.dist-info/licenses/LICENSE,sha256=j_sUyRmuUbF_c9KR7g_uTdRv-cBn65wjYQpmusAzyT0,1645
6
+ typecheck_runner-0.1.2.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
7
+ typecheck_runner-0.1.2.dist-info/entry_points.txt,sha256=DnC_eOsN1KeMB9CKwGKR4DJ7vcbAExz1JlNBy1x9PPE,77
8
+ typecheck_runner-0.1.2.dist-info/METADATA,sha256=wU2JMhkwg1oECleZwgSm_mJpVs3JUk-9hi7_8kRsSmM,10094
9
+ typecheck_runner-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.8.24
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ typecheck-runner = typecheck_runner.typecheck_runner:main
3
+
@@ -0,0 +1,24 @@
1
+ This software was developed by employees of the National Institute of Standards
2
+ and Technology (NIST), an agency of the Federal Government. Pursuant to title 17
3
+ United States Code Section 105, works of NIST employees are not subject to
4
+ copyright protection in the United States and are considered to be in the public
5
+ domain. Permission to freely use, copy, modify, and distribute this software and
6
+ its documentation without fee is hereby granted, provided that this notice and
7
+ disclaimer of warranty appears in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
10
+ EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
11
+ THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
12
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
13
+ INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
14
+ SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
15
+ SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
16
+ INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR
17
+ IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
18
+ CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
19
+ PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
20
+ OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
21
+
22
+ Distributions of NIST software should also include copyright and licensing
23
+ statements of any third-party software that are legally bundled with the code in
24
+ compliance with the conditions of those licenses.