pytscheck 0.1.0__py3-none-win_arm64.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.
Files changed (150) hide show
  1. pytscheck/__init__.py +89 -0
  2. pytscheck/__main__.py +221 -0
  3. pytscheck/adapters/__init__.py +38 -0
  4. pytscheck/adapters/base.py +33 -0
  5. pytscheck/adapters/compatibility.py +28 -0
  6. pytscheck/adapters/context.py +38 -0
  7. pytscheck/adapters/discovery.py +43 -0
  8. pytscheck/adapters/errors.py +25 -0
  9. pytscheck/adapters/project.py +431 -0
  10. pytscheck/adapters/registry.py +44 -0
  11. pytscheck/adapters/source_maps.py +255 -0
  12. pytscheck/adapters/sources.py +100 -0
  13. pytscheck/api.py +279 -0
  14. pytscheck/bin/manifest.json +14 -0
  15. pytscheck/bin/windows-arm64/LICENSE +55 -0
  16. pytscheck/bin/windows-arm64/NOTICE.txt +436 -0
  17. pytscheck/bin/windows-arm64/README.md +3 -0
  18. pytscheck/bin/windows-arm64/lib/lib.d.ts +20 -0
  19. pytscheck/bin/windows-arm64/lib/lib.decorators.d.ts +382 -0
  20. pytscheck/bin/windows-arm64/lib/lib.decorators.legacy.d.ts +20 -0
  21. pytscheck/bin/windows-arm64/lib/lib.dom.asynciterable.d.ts +18 -0
  22. pytscheck/bin/windows-arm64/lib/lib.dom.d.ts +45125 -0
  23. pytscheck/bin/windows-arm64/lib/lib.dom.iterable.d.ts +18 -0
  24. pytscheck/bin/windows-arm64/lib/lib.es2015.collection.d.ts +159 -0
  25. pytscheck/bin/windows-arm64/lib/lib.es2015.core.d.ts +595 -0
  26. pytscheck/bin/windows-arm64/lib/lib.es2015.d.ts +26 -0
  27. pytscheck/bin/windows-arm64/lib/lib.es2015.generator.d.ts +75 -0
  28. pytscheck/bin/windows-arm64/lib/lib.es2015.iterable.d.ts +603 -0
  29. pytscheck/bin/windows-arm64/lib/lib.es2015.promise.d.ts +79 -0
  30. pytscheck/bin/windows-arm64/lib/lib.es2015.proxy.d.ts +126 -0
  31. pytscheck/bin/windows-arm64/lib/lib.es2015.reflect.d.ts +142 -0
  32. pytscheck/bin/windows-arm64/lib/lib.es2015.symbol.d.ts +44 -0
  33. pytscheck/bin/windows-arm64/lib/lib.es2015.symbol.wellknown.d.ts +324 -0
  34. pytscheck/bin/windows-arm64/lib/lib.es2016.array.include.d.ts +114 -0
  35. pytscheck/bin/windows-arm64/lib/lib.es2016.d.ts +19 -0
  36. pytscheck/bin/windows-arm64/lib/lib.es2016.full.d.ts +21 -0
  37. pytscheck/bin/windows-arm64/lib/lib.es2016.intl.d.ts +29 -0
  38. pytscheck/bin/windows-arm64/lib/lib.es2017.arraybuffer.d.ts +19 -0
  39. pytscheck/bin/windows-arm64/lib/lib.es2017.d.ts +24 -0
  40. pytscheck/bin/windows-arm64/lib/lib.es2017.date.d.ts +29 -0
  41. pytscheck/bin/windows-arm64/lib/lib.es2017.full.d.ts +21 -0
  42. pytscheck/bin/windows-arm64/lib/lib.es2017.intl.d.ts +42 -0
  43. pytscheck/bin/windows-arm64/lib/lib.es2017.object.d.ts +47 -0
  44. pytscheck/bin/windows-arm64/lib/lib.es2017.sharedmemory.d.ts +133 -0
  45. pytscheck/bin/windows-arm64/lib/lib.es2017.string.d.ts +47 -0
  46. pytscheck/bin/windows-arm64/lib/lib.es2017.typedarrays.d.ts +51 -0
  47. pytscheck/bin/windows-arm64/lib/lib.es2018.asyncgenerator.d.ts +75 -0
  48. pytscheck/bin/windows-arm64/lib/lib.es2018.asynciterable.d.ts +51 -0
  49. pytscheck/bin/windows-arm64/lib/lib.es2018.d.ts +22 -0
  50. pytscheck/bin/windows-arm64/lib/lib.es2018.full.d.ts +22 -0
  51. pytscheck/bin/windows-arm64/lib/lib.es2018.intl.d.ts +81 -0
  52. pytscheck/bin/windows-arm64/lib/lib.es2018.promise.d.ts +28 -0
  53. pytscheck/bin/windows-arm64/lib/lib.es2018.regexp.d.ts +35 -0
  54. pytscheck/bin/windows-arm64/lib/lib.es2019.array.d.ts +77 -0
  55. pytscheck/bin/windows-arm64/lib/lib.es2019.d.ts +22 -0
  56. pytscheck/bin/windows-arm64/lib/lib.es2019.full.d.ts +22 -0
  57. pytscheck/bin/windows-arm64/lib/lib.es2019.intl.d.ts +21 -0
  58. pytscheck/bin/windows-arm64/lib/lib.es2019.object.d.ts +31 -0
  59. pytscheck/bin/windows-arm64/lib/lib.es2019.string.d.ts +35 -0
  60. pytscheck/bin/windows-arm64/lib/lib.es2019.symbol.d.ts +22 -0
  61. pytscheck/bin/windows-arm64/lib/lib.es2020.bigint.d.ts +763 -0
  62. pytscheck/bin/windows-arm64/lib/lib.es2020.d.ts +25 -0
  63. pytscheck/bin/windows-arm64/lib/lib.es2020.date.d.ts +40 -0
  64. pytscheck/bin/windows-arm64/lib/lib.es2020.full.d.ts +22 -0
  65. pytscheck/bin/windows-arm64/lib/lib.es2020.intl.d.ts +472 -0
  66. pytscheck/bin/windows-arm64/lib/lib.es2020.number.d.ts +26 -0
  67. pytscheck/bin/windows-arm64/lib/lib.es2020.promise.d.ts +45 -0
  68. pytscheck/bin/windows-arm64/lib/lib.es2020.sharedmemory.d.ts +97 -0
  69. pytscheck/bin/windows-arm64/lib/lib.es2020.string.d.ts +42 -0
  70. pytscheck/bin/windows-arm64/lib/lib.es2020.symbol.wellknown.d.ts +39 -0
  71. pytscheck/bin/windows-arm64/lib/lib.es2021.d.ts +21 -0
  72. pytscheck/bin/windows-arm64/lib/lib.es2021.full.d.ts +22 -0
  73. pytscheck/bin/windows-arm64/lib/lib.es2021.intl.d.ts +164 -0
  74. pytscheck/bin/windows-arm64/lib/lib.es2021.promise.d.ts +46 -0
  75. pytscheck/bin/windows-arm64/lib/lib.es2021.string.d.ts +31 -0
  76. pytscheck/bin/windows-arm64/lib/lib.es2021.weakref.d.ts +76 -0
  77. pytscheck/bin/windows-arm64/lib/lib.es2022.array.d.ts +119 -0
  78. pytscheck/bin/windows-arm64/lib/lib.es2022.d.ts +23 -0
  79. pytscheck/bin/windows-arm64/lib/lib.es2022.error.d.ts +73 -0
  80. pytscheck/bin/windows-arm64/lib/lib.es2022.full.d.ts +22 -0
  81. pytscheck/bin/windows-arm64/lib/lib.es2022.intl.d.ts +143 -0
  82. pytscheck/bin/windows-arm64/lib/lib.es2022.object.d.ts +24 -0
  83. pytscheck/bin/windows-arm64/lib/lib.es2022.regexp.d.ts +37 -0
  84. pytscheck/bin/windows-arm64/lib/lib.es2022.string.d.ts +23 -0
  85. pytscheck/bin/windows-arm64/lib/lib.es2023.array.d.ts +922 -0
  86. pytscheck/bin/windows-arm64/lib/lib.es2023.collection.d.ts +19 -0
  87. pytscheck/bin/windows-arm64/lib/lib.es2023.d.ts +20 -0
  88. pytscheck/bin/windows-arm64/lib/lib.es2023.full.d.ts +22 -0
  89. pytscheck/bin/windows-arm64/lib/lib.es2023.intl.d.ts +62 -0
  90. pytscheck/bin/windows-arm64/lib/lib.es2024.arraybuffer.d.ts +63 -0
  91. pytscheck/bin/windows-arm64/lib/lib.es2024.collection.d.ts +27 -0
  92. pytscheck/bin/windows-arm64/lib/lib.es2024.d.ts +24 -0
  93. pytscheck/bin/windows-arm64/lib/lib.es2024.full.d.ts +22 -0
  94. pytscheck/bin/windows-arm64/lib/lib.es2024.object.d.ts +27 -0
  95. pytscheck/bin/windows-arm64/lib/lib.es2024.promise.d.ts +33 -0
  96. pytscheck/bin/windows-arm64/lib/lib.es2024.regexp.d.ts +23 -0
  97. pytscheck/bin/windows-arm64/lib/lib.es2024.sharedmemory.d.ts +66 -0
  98. pytscheck/bin/windows-arm64/lib/lib.es2024.string.d.ts +27 -0
  99. pytscheck/bin/windows-arm64/lib/lib.es2025.collection.d.ts +94 -0
  100. pytscheck/bin/windows-arm64/lib/lib.es2025.d.ts +23 -0
  101. pytscheck/bin/windows-arm64/lib/lib.es2025.float16.d.ts +443 -0
  102. pytscheck/bin/windows-arm64/lib/lib.es2025.full.d.ts +22 -0
  103. pytscheck/bin/windows-arm64/lib/lib.es2025.intl.d.ts +200 -0
  104. pytscheck/bin/windows-arm64/lib/lib.es2025.iterator.d.ts +146 -0
  105. pytscheck/bin/windows-arm64/lib/lib.es2025.promise.d.ts +32 -0
  106. pytscheck/bin/windows-arm64/lib/lib.es2025.regexp.d.ts +30 -0
  107. pytscheck/bin/windows-arm64/lib/lib.es5.d.ts +4599 -0
  108. pytscheck/bin/windows-arm64/lib/lib.es6.d.ts +21 -0
  109. pytscheck/bin/windows-arm64/lib/lib.esnext.array.d.ts +33 -0
  110. pytscheck/bin/windows-arm64/lib/lib.esnext.collection.d.ts +47 -0
  111. pytscheck/bin/windows-arm64/lib/lib.esnext.d.ts +27 -0
  112. pytscheck/bin/windows-arm64/lib/lib.esnext.date.d.ts +21 -0
  113. pytscheck/bin/windows-arm64/lib/lib.esnext.decorators.d.ts +26 -0
  114. pytscheck/bin/windows-arm64/lib/lib.esnext.disposable.d.ts +191 -0
  115. pytscheck/bin/windows-arm64/lib/lib.esnext.error.d.ts +22 -0
  116. pytscheck/bin/windows-arm64/lib/lib.esnext.full.d.ts +22 -0
  117. pytscheck/bin/windows-arm64/lib/lib.esnext.intl.d.ts +107 -0
  118. pytscheck/bin/windows-arm64/lib/lib.esnext.sharedmemory.d.ts +23 -0
  119. pytscheck/bin/windows-arm64/lib/lib.esnext.temporal.d.ts +485 -0
  120. pytscheck/bin/windows-arm64/lib/lib.esnext.typedarrays.d.ts +90 -0
  121. pytscheck/bin/windows-arm64/lib/lib.scripthost.d.ts +320 -0
  122. pytscheck/bin/windows-arm64/lib/lib.webworker.asynciterable.d.ts +18 -0
  123. pytscheck/bin/windows-arm64/lib/lib.webworker.d.ts +15606 -0
  124. pytscheck/bin/windows-arm64/lib/lib.webworker.importscripts.d.ts +21 -0
  125. pytscheck/bin/windows-arm64/lib/lib.webworker.iterable.d.ts +18 -0
  126. pytscheck/bin/windows-arm64/lib/tsgo.exe +0 -0
  127. pytscheck/bin/windows-arm64/package.json +66 -0
  128. pytscheck/checker.py +201 -0
  129. pytscheck/client.py +63 -0
  130. pytscheck/config.py +128 -0
  131. pytscheck/defaults.py +34 -0
  132. pytscheck/diagnostics.py +226 -0
  133. pytscheck/exceptions.py +115 -0
  134. pytscheck/integrations/README.md +13 -0
  135. pytscheck/models.py +101 -0
  136. pytscheck/options.py +56 -0
  137. pytscheck/paths.py +45 -0
  138. pytscheck/project.py +39 -0
  139. pytscheck/protocol.py +159 -0
  140. pytscheck/py.typed +0 -0
  141. pytscheck/resolver.py +90 -0
  142. pytscheck/results.py +31 -0
  143. pytscheck/runner.py +200 -0
  144. pytscheck/version.py +13 -0
  145. pytscheck-0.1.0.dist-info/METADATA +158 -0
  146. pytscheck-0.1.0.dist-info/RECORD +150 -0
  147. pytscheck-0.1.0.dist-info/WHEEL +4 -0
  148. pytscheck-0.1.0.dist-info/entry_points.txt +2 -0
  149. pytscheck-0.1.0.dist-info/licenses/LICENSE +204 -0
  150. pytscheck-0.1.0.dist-info/licenses/NOTICE.txt +442 -0
