0
# Pyright
1
2
A Python command-line wrapper over Microsoft's pyright static type checker for Python. This package eliminates the need to install Node.js or npm separately by automatically managing the Node.js environment and pyright npm package installation, making pyright accessible to Python developers without JavaScript toolchain dependencies.
3
4
## Package Information
5
6
- **Package Name**: pyright
7
- **Language**: Python
8
- **Installation**: `pip install pyright`
9
- **Recommended Installation**: `pip install pyright[nodejs]` (more reliable Node.js binaries)
10
11
## Core Imports
12
13
```python
14
import pyright
15
```
16
17
For direct module access:
18
19
```python
20
import pyright.cli
21
import pyright.langserver
22
import pyright.errors
23
import pyright.node
24
import pyright.utils
25
import pyright.types
26
```
27
28
For specific imports:
29
30
```python
31
from pyright import errors
32
from pyright.cli import run, main, entrypoint
33
from pyright.langserver import run, main, entrypoint
34
from pyright.node import run, version, latest
35
from pyright.types import Target, check_target
36
from pyright.utils import get_cache_dir, env_to_bool
37
```
38
39
## Basic Usage
40
41
### Command Line Usage
42
43
```python
44
# Via console script (most common)
45
# After installation, pyright is available as a command:
46
# $ pyright --help
47
# $ pyright src/
48
49
# Programmatic usage
50
from pyright.cli import run, main
51
52
# Run pyright with arguments (returns CompletedProcess)
53
result = run('--version')
54
print(result.stdout)
55
56
# Run pyright and get exit code
57
exit_code = main(['src/', '--outputjson'])
58
```
59
60
### Language Server Usage
61
62
```python
63
from pyright.langserver import run as langserver_run, main as langserver_main
64
65
# Run pyright language server
66
result = langserver_run('--stdio')
67
68
# Run with exit code
69
exit_code = langserver_main('--stdio')
70
```
71
72
## Architecture
73
74
The package provides four entry points for different use cases:
75
76
- **CLI Tools**: `pyright` and `pyright-python` for command-line type checking
77
- **Language Server**: `pyright-langserver` and `pyright-python-langserver` for IDE integration
78
- **Node.js Management**: Automatically handles Node.js installation via three strategies:
79
- Global Node.js (preferred if available)
80
- nodejs-wheel package (more reliable, requires `[nodejs]` extra)
81
- nodeenv (fallback, creates isolated Node.js environment)
82
83
## Capabilities
84
85
### Command Line Interface
86
87
Core functions for running pyright type checking from Python code or command line.
88
89
```python { .api }
90
def run(*args: str, **kwargs: Any) -> Union[subprocess.CompletedProcess[bytes], subprocess.CompletedProcess[str]]:
91
"""
92
Execute pyright with given arguments.
93
94
Parameters:
95
- *args: Command line arguments to pass to pyright
96
- **kwargs: Additional subprocess arguments (stdout, stderr, etc.)
97
98
Returns:
99
subprocess.CompletedProcess: Result of pyright execution
100
"""
101
102
def main(args: List[str], **kwargs: Any) -> int:
103
"""
104
Main entry point for pyright CLI returning exit code.
105
106
Parameters:
107
- args: List of command line arguments
108
- **kwargs: Additional subprocess arguments
109
110
Returns:
111
int: Exit code (0 for success, non-zero for errors)
112
"""
113
114
def entrypoint() -> NoReturn:
115
"""
116
Console script entry point for pyright command.
117
118
Calls main() with sys.argv[1:] and exits with the result.
119
"""
120
```
121
122
### Language Server Interface
123
124
Functions for running pyright as a language server for IDE integration.
125
126
```python { .api }
127
def run(*args: str, **kwargs: Any) -> subprocess.CompletedProcess[bytes] | subprocess.CompletedProcess[str]:
128
"""
129
Execute pyright language server with arguments.
130
131
Parameters:
132
- *args: Language server arguments (typically --stdio)
133
- **kwargs: Additional subprocess arguments
134
135
Returns:
136
subprocess.CompletedProcess: Result of language server execution
137
"""
138
139
def main(*args: str, **kwargs: Any) -> int:
140
"""
141
Main entry point for language server returning exit code.
142
143
Parameters:
144
- *args: Language server arguments
145
- **kwargs: Additional subprocess arguments
146
147
Returns:
148
int: Exit code
149
"""
150
151
def entrypoint() -> NoReturn:
152
"""
153
Console script entry point for pyright language server.
154
155
Calls main() with sys.argv[1:] and exits with the result.
156
"""
157
```
158
159
### Node.js Management
160
161
Low-level functions for managing Node.js runtime and npm packages.
162
163
```python { .api }
164
def run(target: Target, *args: str, **kwargs: Any) -> Union[subprocess.CompletedProcess[bytes], subprocess.CompletedProcess[str]]:
165
"""
166
Execute node or npm commands using resolved binary strategy.
167
168
Parameters:
169
- target: Either 'node' or 'npm'
170
- *args: Command line arguments to pass to the binary
171
- **kwargs: Additional subprocess arguments
172
173
Returns:
174
subprocess.CompletedProcess: Result of command execution
175
176
Raises:
177
- BinaryNotFound: If required binary cannot be found
178
- VersionCheckFailed: If version validation fails
179
"""
180
181
def version(target: Target) -> Tuple[int, ...]:
182
"""
183
Get version information for node or npm binary.
184
185
Parameters:
186
- target: Either 'node' or 'npm'
187
188
Returns:
189
Tuple[int, ...]: Version tuple (e.g., (18, 17, 0))
190
191
Raises:
192
- VersionCheckFailed: If version cannot be determined
193
"""
194
195
def latest(package: str) -> str:
196
"""
197
Get latest version of an npm package.
198
199
Parameters:
200
- package: NPM package name
201
202
Returns:
203
str: Latest version string
204
205
Raises:
206
- VersionCheckFailed: If version check fails
207
"""
208
209
def get_env_variables() -> Dict[str, Any]:
210
"""
211
Get environment variables for Node.js execution.
212
213
Returns:
214
Dict[str, Any]: Environment variables dict
215
"""
216
217
def get_pkg_version(pkg: Path) -> str | None:
218
"""
219
Parse package.json file and return version property.
220
221
Parameters:
222
- pkg: Path to package.json file
223
224
Returns:
225
str | None: Version string or None if cannot be resolved
226
"""
227
```
228
229
### Utility Functions
230
231
Helper functions for directory management and configuration.
232
233
```python { .api }
234
def get_cache_dir() -> Path:
235
"""
236
Get user cache directory path.
237
238
Returns:
239
Path: Cache directory path (respects XDG_CACHE_HOME, defaults to ~/.cache)
240
"""
241
242
def get_env_dir() -> Path:
243
"""
244
Get nodeenv directory path.
245
246
Returns:
247
Path: Directory containing nodeenv installation
248
"""
249
250
def get_bin_dir(*, env_dir: Path) -> Path:
251
"""
252
Get binary directory for given environment directory.
253
254
Parameters:
255
- env_dir: Environment directory path
256
257
Returns:
258
Path: Binary directory (Scripts on Windows, bin on Unix)
259
"""
260
261
def env_to_bool(key: str, *, default: bool = False) -> bool:
262
"""
263
Convert environment variable to boolean.
264
265
Parameters:
266
- key: Environment variable name
267
- default: Default value if not set
268
269
Returns:
270
bool: Boolean value (recognizes '1', 't', 'on', 'true' as True)
271
"""
272
273
def maybe_decode(data: Union[str, bytes]) -> str:
274
"""
275
Decode bytes to string if needed.
276
277
Parameters:
278
- data: String or bytes data
279
280
Returns:
281
str: Decoded string
282
"""
283
284
def get_latest_version() -> Optional[str]:
285
"""
286
Get latest pyright-python version from PyPI.
287
288
Returns:
289
Optional[str]: Latest version string or None if unavailable
290
"""
291
```
292
293
### Type Validation
294
295
Functions for validating and working with type definitions.
296
297
```python { .api }
298
def check_target(value: Any) -> None:
299
"""
300
Validate that a value is a valid Target type.
301
302
Parameters:
303
- value: Value to validate
304
305
Raises:
306
- TypeError: If value is not 'node' or 'npm'
307
"""
308
```
309
310
## Exception Handling
311
312
```python { .api }
313
class PyrightError(Exception):
314
"""Base exception for pyright-related errors."""
315
message: str
316
317
class NodeError(PyrightError):
318
"""Node.js related errors."""
319
pass
320
321
class BinaryNotFound(NodeError):
322
"""Raised when expected Node.js binary is not found."""
323
path: Path
324
target: Target
325
326
class VersionCheckFailed(NodeError):
327
"""Raised when version checking fails."""
328
pass
329
```
330
331
## Types
332
333
```python { .api }
334
Target = Literal['node', 'npm']
335
336
class GlobalStrategy(NamedTuple):
337
"""Strategy using global Node.js installation."""
338
type: Literal['global']
339
path: Path
340
341
class NodeJSWheelStrategy(NamedTuple):
342
"""Strategy using nodejs-wheel package."""
343
type: Literal['nodejs_wheel']
344
345
class NodeenvStrategy(NamedTuple):
346
"""Strategy using nodeenv installation."""
347
type: Literal['nodeenv']
348
path: Path
349
350
Strategy = Union[GlobalStrategy, NodeJSWheelStrategy, NodeenvStrategy]
351
```
352
353
## Constants
354
355
Important constants used by the Node.js management system:
356
357
```python { .api }
358
ENV_DIR: Path # Environment directory path
359
BINARIES_DIR: Path # Binary directory path
360
USE_GLOBAL_NODE: bool # Whether to use global Node.js (default: True)
361
USE_NODEJS_WHEEL: bool # Whether to use nodejs-wheel package (default: True)
362
NODE_VERSION: Optional[str] # User-specified Node.js version
363
VERSION_RE: Pattern # Regular expression for version matching
364
PYPI_API_URL: str # PyPI JSON API URL for version checking
365
366
# Package metadata constants (available from main pyright module)
367
__version__: str # Package version (e.g., "1.1.405")
368
__pyright_version__: str # Wrapped pyright version (e.g., "1.1.405")
369
__title__: str # Package title
370
__author__: str # Package author
371
__license__: str # Package license
372
__copyright__: str # Copyright information
373
```
374
375
## Environment Variables
376
377
Extensive configuration options via environment variables:
378
379
### Version Control
380
- `PYRIGHT_PYTHON_FORCE_VERSION`: Override pyright version (e.g., "1.1.400", "latest")
381
- `PYRIGHT_PYTHON_PYLANCE_VERSION`: Use Pylance-compatible version (e.g., "2023.11.11")
382
383
### Node.js Management
384
- `PYRIGHT_PYTHON_GLOBAL_NODE`: Use global Node.js (default: True)
385
- `PYRIGHT_PYTHON_NODE_VERSION`: Specify Node.js version for nodeenv
386
- `PYRIGHT_PYTHON_ENV_DIR`: Custom nodeenv directory path
387
- `PYRIGHT_PYTHON_NODEJS_WHEEL`: Use nodejs-wheel package (default: True)
388
389
### Caching and Storage
390
- `PYRIGHT_PYTHON_CACHE_DIR`: Custom cache directory
391
- `XDG_CACHE_HOME`: XDG cache directory (respected if set)
392
393
### Output and Debugging
394
- `PYRIGHT_PYTHON_DEBUG`: Enable debug logging
395
- `PYRIGHT_PYTHON_VERBOSE`: Show npm installation logs
396
- `PYRIGHT_PYTHON_IGNORE_WARNINGS`: Suppress version warnings
397
398
### Package Control
399
- `PYRIGHT_PYTHON_USE_BUNDLED_PYRIGHT`: Use bundled pyright version (default: True)
400
401
## Console Scripts
402
403
Four console scripts are installed:
404
405
- `pyright`: Main pyright CLI command
406
- `pyright-python`: Alias for pyright CLI
407
- `pyright-langserver`: Pyright language server
408
- `pyright-python-langserver`: Alias for language server
409
410
## Pre-commit Integration
411
412
Support for pre-commit hooks via `.pre-commit-config.yaml`:
413
414
```yaml
415
repos:
416
- repo: https://github.com/RobertCraigie/pyright-python
417
rev: v1.1.405
418
hooks:
419
- id: pyright
420
```
421
422
## Installation Options
423
424
```bash
425
# Basic installation
426
pip install pyright
427
428
# Recommended: with nodejs-wheel for reliable Node.js binaries
429
pip install pyright[nodejs]
430
431
# Development installation
432
pip install pyright[dev]
433
434
# All extras
435
pip install pyright[all]
436
```
437
438
## Usage Examples
439
440
### Basic Type Checking
441
442
```python
443
from pyright.cli import run
444
445
# Check specific files
446
result = run('src/main.py', 'src/utils.py')
447
if result.returncode == 0:
448
print("Type checking passed!")
449
else:
450
print("Type checking failed")
451
452
# Check entire directory with JSON output
453
result = run('src/', '--outputjson')
454
```
455
456
### Language Server for IDE
457
458
```python
459
from pyright.langserver import run as langserver_run
460
461
# Start language server with stdio communication
462
result = langserver_run('--stdio')
463
```
464
465
### Version Management
466
467
```python
468
from pyright.node import version, latest
469
470
# Check Node.js version
471
node_version = version('node')
472
print(f"Node.js version: {'.'.join(map(str, node_version))}")
473
474
# Get latest pyright version
475
latest_pyright = latest('pyright')
476
print(f"Latest pyright: {latest_pyright}")
477
```
478
479
### Error Handling
480
481
```python
482
from pyright.cli import run
483
from pyright.errors import PyrightError, BinaryNotFound
484
485
try:
486
result = run('--version')
487
print(result.stdout.decode())
488
except BinaryNotFound as e:
489
print(f"Node.js binary not found at {e.path}")
490
except PyrightError as e:
491
print(f"Pyright error: {e.message}")
492
```