pytscheck/__init__.py ADDED
@@ -0,0 +1,89 @@
1
+ """PyTSCheck: Python-native TypeScript type checking.
2
+
3
+ PyTSCheck wraps Microsoft's native TypeScript 7 compiler (``tsgo``) and
4
+ exposes a typed Python API for checking source strings, files, and
5
+ projects. The compiler is bundled inside platform-specific wheels, so no
6
+ Node.js or Go installation is required.
7
+
8
+ Public API
9
+ ----------
10
+
11
+ The top-level entry points mirror the module-level functions in
12
+ :mod:`pytscheck.api`::
13
+
14
+ from pytscheck import check, check_file, check_project
15
+
16
+ result = check('const age: number = "twenty";')
17
+ if not result.success:
18
+ for diagnostic in result.errors:
19
+ print(diagnostic.file, diagnostic.line, diagnostic.message)
20
+
21
+ Adapter authors import from :mod:`pytscheck.adapters` instead; the core
22
+ package never imports a specific adapter.
23
+
24
+ Stability
25
+ ---------
26
+
27
+ The names re-exported here are the public surface and follow Semantic
28
+ Versioning. Anything not listed in :data:`__all__` is internal and may
29
+ change without notice.
30
+
31
+ Importing this module is cheap and safe: no subprocess is launched, no
32
+ binary is located, and no network access occurs until a ``check*``
33
+ function is called. This matters for packaging tests that run on machines
34
+ without a bundled compiler.
35
+ """
36
+
37
+ from __future__ import annotations
38
+
39
+ from .api import check, check_file, check_project
40
+ from .config import CompilerOptions
41
+ from .exceptions import (
42
+ AdapterDiscoveryError,
43
+ AdapterError,
44
+ AdapterExtractionError,
45
+ AdapterMappingError,
46
+ AdapterProtocolError,
47
+ AdapterRegistrationError,
48
+ CompilerExecutionError,
49
+ CompilerNotFoundError,
50
+ CompilerTimeoutError,
51
+ ConfigurationError,
52
+ OutputParseError,
53
+ PyTSCheckError,
54
+ UnsupportedPlatformError,
55
+ )
56
+ from .models import Diagnostic, RelatedInformation, Result, SourceFile
57
+ from .version import ADAPTER_PROTOCOL_VERSION, COMPILER_VERSION, __version__
58
+
59
+ __all__ = [ # noqa: RUF022 -- Public exports retain the tested version/API group order.
60
+ # Version metadata
61
+ "__version__",
62
+ "COMPILER_VERSION",
63
+ "ADAPTER_PROTOCOL_VERSION",
64
+ # Public API
65
+ "check",
66
+ "check_file",
67
+ "check_project",
68
+ # Configuration
69
+ "CompilerOptions",
70
+ # Models
71
+ "Result",
72
+ "Diagnostic",
73
+ "RelatedInformation",
74
+ "SourceFile",
75
+ # Exceptions
76
+ "PyTSCheckError",
77
+ "UnsupportedPlatformError",
78
+ "CompilerNotFoundError",
79
+ "CompilerExecutionError",
80
+ "CompilerTimeoutError",
81
+ "OutputParseError",
82
+ "ConfigurationError",
83
+ "AdapterError",
84
+ "AdapterDiscoveryError",
85
+ "AdapterExtractionError",
86
+ "AdapterMappingError",
87
+ "AdapterProtocolError",
88
+ "AdapterRegistrationError",
89
+ ]
pytscheck/__main__.py ADDED
@@ -0,0 +1,221 @@
1
+ """``python -m pytscheck`` and the ``pytscheck`` console script.
2
+
3
+ This module is intentionally small. It exposes three things:
4
+
5
+ - ``--version`` : print pytscheck / compiler / protocol versions
6
+ - ``--where`` : print the path to the bundled tsgo binary
7
+ - ``check`` : a minimal CLI over the public API (Phase 2+)
8
+
9
+ Every subcommand maps to a public function in :mod:`pytscheck.api`. The
10
+ CLI never reimplements logic: it parses arguments, calls the API, and
11
+ formats the result.
12
+
13
+ Exit codes
14
+ ----------
15
+
16
+ 0 success (no errors)
17
+ 1 type errors were reported
18
+ 2 usage / configuration error
19
+ 3 operational failure (missing binary, crash, timeout, unparsable output)
20
+
21
+ The distinction between 1 and 3 matters for CI: a tool that wants to fail
22
+ the build on type errors should treat 1 as a normal failure and 3 as an
23
+ infrastructure problem.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import argparse
29
+ import sys
30
+ from pathlib import Path
31
+
32
+ from .exceptions import (
33
+ CompilerExecutionError,
34
+ CompilerNotFoundError,
35
+ CompilerTimeoutError,
36
+ ConfigurationError,
37
+ OutputParseError,
38
+ PyTSCheckError,
39
+ UnsupportedPlatformError,
40
+ )
41
+ from .models import Diagnostic, Result
42
+ from .version import ADAPTER_PROTOCOL_VERSION, COMPILER_VERSION, __version__
43
+
44
+ EXIT_OK = 0
45
+ EXIT_TYPE_ERRORS = 1
46
+ EXIT_USAGE = 2
47
+ EXIT_OPERATIONAL = 3
48
+
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Argument parsing
52
+ # ---------------------------------------------------------------------------
53
+
54
+
55
+ def _build_parser() -> argparse.ArgumentParser:
56
+ parser = argparse.ArgumentParser(
57
+ prog="pytscheck",
58
+ description="Type-check TypeScript from Python.",
59
+ )
60
+ parser.add_argument(
61
+ "--version",
62
+ action="store_true",
63
+ help="print versions and exit",
64
+ )
65
+ parser.add_argument(
66
+ "--where",
67
+ action="store_true",
68
+ help="print the path to the bundled tsgo binary and exit",
69
+ )
70
+
71
+ sub = parser.add_subparsers(dest="command", metavar="COMMAND")
72
+
73
+ # --- check string -----------------------------------------------------
74
+ p_str = sub.add_parser("string", help="check an in-memory source string")
75
+ p_str.add_argument("source", help="TypeScript source text")
76
+ p_str.add_argument("--filename", default="input.ts", help="virtual filename")
77
+ p_str.add_argument("--json", action="store_true", help="emit JSON diagnostics")
78
+ p_str.add_argument("--keep-raw", action="store_true", help="include raw compiler output")
79
+
80
+ # --- check file -------------------------------------------------------
81
+ p_file = sub.add_parser("file", help="check a single file")
82
+ p_file.add_argument("path", type=Path, help="path to a .ts / .tsx / .mts / .cts file")
83
+ p_file.add_argument("--json", action="store_true", help="emit JSON diagnostics")
84
+ p_file.add_argument("--keep-raw", action="store_true", help="include raw compiler output")
85
+
86
+ # --- check project ----------------------------------------------------
87
+ p_proj = sub.add_parser("project", help="check a project directory")
88
+ p_proj.add_argument("root", type=Path, help="project root directory")
89
+ p_proj.add_argument("--json", action="store_true", help="emit JSON diagnostics")
90
+ p_proj.add_argument("--keep-raw", action="store_true", help="include raw compiler output")
91
+
92
+ return parser
93
+
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # Output formatting
97
+ # ---------------------------------------------------------------------------
98
+
99
+
100
+ def _format_diagnostic(d: Diagnostic) -> str:
101
+ """One-line, grep-friendly rendering of a diagnostic."""
102
+ loc = f"{d.file or '<global>'}({d.line},{d.column})"
103
+ return f"{loc}: {d.category} TS{d.code}: {d.message}"
104
+
105
+
106
+ def _print_result(result: Result, *, as_json: bool) -> None:
107
+ if as_json:
108
+ import json
109
+
110
+ payload = {
111
+ "success": result.success,
112
+ "compiler_version": result.compiler_version,
113
+ "elapsed_seconds": result.elapsed_seconds,
114
+ "diagnostics": [
115
+ {
116
+ "file": d.file,
117
+ "origin_file": d.origin_file,
118
+ "line": d.line,
119
+ "column": d.column,
120
+ "end_line": d.end_line,
121
+ "end_column": d.end_column,
122
+ "code": d.code,
123
+ "category": d.category,
124
+ "message": d.message,
125
+ }
126
+ for d in result.diagnostics
127
+ ],
128
+ }
129
+ print(json.dumps(payload, indent=2))
130
+ return
131
+
132
+ for d in result.diagnostics:
133
+ print(_format_diagnostic(d))
134
+ if result.success:
135
+ print(f"ok ({result.elapsed_seconds:.2f}s)")
136
+ else:
137
+ n = len(result.errors)
138
+ print(f"{n} error{'s' if n != 1 else ''} ({result.elapsed_seconds:.2f}s)")
139
+
140
+
141
+ # ---------------------------------------------------------------------------
142
+ # Command handlers
143
+ # ---------------------------------------------------------------------------
144
+
145
+
146
+ def _cmd_version() -> int:
147
+ print(f"pytscheck {__version__}")
148
+ print(f"bundled compiler {COMPILER_VERSION}")
149
+ print(f"adapter protocol {ADAPTER_PROTOCOL_VERSION}")
150
+ return EXIT_OK
151
+
152
+
153
+ def _cmd_where() -> int:
154
+ from .runner import binary_path
155
+
156
+ try:
157
+ print(binary_path())
158
+ except PyTSCheckError as exc:
159
+ print(f"error: {exc}", file=sys.stderr)
160
+ return EXIT_OPERATIONAL
161
+ return EXIT_OK
162
+
163
+
164
+ def _cmd_check(args: argparse.Namespace) -> int:
165
+ # Import lazily so --version / --where never pull in the runner.
166
+ from .api import check, check_file, check_project
167
+
168
+ try:
169
+ if args.command == "string":
170
+ result = check(
171
+ args.source,
172
+ filename=args.filename,
173
+ keep_raw=args.keep_raw,
174
+ )
175
+ elif args.command == "file":
176
+ result = check_file(args.path, keep_raw=args.keep_raw)
177
+ elif args.command == "project":
178
+ result = check_project(args.root, keep_raw=args.keep_raw)
179
+ else: # pragma: no cover - argparse enforces this
180
+ print(f"unknown command: {args.command}", file=sys.stderr)
181
+ return EXIT_USAGE
182
+ except ConfigurationError as exc:
183
+ print(f"configuration error: {exc}", file=sys.stderr)
184
+ return EXIT_USAGE
185
+ except (
186
+ CompilerNotFoundError,
187
+ CompilerTimeoutError,
188
+ CompilerExecutionError,
189
+ OutputParseError,
190
+ UnsupportedPlatformError,
191
+ ) as exc:
192
+ print(f"operational error: {exc}", file=sys.stderr)
193
+ return EXIT_OPERATIONAL
194
+
195
+ _print_result(result, as_json=args.json)
196
+ return EXIT_OK if result.success else EXIT_TYPE_ERRORS
197
+
198
+
199
+ # ---------------------------------------------------------------------------
200
+ # Entry point
201
+ # ---------------------------------------------------------------------------
202
+
203
+
204
+ def main(argv: list[str] | None = None) -> int:
205
+ parser = _build_parser()
206
+ args = parser.parse_args(argv)
207
+
208
+ if args.version:
209
+ return _cmd_version()
210
+ if args.where:
211
+ return _cmd_where()
212
+
213
+ if args.command in {"string", "file", "project"}:
214
+ return _cmd_check(args)
215
+
216
+ parser.print_help()
217
+ return EXIT_USAGE
218
+
219
+
220
+ if __name__ == "__main__":
221
+ raise SystemExit(main())
@@ -0,0 +1,38 @@
1
+ """Compiler-agnostic adapter system.
2
+
3
+ Adapters let external Python tools submit generated TypeScript and receive
4
+ diagnostics mapped back to their own source files. The pytscheck core never
5
+ imports a specific adapter; tools register theirs through the
6
+ ``pytscheck.adapters`` entry-point group.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from .base import CompilerAdapter
12
+ from .context import DeclarationResource, ProjectContext
13
+ from .errors import (
14
+ AdapterError,
15
+ AdapterExtractionError,
16
+ AdapterMappingError,
17
+ AdapterProtocolError,
18
+ AdapterRegistrationError,
19
+ )
20
+ from .registry import get_adapter, register_adapter, unregister_adapter
21
+ from .source_maps import remap_diagnostics
22
+ from .sources import collect_sources
23
+
24
+ __all__ = [
25
+ "AdapterError",
26
+ "AdapterExtractionError",
27
+ "AdapterMappingError",
28
+ "AdapterProtocolError",
29
+ "AdapterRegistrationError",
30
+ "CompilerAdapter",
31
+ "DeclarationResource",
32
+ "ProjectContext",
33
+ "collect_sources",
34
+ "get_adapter",
35
+ "register_adapter",
36
+ "remap_diagnostics",
37
+ "unregister_adapter",
38
+ ]
@@ -0,0 +1,33 @@
1
+ """The compiler-agnostic adapter protocol."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Protocol, runtime_checkable
6
+
7
+ from ..models import SourceFile
8
+
9
+
10
+ @runtime_checkable
11
+ class CompilerAdapter(Protocol):
12
+ """Structural protocol implemented by every adapter.
13
+
14
+ Implementations live in the consuming tool's package. pytscheck core
15
+ never imports them directly; registration is via the entry-point group
16
+ ``pytscheck.adapters``.
17
+ """
18
+
19
+ @property
20
+ def name(self) -> str:
21
+ """A short, unique identifier (e.g. ``"teloc"``)."""
22
+ ...
23
+
24
+ def get_sources(self, project_root: str) -> list[SourceFile]:
25
+ """Return the TypeScript sources to check.
26
+
27
+ Must raise :class:`AdapterExtractionError` (not return a diagnostic)
28
+ if the tool cannot produce TypeScript for any input.
29
+ """
30
+ ...
31
+
32
+
33
+ __all__ = ["CompilerAdapter"]
@@ -0,0 +1,28 @@
1
+ """Protocol-version and capability compatibility checks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ..version import ADAPTER_PROTOCOL_VERSION
6
+ from .base import CompilerAdapter
7
+ from .errors import AdapterProtocolError
8
+
9
+
10
+ def check_protocol_version(adapter: CompilerAdapter) -> None:
11
+ """Verify the adapter declares a compatible protocol version.
12
+
13
+ Adapters may expose ``protocol_version`` (a string). If absent, we assume
14
+ "1.x" compatibility and accept.
15
+ """
16
+ declared = getattr(adapter, "protocol_version", None)
17
+ if declared is None:
18
+ return
19
+ if not isinstance(declared, str):
20
+ raise AdapterProtocolError(f"adapter {adapter.name!r} has non-string protocol_version")
21
+ if declared.split(".")[0] != ADAPTER_PROTOCOL_VERSION.split(".")[0]:
22
+ raise AdapterProtocolError(
23
+ f"adapter {adapter.name!r} speaks protocol {declared}, "
24
+ f"core speaks {ADAPTER_PROTOCOL_VERSION}"
25
+ )
26
+
27
+
28
+ __all__ = ["check_protocol_version"]
@@ -0,0 +1,38 @@
1
+ """Optional framework-independent context for generated project checking."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from pathlib import Path
7
+
8
+
9
+ @dataclass(frozen=True, slots=True)
10
+ class DeclarationResource:
11
+ """Declarations shipped by a Python package, optionally exposed as a module.
12
+
13
+ ``resource`` is a package-relative file or directory. Resources may come
14
+ from ordinary installations or zip importers; no Node installation is needed.
15
+ """
16
+
17
+ package: str
18
+ resource: str = "types"
19
+ module: str | None = None
20
+
21
+
22
+ @dataclass(frozen=True, slots=True)
23
+ class ProjectContext:
24
+ """Opt into project configuration, real files and declaration resources.
25
+
26
+ Paths are relative to the root passed to ``check_project`` unless absolute.
27
+ Caller options override ``compiler_options``, which override tsconfig.
28
+ Generated paths must not overwrite an existing project file.
29
+ """
30
+
31
+ tsconfig: str | Path | None = None
32
+ inherit_tsconfig: bool = True
33
+ include_project_files: bool = True
34
+ declaration_paths: tuple[str | Path, ...] = ()
35
+ declaration_resources: tuple[DeclarationResource, ...] = ()
36
+ compiler_options: dict[str, object] = field(default_factory=dict)
37
+ max_workspace_files: int = 100_000
38
+ max_workspace_bytes: int = 512 * 1024 * 1024
@@ -0,0 +1,43 @@
1
+ """Entry-point discovery for third-party adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib.metadata import entry_points
6
+
7
+ from ..defaults import DEFAULT_ADAPTER_ENTRY_POINT_GROUP
8
+ from .base import CompilerAdapter
9
+ from .errors import AdapterDiscoveryError
10
+ from .registry import register_adapter
11
+
12
+
13
+ def discover_adapters(
14
+ group: str = DEFAULT_ADAPTER_ENTRY_POINT_GROUP,
15
+ ) -> tuple[str, ...]:
16
+ """Discover and register all adapters advertised under ``group``.
17
+
18
+ Returns the names of adapters that were newly registered.
19
+ """
20
+ registered: list[str] = []
21
+ try:
22
+ eps = entry_points(group=group)
23
+ except Exception as exc: # pragma: no cover - importlib.metadata is stable
24
+ raise AdapterDiscoveryError(f"entry-point discovery failed: {exc}") from exc
25
+
26
+ for ep in eps:
27
+ try:
28
+ obj = ep.load()
29
+ adapter = obj() if isinstance(obj, type) else obj
30
+ except Exception as exc:
31
+ raise AdapterDiscoveryError(
32
+ f"failed to load adapter entry point {ep.name!r}: {exc}"
33
+ ) from exc
34
+
35
+ if not isinstance(adapter, CompilerAdapter):
36
+ raise AdapterDiscoveryError(f"entry point {ep.name!r} did not yield a CompilerAdapter")
37
+ register_adapter(adapter)
38
+ registered.append(adapter.name)
39
+
40
+ return tuple(registered)
41
+
42
+
43
+ __all__ = ["discover_adapters"]
@@ -0,0 +1,25 @@
1
+ """Adapter-layer exceptions.
2
+
3
+ Re-exported from the top-level exception hierarchy so callers can catch
4
+ ``pytscheck.AdapterError`` without knowing about this submodule.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from ..exceptions import (
10
+ AdapterDiscoveryError,
11
+ AdapterError,
12
+ AdapterExtractionError,
13
+ AdapterMappingError,
14
+ AdapterProtocolError,
15
+ AdapterRegistrationError,
16
+ )
17
+
18
+ __all__ = [
19
+ "AdapterDiscoveryError",
20
+ "AdapterError",
21
+ "AdapterExtractionError",
22
+ "AdapterMappingError",
23
+ "AdapterProtocolError",
24
+ "AdapterRegistrationError",
25
+ ]