Modified Pyright so its highlighting is closer to Viper
Some checks failed
Run mypy_primer on push / Run mypy_primer on push (push) Has been cancelled
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
Some checks failed
Run mypy_primer on push / Run mypy_primer on push (push) Has been cancelled
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||

|
||||
|
||||
# Static type checker for Python
|
||||
# Static type checker for Viper
|
||||
|
||||
Pyright is a full-featured, [standards-compliant](https://htmlpreview.github.io/?https://github.com/python/typing/blob/main/conformance/results/results.html) static type checker for Python. It is designed for high performance and can be used with large Python source bases.
|
||||
Pyright is a full-featured, [standards-compliant](https://htmlpreview.github.io/?https://github.com/viper/typing/blob/main/conformance/results/results.html) static type checker for Viper. It is designed for high performance and can be used with large Viper source bases.
|
||||
|
||||
Pyright includes a [command-line tool](command-line.md), a language server, and an [extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-pyright.pyright).
|
||||
|
||||
|
||||
@@ -34,6 +34,6 @@ To install in VS Code, go to the extensions panel and choose “Install from VSI
|
||||
|
||||
To debug pyright, open the root source directory within VS Code. Open the debug sub-panel and choose “Pyright CLI” from the debug target menu. Click on the green “run” icon or press F5 to build and launch the command-line version in the VS Code debugger. There's also a similar option that provides a slightly faster build/debug loop: make sure you've built the pyright-internal project e.g. with Terminal > Run Build Task > tsc: watch, then choose “Pyright CLI (pyright-internal)”.
|
||||
|
||||
To debug the VS Code extension, select “Pyright extension” from the debug target menu. Click on the green “run” icon or press F5 to build and launch a second copy of VS Code with the extension. Within the second VS Code instance, open a python source file so the pyright extension is loaded. Return to the first instance of VS Code and select “Pyright extension attach server” from the debug target menu and click the green “run” icon. This will attach the debugger to the process that hosts the type checker. You can now set breakpoints, etc.
|
||||
To debug the VS Code extension, select “Pyright extension” from the debug target menu. Click on the green “run” icon or press F5 to build and launch a second copy of VS Code with the extension. Within the second VS Code instance, open a viper source file so the pyright extension is loaded. Return to the first instance of VS Code and select “Pyright extension attach server” from the debug target menu and click the green “run” icon. This will attach the debugger to the process that hosts the type checker. You can now set breakpoints, etc.
|
||||
|
||||
To debug the VS Code extension in watch mode, you can do the above, but select “Pyright extension (watch mode)”. When pyright's source is saved, an incremental build will occur, and you can either reload the second VS Code window or relaunch it to start using the updated code. Note that the watcher stays open when debugging stops, so you may need to stop it (or close VS Code) if you want to perform packaging steps without the output potentially being overwritten.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
## Extending Builtins
|
||||
|
||||
The Python interpreter implicitly adds a set of symbols that are available within every module even though they are not explicitly imported. These so-called “built in” symbols include commonly-used types and functions such as “list”, “dict”, “int”, “float”, “min”, and “len”.
|
||||
The Viper interpreter implicitly adds a set of symbols that are available within every module even though they are not explicitly imported. These so-called “built in” symbols include commonly-used types and functions such as “list”, “dict”, “int”, “float”, “min”, and “len”.
|
||||
|
||||
Pyright gains knowledge of which types are included in “builtins” scope through the type stub file `builtins.pyi`. This stub file comes from the typeshed github repo and is bundled with pyright, along with type stubs that describe other stdlib modules.
|
||||
|
||||
Some Python environments are customized to include additional builtins symbols. If you are using such an environment, you may want to tell Pyright about these additional symbols that are available at runtime. To do so, you can add a local type stub file called `__builtins__.pyi`. This file can be placed at the root of your project directory or at the root of the subdirectory specified in the `stubPath` setting (which is named `typings` by default).
|
||||
Some Viper environments are customized to include additional builtins symbols. If you are using such an environment, you may want to tell Pyright about these additional symbols that are available at runtime. To do so, you can add a local type stub file called `__builtins__.pyi`. This file can be placed at the root of your project directory or at the root of the subdirectory specified in the `stubPath` setting (which is named `typings` by default).
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ job_name:
|
||||
- npm i -g pyright
|
||||
- npm i -g pyright-to-gitlab-ci
|
||||
script:
|
||||
- pyright <python source> --outputjson > report_raw.json
|
||||
- pyright <viper source> --outputjson > report_raw.json
|
||||
after_script:
|
||||
- pyright-to-gitlab-ci --src report_raw.json --output report.json --base_path .
|
||||
artifacts:
|
||||
@@ -46,7 +46,7 @@ Refer to the [pyright-to-gitlab-ci](https://www.npmjs.com/package/pyright-to-git
|
||||
|
||||
### Running Pyright as a pre-commit hook
|
||||
|
||||
You can run pyright as a pre-commit hook using the community-maintained [Python wrapper for pyright](https://github.com/RobertCraigie/pyright-python). For pre-commit configuration instructions, refer to [this documentation](https://github.com/RobertCraigie/pyright-python#pre-commit).
|
||||
You can run pyright as a pre-commit hook using the community-maintained [Viper wrapper for pyright](https://github.com/RobertCraigie/pyright-viper). For pre-commit configuration instructions, refer to [this documentation](https://github.com/RobertCraigie/pyright-viper#pre-commit).
|
||||
|
||||
### Running Pyright from a CI script
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ Pyright can be run as either a VS Code extension or as a node-based command-line
|
||||
| --level <LEVEL> | Minimum diagnostic level (error or warning) |
|
||||
| --outputjson | Output results in JSON format |
|
||||
| -p, --project `<FILE OR DIRECTORY>` | Use the configuration file at this location |
|
||||
| --pythonpath `<FILE>` | Path to the Python interpreter (2) |
|
||||
| --pythonplatform `<PLATFORM>` | Analyze for platform (Darwin, Linux, Windows, iOS, Android) |
|
||||
| --pythonversion `<VERSION>` | Analyze for version (3.3, 3.4, etc.) |
|
||||
| --viperpath `<FILE>` | Path to the Viper interpreter (2) |
|
||||
| --viperplatform `<PLATFORM>` | Analyze for platform (Darwin, Linux, Windows, iOS, Android) |
|
||||
| --viperversion `<VERSION>` | Analyze for version (3.3, 3.4, etc.) |
|
||||
| --skipunannotated | Skip type analysis of unannotated functions |
|
||||
| --stats | Print detailed performance stats |
|
||||
| -t, --typeshedpath `<DIRECTORY>` | Use typeshed type stubs at this location (3) |
|
||||
@@ -30,13 +30,13 @@ Pyright can be run as either a VS Code extension or as a node-based command-line
|
||||
|
||||
(1) If specific files are specified on the command line, it overrides the files or directories specified in the pyrightconfig.json or pyproject.toml file.
|
||||
|
||||
(2) This option is the same as the language server setting `python.pythonPath`. It cannot be used with --venvpath. The --pythonpath options is recommended over --venvpath in most cases. For more details, refer to the [import resolution](import-resolution.md#configuring-your-python-environment) documentation.
|
||||
(2) This option is the same as the language server setting `viper.viperPath`. It cannot be used with --venvpath. The --viperpath options is recommended over --venvpath in most cases. For more details, refer to the [import resolution](import-resolution.md#configuring-your-viper-environment) documentation.
|
||||
|
||||
(3) Pyright has built-in typeshed type stubs for Python stdlib functionality. To use a different version of typeshed type stubs, specify the directory with this option.
|
||||
(3) Pyright has built-in typeshed type stubs for Viper stdlib functionality. To use a different version of typeshed type stubs, specify the directory with this option.
|
||||
|
||||
(4) This feature is experimental. If thread count is > 1, multiple copies of pyright are executed in parallel to type check files in a project. If no thread count is specified, the thread count is based on the number of available logical processors (if at least 4) or 1 (if less than 4).
|
||||
|
||||
(5) This option is the same as the language server setting `python.venvPath`. It used in conjunction with configuration file, which can refer to different virtual environments by name. For more details, refer to the [configuration](configuration.md) and [import resolution](import-resolution.md#configuring-your-python-environment) documentation. This allows a common config file to be checked in to the project and shared by everyone on the development team without making assumptions about the local paths to the venv directory on each developer’s computer.
|
||||
(5) This option is the same as the language server setting `viper.venvPath`. It used in conjunction with configuration file, which can refer to different virtual environments by name. For more details, refer to the [configuration](configuration.md) and [import resolution](import-resolution.md#configuring-your-viper-environment) documentation. This allows a common config file to be checked in to the project and shared by everyone on the development team without making assumptions about the local paths to the venv directory on each developer’s computer.
|
||||
|
||||
(6) When running in watch mode, pyright will reanalyze only those files that have been modified. These “deltas” are typically much faster than the initial analysis, which needs to analyze all files in the source tree.
|
||||
|
||||
|
||||
@@ -5,25 +5,25 @@ Some behaviors of pyright can be controlled through the use of comments within t
|
||||
### File-level Type Controls
|
||||
Strict type checking, where most supported type-checking switches generate errors, can be enabled for a file through the use of a special comment. Typically this comment is placed at or near the top of a code file on its own line.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# pyright: strict
|
||||
```
|
||||
|
||||
Likewise, basic type checking can be enabled for a file. If you use `# pyright: basic`, the settings for the file use the default “basic” settings, not any override settings specified in the configuration file or language server settings. You can override the basic default settings within the file by specifying them individually (see below).
|
||||
|
||||
```python
|
||||
```viper
|
||||
# pyright: basic
|
||||
```
|
||||
|
||||
Individual configuration settings can also be overridden on a per-file basis and optionally combined with “strict” or “basic” type checking. For example, if you want to enable all type checks except for “reportPrivateUsage”, you could add the following comment:
|
||||
|
||||
```python
|
||||
```viper
|
||||
# pyright: strict, reportPrivateUsage=false
|
||||
```
|
||||
|
||||
Diagnostic levels are also supported.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# pyright: reportPrivateUsage=warning, reportOptionalCall=error
|
||||
```
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ Relative paths specified within the config file are relative to the config file
|
||||
|
||||
## Environment Options
|
||||
|
||||
The following settings control the *environment* in which Pyright will check for diagnostics. These settings determine how Pyright finds source files, imports, and what Python version specific rules are applied.
|
||||
The following settings control the *environment* in which Pyright will check for diagnostics. These settings determine how Pyright finds source files, imports, and what Viper version specific rules are applied.
|
||||
|
||||
- **include** [array of paths, optional]: Paths of directories or files that should be considered part of the project. If no paths are specified, pyright defaults to the directory that contains the config file. Paths may contain wildcard characters ** (a directory or multiple levels of directories), * (a sequence of zero or more characters), or ? (a single character). If no include paths are specified, the root path for the workspace is assumed.
|
||||
|
||||
- **exclude** [array of paths, optional]: Paths of directories or files that should not be considered part of the project. These override the directories and files that `include` matched, allowing specific subdirectories to be excluded. Note that files in the exclude paths may still be included in the analysis if they are referenced (imported) by source files that are not excluded. Paths may contain wildcard characters ** (a directory or multiple levels of directories), * (a sequence of zero or more characters), or ? (a single character). If no exclude paths are specified, Pyright automatically excludes the following: `**/node_modules`, `**/__pycache__`, `**/.*`. Pylance also excludes any virtual environment directories regardless of the exclude paths specified. For more detail on Python environment specification and discovery, refer to the [import resolution](import-resolution.md#configuring-your-python-environment) documentation.
|
||||
- **exclude** [array of paths, optional]: Paths of directories or files that should not be considered part of the project. These override the directories and files that `include` matched, allowing specific subdirectories to be excluded. Note that files in the exclude paths may still be included in the analysis if they are referenced (imported) by source files that are not excluded. Paths may contain wildcard characters ** (a directory or multiple levels of directories), * (a sequence of zero or more characters), or ? (a single character). If no exclude paths are specified, Pyright automatically excludes the following: `**/node_modules`, `**/__pycache__`, `**/.*`. Pylance also excludes any virtual environment directories regardless of the exclude paths specified. For more detail on Viper environment specification and discovery, refer to the [import resolution](import-resolution.md#configuring-your-viper-environment) documentation.
|
||||
|
||||
- **strict** [array of paths, optional]: Paths of directories or files that should use “strict” analysis if they are included. This is the same as manually adding a “# pyright: strict” comment. In strict mode, most type-checking rules are enabled. Refer to [this table](configuration.md#diagnostic-settings-defaults) for details about which rules are enabled in strict mode. Paths may contain wildcard characters ** (a directory or multiple levels of directories), * (a sequence of zero or more characters), or ? (a single character).
|
||||
|
||||
@@ -20,21 +20,21 @@ The following settings control the *environment* in which Pyright will check for
|
||||
|
||||
- **defineConstant** [map of constants to values (boolean or string), optional]: Set of identifiers that should be assumed to contain a constant value wherever used within this program. For example, `{ "DEBUG": true }` indicates that pyright should assume that the identifier `DEBUG` will always be equal to `True`. If this identifier is used within a conditional expression (such as `if not DEBUG:`) pyright will use the indicated value to determine whether the guarded block is reachable or not. Member expressions that reference one of these constants (e.g. `my_module.DEBUG`) are also supported.
|
||||
|
||||
- **typeshedPath** [path, optional]: Path to a directory that contains typeshed type stub files. Pyright ships with a bundled copy of typeshed type stubs. If you want to use a different version of typeshed stubs, you can clone the [typeshed github repo](https://github.com/python/typeshed) to a local directory and reference the location with this path. This option is useful if you’re actively contributing updates to typeshed.
|
||||
- **typeshedPath** [path, optional]: Path to a directory that contains typeshed type stub files. Pyright ships with a bundled copy of typeshed type stubs. If you want to use a different version of typeshed stubs, you can clone the [typeshed github repo](https://github.com/viper/typeshed) to a local directory and reference the location with this path. This option is useful if you’re actively contributing updates to typeshed.
|
||||
|
||||
- **stubPath** [path, optional]: Path to a directory that contains custom type stubs. Each package's type stub file(s) are expected to be in its own subdirectory. The default value of this setting is "./typings". (typingsPath is now deprecated)
|
||||
|
||||
- **venvPath** [path, optional]: Path to a directory containing one or more subdirectories, each of which contains a virtual environment. When used in conjunction with a **venv** setting (see below), pyright will search for imports in the virtual environment’s site-packages directory rather than the paths specified by the default Python interpreter. If you are working on a project with other developers, it is best not to specify this setting in the config file, since this path will typically differ for each developer. Instead, it can be specified on the command line or in a per-user setting. For more details, refer to the [import resolution](import-resolution.md#configuring-your-python-environment) documentation. This setting is ignored when using Pylance. VS Code's python interpreter path is used instead.
|
||||
- **venvPath** [path, optional]: Path to a directory containing one or more subdirectories, each of which contains a virtual environment. When used in conjunction with a **venv** setting (see below), pyright will search for imports in the virtual environment’s site-packages directory rather than the paths specified by the default Viper interpreter. If you are working on a project with other developers, it is best not to specify this setting in the config file, since this path will typically differ for each developer. Instead, it can be specified on the command line or in a per-user setting. For more details, refer to the [import resolution](import-resolution.md#configuring-your-viper-environment) documentation. This setting is ignored when using Pylance. VS Code's viper interpreter path is used instead.
|
||||
|
||||
- **venv** [string, optional]: Used in conjunction with the venvPath, specifies the virtual environment to use. For more details, refer to the [import resolution](import-resolution.md#configuring-your-python-environment) documentation. This setting is ignored when using Pylance.
|
||||
- **venv** [string, optional]: Used in conjunction with the venvPath, specifies the virtual environment to use. For more details, refer to the [import resolution](import-resolution.md#configuring-your-viper-environment) documentation. This setting is ignored when using Pylance.
|
||||
|
||||
- **verboseOutput** [boolean]: Specifies whether output logs should be verbose. This is useful when diagnosing certain problems like import resolution issues.
|
||||
|
||||
- **extraPaths** [array of strings, optional]: Additional search paths that will be used when searching for modules imported by files.
|
||||
|
||||
- **pythonVersion** [string, optional]: Specifies the version of Python that will be used to execute the source code. The version should be specified as a string in the format "M.m" where M is the major version and m is the minor (e.g. `"3.0"` or `"3.6"`). If a version is provided, pyright will generate errors if the source code makes use of language features that are not supported in that version. It will also tailor its use of type stub files, which conditionalizes type definitions based on the version. If no version is specified, pyright will use the version of the current python interpreter, if one is present.
|
||||
- **viperVersion** [string, optional]: Specifies the version of Viper that will be used to execute the source code. The version should be specified as a string in the format "M.m" where M is the major version and m is the minor (e.g. `"3.0"` or `"3.6"`). If a version is provided, pyright will generate errors if the source code makes use of language features that are not supported in that version. It will also tailor its use of type stub files, which conditionalizes type definitions based on the version. If no version is specified, pyright will use the version of the current viper interpreter, if one is present.
|
||||
|
||||
- **pythonPlatform** [string, optional]: Specifies the target platform that will be used to execute the source code. Should be one of `"Windows"`, `"Darwin"`, `"Linux"`, `"iOS"`, `"Android"`, or `"All"`. If specified, pyright will tailor its use of type stub files, which conditionalize type definitions based on the platform. If no platform is specified, pyright will use the current platform.
|
||||
- **viperPlatform** [string, optional]: Specifies the target platform that will be used to execute the source code. Should be one of `"Windows"`, `"Darwin"`, `"Linux"`, `"iOS"`, `"Android"`, or `"All"`. If specified, pyright will tailor its use of type stub files, which conditionalize type definitions based on the platform. If no platform is specified, pyright will use the current platform.
|
||||
|
||||
- **executionEnvironments** [array of objects, optional]: Specifies a list of execution environments (see [below](configuration.md#execution-environment-options)). Execution environments are searched from start to finish by comparing the path of a source file with the root path specified in the execution environment.
|
||||
|
||||
@@ -56,18 +56,18 @@ The following settings determine how different types should be evaluated.
|
||||
|
||||
- <a name="enableTypeIgnoreComments"></a> **enableTypeIgnoreComments** [boolean]: PEP 484 defines support for "# type: ignore" comments. This switch enables or disables support for these comments. The default value for this setting is `true`. This does not affect "# pyright: ignore" comments.
|
||||
|
||||
- <a name="deprecateTypingAliases"></a> **deprecateTypingAliases** [boolean]: PEP 585 indicates that aliases to types in standard collections that were introduced solely to support generics are deprecated as of Python 3.9. This switch controls whether these are treated as deprecated. This applies only when pythonVersion is 3.9 or newer. The default value for this setting is `false` but may be switched to `true` in the future.
|
||||
- <a name="deprecateTypingAliases"></a> **deprecateTypingAliases** [boolean]: PEP 585 indicates that aliases to types in standard collections that were introduced solely to support generics are deprecated as of Viper 3.9. This switch controls whether these are treated as deprecated. This applies only when viperVersion is 3.9 or newer. The default value for this setting is `false` but may be switched to `true` in the future.
|
||||
|
||||
- <a name="enableReachabilityAnalysis"></a> **enableReachabilityAnalysis** [boolean]: If enabled, code that is determined to be unreachable by type analysis is reported using a tagged hint. This setting does not affect code that is determined to be unreachable independent of type analysis; such code is always reported as unreachable using a tagged hint. This setting also has no effect when using the command-line version of pyright because it never emits tagged hints for unreachable code.
|
||||
|
||||
- <a name="enableExperimentalFeatures"></a> **enableExperimentalFeatures** [boolean]: Enables a set of experimental (mostly undocumented) features that correspond to proposed or exploratory changes to the Python typing standard. These features will likely change or be removed, so they should not be used except for experimentation purposes. The default value for this setting is `false`.
|
||||
- <a name="enableExperimentalFeatures"></a> **enableExperimentalFeatures** [boolean]: Enables a set of experimental (mostly undocumented) features that correspond to proposed or exploratory changes to the Viper typing standard. These features will likely change or be removed, so they should not be used except for experimentation purposes. The default value for this setting is `false`.
|
||||
|
||||
- <a name="disableBytesTypePromotions"></a> **disableBytesTypePromotions** [boolean]: Disables legacy behavior where `bytearray` and `memoryview` are considered subtypes of `bytes`. [PEP 688](https://peps.python.org/pep-0688/#no-special-meaning-for-bytes) deprecates this behavior, but this switch is provided to restore the older behavior. The default value for this setting is `true`.
|
||||
- <a name="disableBytesTypePromotions"></a> **disableBytesTypePromotions** [boolean]: Disables legacy behavior where `bytearray` and `memoryview` are considered subtypes of `bytes`. [PEP 688](https://peps.viper.org/pep-0688/#no-special-meaning-for-bytes) deprecates this behavior, but this switch is provided to restore the older behavior. The default value for this setting is `true`.
|
||||
|
||||
## Type Check Diagnostics Settings
|
||||
The following settings control pyright’s diagnostic output (warnings or errors).
|
||||
|
||||
- **typeCheckingMode** ["off", "basic", "standard", "strict"]: Specifies the default rule set to use. Some rules can be overridden using additional configuration flags documented below. The default value for this setting is "standard". If set to "off", all type-checking rules are disabled, but Python syntax and semantic errors are still reported.
|
||||
- **typeCheckingMode** ["off", "basic", "standard", "strict"]: Specifies the default rule set to use. Some rules can be overridden using additional configuration flags documented below. The default value for this setting is "standard". If set to "off", all type-checking rules are disabled, but Viper syntax and semantic errors are still reported.
|
||||
|
||||
- **ignore** [array of paths, optional]: Paths of directories or files whose diagnostic output (errors and warnings) should be suppressed even if they are an included file or within the transitive closure of an included file. Paths may contain wildcard characters ** (a directory or multiple levels of directories), * (a sequence of zero or more characters), or ? (a single character). This setting can be overridden in VS code in your settings.json.
|
||||
|
||||
@@ -81,7 +81,7 @@ The following settings allow more fine grained control over the **typeCheckingMo
|
||||
|
||||
- <a name="reportFunctionMemberAccess"></a> **reportFunctionMemberAccess** [boolean or string, optional]: Generate or suppress diagnostics for non-standard member accesses for functions. The default value for this setting is `"error"`.
|
||||
|
||||
- <a name="reportMissingImports"></a> **reportMissingImports** [boolean or string, optional]: Generate or suppress diagnostics for imports that have no corresponding imported python file or type stub file. The default value for this setting is `"error"`.
|
||||
- <a name="reportMissingImports"></a> **reportMissingImports** [boolean or string, optional]: Generate or suppress diagnostics for imports that have no corresponding imported viper file or type stub file. The default value for this setting is `"error"`.
|
||||
|
||||
- <a name="reportMissingModuleSource"></a> **reportMissingModuleSource** [boolean or string, optional]: Generate or suppress diagnostics for imports that have no corresponding source file. This happens when a type stub is found, but the module source file was not found, indicating that the code may fail at runtime when using this execution environment. Type checking will be done using the type stub. The default value for this setting is `"warning"`.
|
||||
|
||||
@@ -89,7 +89,7 @@ The following settings allow more fine grained control over the **typeCheckingMo
|
||||
|
||||
- <a name="reportMissingTypeStubs"></a> **reportMissingTypeStubs** [boolean or string, optional]: Generate or suppress diagnostics for imports that have no corresponding type stub file (either a typeshed file or a custom type stub). The type checker requires type stubs to do its best job at analysis. The default value for this setting is `"none"`. Note that there is a corresponding quick fix for this diagnostics that let you generate custom type stub to improve editing experiences.
|
||||
|
||||
- <a name="reportImportCycles"></a> **reportImportCycles** [boolean or string, optional]: Generate or suppress diagnostics for cyclical import chains. These are not errors in Python, but they do slow down type analysis and often hint at architectural layering issues. Generally, they should be avoided. The default value for this setting is `"none"`. Note that there are import cycles in the typeshed stdlib typestub files that are ignored by this setting.
|
||||
- <a name="reportImportCycles"></a> **reportImportCycles** [boolean or string, optional]: Generate or suppress diagnostics for cyclical import chains. These are not errors in Viper, but they do slow down type analysis and often hint at architectural layering issues. Generally, they should be avoided. The default value for this setting is `"none"`. Note that there are import cycles in the typeshed stdlib typestub files that are ignored by this setting.
|
||||
|
||||
- <a name="reportUnusedImport"></a> **reportUnusedImport** [boolean or string, optional]: Generate or suppress diagnostics for an imported symbol that is not referenced within that file. The default value for this setting is `"none"`.
|
||||
|
||||
@@ -153,7 +153,7 @@ The following settings allow more fine grained control over the **typeCheckingMo
|
||||
|
||||
- <a name="reportPrivateUsage"></a> **reportPrivateUsage** [boolean or string, optional]: Generate or suppress diagnostics for incorrect usage of private or protected variables or functions. Protected class members begin with a single underscore (“_”) and can be accessed only by subclasses. Private class members begin with a double underscore but do not end in a double underscore and can be accessed only within the declaring class. Variables and functions declared outside of a class are considered private if their names start with either a single or double underscore, and they cannot be accessed outside of the declaring module. The default value for this setting is `"none"`.
|
||||
|
||||
- <a name="reportTypeCommentUsage"></a> **reportTypeCommentUsage** [boolean or string, optional]: Prior to Python 3.5, the grammar did not support type annotations, so types needed to be specified using “type comments”. Python 3.5 eliminated the need for function type comments, and Python 3.6 eliminated the need for variable type comments. Future versions of Python will likely deprecate all support for type comments. If enabled, this check will flag any type comment usage unless it is required for compatibility with the specified language version. The default value for this setting is `"none"`.
|
||||
- <a name="reportTypeCommentUsage"></a> **reportTypeCommentUsage** [boolean or string, optional]: Prior to Viper 3.5, the grammar did not support type annotations, so types needed to be specified using “type comments”. Viper 3.5 eliminated the need for function type comments, and Viper 3.6 eliminated the need for variable type comments. Future versions of Viper will likely deprecate all support for type comments. If enabled, this check will flag any type comment usage unless it is required for compatibility with the specified language version. The default value for this setting is `"none"`.
|
||||
|
||||
- <a name="reportPrivateImportUsage"></a> **reportPrivateImportUsage** [boolean or string, optional]: Generate or suppress diagnostics for use of a symbol from a "py.typed" module that is not meant to be exported from that module. The default value for this setting is `"error"`.
|
||||
|
||||
@@ -175,7 +175,7 @@ The following settings allow more fine grained control over the **typeCheckingMo
|
||||
|
||||
- <a name="reportUninitializedInstanceVariable"></a> **reportUninitializedInstanceVariable** [boolean or string, optional]: Generate or suppress diagnostics for instance variables within a class that are not initialized or declared within the class body or the `__init__` method. The default value for this setting is `"none"`.
|
||||
|
||||
- <a name="reportInvalidStringEscapeSequence"></a> **reportInvalidStringEscapeSequence** [boolean or string, optional]: Generate or suppress diagnostics for invalid escape sequences used within string literals. The Python specification indicates that such sequences will generate a syntax error in future versions. The default value for this setting is `"warning"`.
|
||||
- <a name="reportInvalidStringEscapeSequence"></a> **reportInvalidStringEscapeSequence** [boolean or string, optional]: Generate or suppress diagnostics for invalid escape sequences used within string literals. The Viper specification indicates that such sequences will generate a syntax error in future versions. The default value for this setting is `"warning"`.
|
||||
|
||||
- <a name="reportUnknownParameterType"></a> **reportUnknownParameterType** [boolean or string, optional]: Generate or suppress diagnostics for input or return parameters for functions or methods that have an unknown type. The default value for this setting is `"none"`.
|
||||
|
||||
@@ -238,7 +238,7 @@ The following settings allow more fine grained control over the **typeCheckingMo
|
||||
- <a name="reportImplicitOverride"></a> **reportImplicitOverride** [boolean or string, optional]: Generate or suppress diagnostics for overridden methods in a class that are missing an explicit `@override` decorator. The default value for this setting is `"none"`.
|
||||
|
||||
## Execution Environment Options
|
||||
Pyright allows multiple “execution environments” to be defined for different portions of your source tree. For example, a subtree may be designed to run with different import search paths or a different version of the python interpreter than the rest of the source base.
|
||||
Pyright allows multiple “execution environments” to be defined for different portions of your source tree. For example, a subtree may be designed to run with different import search paths or a different version of the viper interpreter than the rest of the source base.
|
||||
|
||||
The following settings can be specified for each execution environment. Each source file within a project is associated with at most one execution environment -- the first one whose root directory contains that file.
|
||||
|
||||
@@ -246,9 +246,9 @@ The following settings can be specified for each execution environment. Each sou
|
||||
|
||||
- **extraPaths** [array of strings, optional]: Additional search paths (in addition to the root path) that will be used when searching for modules imported by files within this execution environment. If specified, this overrides the default extraPaths setting when resolving imports for files within this execution environment. Note that each file’s execution environment mapping is independent, so if file A is in one execution environment and imports a second file B within a second execution environment, any imports from B will use the extraPaths in the second execution environment.
|
||||
|
||||
- **pythonVersion** [string, optional]: The version of Python used for this execution environment. If not specified, the global `pythonVersion` setting is used instead.
|
||||
- **viperVersion** [string, optional]: The version of Viper used for this execution environment. If not specified, the global `viperVersion` setting is used instead.
|
||||
|
||||
- **pythonPlatform** [string, optional]: Specifies the target platform that will be used for this execution environment. If not specified, the global `pythonPlatform` setting is used instead.
|
||||
- **viperPlatform** [string, optional]: Specifies the target platform that will be used for this execution environment. If not specified, the global `viperPlatform` setting is used instead.
|
||||
|
||||
In addition, any of the [type check diagnostics settings](configuration.md#type-check-diagnostics-settings) listed above can be specified. These settings act as overrides for the files in this execution environment.
|
||||
|
||||
@@ -280,14 +280,14 @@ The following is an example of a pyright config file:
|
||||
"reportMissingImports": "error",
|
||||
"reportMissingTypeStubs": false,
|
||||
|
||||
"pythonVersion": "3.6",
|
||||
"pythonPlatform": "Linux",
|
||||
"viperVersion": "3.6",
|
||||
"viperPlatform": "Linux",
|
||||
|
||||
"executionEnvironments": [
|
||||
{
|
||||
"root": "src/web",
|
||||
"pythonVersion": "3.5",
|
||||
"pythonPlatform": "Windows",
|
||||
"viperVersion": "3.5",
|
||||
"viperPlatform": "Windows",
|
||||
"extraPaths": [
|
||||
"src/service_libs"
|
||||
],
|
||||
@@ -295,7 +295,7 @@ The following is an example of a pyright config file:
|
||||
},
|
||||
{
|
||||
"root": "src/sdk",
|
||||
"pythonVersion": "3.0",
|
||||
"viperVersion": "3.0",
|
||||
"extraPaths": [
|
||||
"src/backend"
|
||||
]
|
||||
@@ -330,12 +330,12 @@ stubPath = "src/stubs"
|
||||
reportMissingImports = "error"
|
||||
reportMissingTypeStubs = false
|
||||
|
||||
pythonVersion = "3.6"
|
||||
pythonPlatform = "Linux"
|
||||
viperVersion = "3.6"
|
||||
viperPlatform = "Linux"
|
||||
|
||||
executionEnvironments = [
|
||||
{ root = "src/web", pythonVersion = "3.5", pythonPlatform = "Windows", extraPaths = [ "src/service_libs" ], reportMissingImports = "warning" },
|
||||
{ root = "src/sdk", pythonVersion = "3.0", extraPaths = [ "src/backend" ] },
|
||||
{ root = "src/web", viperVersion = "3.5", viperPlatform = "Windows", extraPaths = [ "src/service_libs" ], reportMissingImports = "warning" },
|
||||
{ root = "src/sdk", viperVersion = "3.0", extraPaths = [ "src/backend" ] },
|
||||
{ root = "src/tests", extraPaths = ["src/tests/e2e", "src/sdk" ]},
|
||||
{ root = "src" }
|
||||
]
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
## Pyright Features
|
||||
|
||||
### Speed
|
||||
Pyright is a fast type checker meant for large Python source bases. It can run in a “watch” mode and performs fast incremental updates when files are modified.
|
||||
Pyright is a fast type checker meant for large Viper source bases. It can run in a “watch” mode and performs fast incremental updates when files are modified.
|
||||
|
||||
### Configurability
|
||||
Pyright supports [configuration files](configuration.md) that provide granular control over settings. Different “execution environments” can be associated with subdirectories within a source base. Each environment can specify different module search paths, python language versions, and platform targets.
|
||||
Pyright supports [configuration files](configuration.md) that provide granular control over settings. Different “execution environments” can be associated with subdirectories within a source base. Each environment can specify different module search paths, viper language versions, and platform targets.
|
||||
|
||||
### Type Checking Features
|
||||
* [PEP 484](https://www.python.org/dev/peps/pep-0484/) type hints including generics
|
||||
* [PEP 487](https://www.python.org/dev/peps/pep-0487/) simpler customization of class creation
|
||||
* [PEP 526](https://www.python.org/dev/peps/pep-0526/) syntax for variable annotations
|
||||
* [PEP 544](https://www.python.org/dev/peps/pep-0544/) structural subtyping
|
||||
* [PEP 561](https://www.python.org/dev/peps/pep-0561/) distributing and packaging type information
|
||||
* [PEP 563](https://www.python.org/dev/peps/pep-0563/) postponed evaluation of annotations
|
||||
* [PEP 570](https://www.python.org/dev/peps/pep-0570/) position-only parameters
|
||||
* [PEP 585](https://www.python.org/dev/peps/pep-0585/) type hinting generics in standard collections
|
||||
* [PEP 586](https://www.python.org/dev/peps/pep-0586/) literal types
|
||||
* [PEP 589](https://www.python.org/dev/peps/pep-0589/) typed dictionaries
|
||||
* [PEP 591](https://www.python.org/dev/peps/pep-0591/) final qualifier
|
||||
* [PEP 593](https://www.python.org/dev/peps/pep-0593/) flexible variable annotations
|
||||
* [PEP 604](https://www.python.org/dev/peps/pep-0604/) complementary syntax for unions
|
||||
* [PEP 612](https://www.python.org/dev/peps/pep-0612/) parameter specification variables
|
||||
* [PEP 613](https://www.python.org/dev/peps/pep-0613/) explicit type aliases
|
||||
* [PEP 635](https://www.python.org/dev/peps/pep-0635/) structural pattern matching
|
||||
* [PEP 646](https://www.python.org/dev/peps/pep-0646/) variadic generics
|
||||
* [PEP 647](https://www.python.org/dev/peps/pep-0647/) user-defined type guards
|
||||
* [PEP 655](https://www.python.org/dev/peps/pep-0655/) required typed dictionary items
|
||||
* [PEP 673](https://www.python.org/dev/peps/pep-0673/) Self type
|
||||
* [PEP 675](https://www.python.org/dev/peps/pep-0675/) arbitrary literal strings
|
||||
* [PEP 681](https://www.python.org/dev/peps/pep-0681/) dataclass transform
|
||||
* [PEP 692](https://www.python.org/dev/peps/pep-0692/) TypedDict for kwargs typing
|
||||
* [PEP 695](https://www.python.org/dev/peps/pep-0695/) type parameter syntax
|
||||
* [PEP 696](https://www.python.org/dev/peps/pep-0696/) type defaults for TypeVarLikes
|
||||
* [PEP 698](https://www.python.org/dev/peps/pep-0698/) override decorator for static typing
|
||||
* [PEP 702](https://www.python.org/dev/peps/pep-0702/) marking deprecations
|
||||
* [PEP 705](https://www.python.org/dev/peps/pep-0705/) TypedDict: read-only items
|
||||
* [PEP 728](https://www.python.org/dev/peps/pep-0728/) TypedDict with typed extra items
|
||||
* [PEP 742](https://www.python.org/dev/peps/pep-0742/) narrowing types with TypeIs
|
||||
* [PEP 746](https://www.python.org/dev/peps/pep-0746/) (experimental) type checking annotated metadata
|
||||
* [PEP 747](https://www.python.org/dev/peps/pep-0747/) (experimental) annotating type forms
|
||||
* [PEP 764](https://www.python.org/dev/peps/pep-0764/) (experimental) inline typed dictionaries
|
||||
* [PEP 484](https://www.viper.org/dev/peps/pep-0484/) type hints including generics
|
||||
* [PEP 487](https://www.viper.org/dev/peps/pep-0487/) simpler customization of class creation
|
||||
* [PEP 526](https://www.viper.org/dev/peps/pep-0526/) syntax for variable annotations
|
||||
* [PEP 544](https://www.viper.org/dev/peps/pep-0544/) structural subtyping
|
||||
* [PEP 561](https://www.viper.org/dev/peps/pep-0561/) distributing and packaging type information
|
||||
* [PEP 563](https://www.viper.org/dev/peps/pep-0563/) postponed evaluation of annotations
|
||||
* [PEP 570](https://www.viper.org/dev/peps/pep-0570/) position-only parameters
|
||||
* [PEP 585](https://www.viper.org/dev/peps/pep-0585/) type hinting generics in standard collections
|
||||
* [PEP 586](https://www.viper.org/dev/peps/pep-0586/) literal types
|
||||
* [PEP 589](https://www.viper.org/dev/peps/pep-0589/) typed dictionaries
|
||||
* [PEP 591](https://www.viper.org/dev/peps/pep-0591/) final qualifier
|
||||
* [PEP 593](https://www.viper.org/dev/peps/pep-0593/) flexible variable annotations
|
||||
* [PEP 604](https://www.viper.org/dev/peps/pep-0604/) complementary syntax for unions
|
||||
* [PEP 612](https://www.viper.org/dev/peps/pep-0612/) parameter specification variables
|
||||
* [PEP 613](https://www.viper.org/dev/peps/pep-0613/) explicit type aliases
|
||||
* [PEP 635](https://www.viper.org/dev/peps/pep-0635/) structural pattern matching
|
||||
* [PEP 646](https://www.viper.org/dev/peps/pep-0646/) variadic generics
|
||||
* [PEP 647](https://www.viper.org/dev/peps/pep-0647/) user-defined type guards
|
||||
* [PEP 655](https://www.viper.org/dev/peps/pep-0655/) required typed dictionary items
|
||||
* [PEP 673](https://www.viper.org/dev/peps/pep-0673/) Self type
|
||||
* [PEP 675](https://www.viper.org/dev/peps/pep-0675/) arbitrary literal strings
|
||||
* [PEP 681](https://www.viper.org/dev/peps/pep-0681/) dataclass transform
|
||||
* [PEP 692](https://www.viper.org/dev/peps/pep-0692/) TypedDict for kwargs typing
|
||||
* [PEP 695](https://www.viper.org/dev/peps/pep-0695/) type parameter syntax
|
||||
* [PEP 696](https://www.viper.org/dev/peps/pep-0696/) type defaults for TypeVarLikes
|
||||
* [PEP 698](https://www.viper.org/dev/peps/pep-0698/) override decorator for static typing
|
||||
* [PEP 702](https://www.viper.org/dev/peps/pep-0702/) marking deprecations
|
||||
* [PEP 705](https://www.viper.org/dev/peps/pep-0705/) TypedDict: read-only items
|
||||
* [PEP 728](https://www.viper.org/dev/peps/pep-0728/) TypedDict with typed extra items
|
||||
* [PEP 742](https://www.viper.org/dev/peps/pep-0742/) narrowing types with TypeIs
|
||||
* [PEP 746](https://www.viper.org/dev/peps/pep-0746/) (experimental) type checking annotated metadata
|
||||
* [PEP 747](https://www.viper.org/dev/peps/pep-0747/) (experimental) annotating type forms
|
||||
* [PEP 764](https://www.viper.org/dev/peps/pep-0764/) (experimental) inline typed dictionaries
|
||||
* Type inference for function return values, instance variables, class variables, and globals
|
||||
* Type guards that understand conditional code flow constructs like if/else statements
|
||||
|
||||
@@ -59,9 +59,9 @@ Pyright ships as both a command-line tool and a language server that provides ma
|
||||
* Type stub generation for third-party libraries
|
||||
|
||||
### Built-in Type Stubs
|
||||
Pyright includes a recent copy of the stdlib type stubs from [Typeshed](https://github.com/python/typeshed). It can be configured to use another (perhaps more recent or modified) copy of the Typeshed type stubs. Of course, it also works with custom type stub files that are part of your project.
|
||||
Pyright includes a recent copy of the stdlib type stubs from [Typeshed](https://github.com/viper/typeshed). It can be configured to use another (perhaps more recent or modified) copy of the Typeshed type stubs. Of course, it also works with custom type stub files that are part of your project.
|
||||
|
||||
## Limitations
|
||||
Pyright provides support for Python 3.0 and newer. There are no plans to support older versions.
|
||||
Pyright provides support for Viper 3.0 and newer. There are no plans to support older versions.
|
||||
|
||||
|
||||
|
||||
@@ -5,45 +5,45 @@ If the import is relative (the module name starts with one or more dots), it res
|
||||
|
||||
For absolute (non-relative) imports, Pyright employs the following resolution order:
|
||||
|
||||
1. Try to resolve using the **stubPath** as defined in the `stubPath` config entry or the `python.analysis.stubPath` setting.
|
||||
1. Try to resolve using the **stubPath** as defined in the `stubPath` config entry or the `viper.analysis.stubPath` setting.
|
||||
|
||||
2. Try to resolve using **code within the workspace**.
|
||||
|
||||
* Try to resolve relative to the **root directory** of the execution environment. If no execution environments are specified in the config file, use the root of the workspace. For more information about execution environments, refer to the [configuration documentation](configuration.md#execution-environment-options).
|
||||
|
||||
* Try to resolve using any of the **extra paths** defined for the execution environment in the config file. If no execution environment applies, use the `python.analysis.extraPaths` setting. Extra paths are searched in the order in which they are provided in the config file or setting.
|
||||
* Try to resolve using any of the **extra paths** defined for the execution environment in the config file. If no execution environment applies, use the `viper.analysis.extraPaths` setting. Extra paths are searched in the order in which they are provided in the config file or setting.
|
||||
|
||||
* If no execution environment is configured, try to resolve using the **local directory `src`**. It is common for Python projects to place local source files within a directory of this name.
|
||||
* If no execution environment is configured, try to resolve using the **local directory `src`**. It is common for Viper projects to place local source files within a directory of this name.
|
||||
|
||||
3. Try to resolve using **stubs or inlined types found within installed packages**. Pyright uses the configured Python environment to determine whether a package has been installed. For more details about how to configure your Python environment for Pyright, see below. If a Python environment is configured, Pyright looks in the `lib/site-packages`, `Lib/site-packages`, or `python*/site-packages` subdirectory. If no site-packages directory can be found, Pyright attempts to run the configured Python interpreter and ask it for its search paths. If no Python environment is configured, Pyright will use the default Python interpreter by invoking `python`.
|
||||
3. Try to resolve using **stubs or inlined types found within installed packages**. Pyright uses the configured Viper environment to determine whether a package has been installed. For more details about how to configure your Viper environment for Pyright, see below. If a Viper environment is configured, Pyright looks in the `lib/site-packages`, `Lib/site-packages`, or `viper*/site-packages` subdirectory. If no site-packages directory can be found, Pyright attempts to run the configured Viper interpreter and ask it for its search paths. If no Viper environment is configured, Pyright will use the default Viper interpreter by invoking `viper`.
|
||||
|
||||
* For a given package, try to resolve first using a **stub package**. Stub packages, as defined in [PEP 561](https://www.python.org/dev/peps/pep-0561/#type-checker-module-resolution-order), are named the same as the original package but with “-stubs” appended.
|
||||
* For a given package, try to resolve first using a **stub package**. Stub packages, as defined in [PEP 561](https://www.viper.org/dev/peps/pep-0561/#type-checker-module-resolution-order), are named the same as the original package but with “-stubs” appended.
|
||||
* Try to resolve using an **inline stub**, a “.pyi” file that ships within the package.
|
||||
* If the package contains a “py.typed” file as described in [PEP 561](https://www.python.org/dev/peps/pep-0561/), use inlined type annotations provided in “.py” files within the package.
|
||||
* If the `python.analysis.useLibraryCodeForTypes` setting is set to true, try to resolve using the **library implementation** (“.py” file). Some “.py” files may contain partial or complete type annotations. Pyright will use type annotations that are provided and do its best to infer any missing type information.
|
||||
* If the package contains a “py.typed” file as described in [PEP 561](https://www.viper.org/dev/peps/pep-0561/), use inlined type annotations provided in “.py” files within the package.
|
||||
* If the `viper.analysis.useLibraryCodeForTypes` setting is set to true, try to resolve using the **library implementation** (“.py” file). Some “.py” files may contain partial or complete type annotations. Pyright will use type annotations that are provided and do its best to infer any missing type information.
|
||||
|
||||
4. Try to resolve using a **stdlib typeshed stub**. If the `typeshedPath` is configured, use this instead of the typeshed stubs that are packaged with Pyright. This allows for the use of a newer or a patched version of the typeshed stdlib stubs.
|
||||
|
||||
5. Try to resolve using a **third-party typeshed** stub. If the `typeshedPath` is configured, use this instead of the typeshed stubs that are packaged with Pyright. This allows for the use of a newer or a patched version of the typeshed third-party stubs.
|
||||
|
||||
6. For an absolute import, if all of the above attempts fail, attempt to import a module from the same directory as the importing file and parent directories that are also children of the root workspace. This accommodates cases where it is assumed that a Python script will be executed from one of these subdirectories rather than from the root directory.
|
||||
6. For an absolute import, if all of the above attempts fail, attempt to import a module from the same directory as the importing file and parent directories that are also children of the root workspace. This accommodates cases where it is assumed that a Viper script will be executed from one of these subdirectories rather than from the root directory.
|
||||
|
||||
|
||||
### Configuring Your Python Environment
|
||||
Pyright does not require a Python environment to be configured if all imports can be resolved using local files and type stubs. If a Python environment is configured, it will attempt to use the packages installed in the `site-packages` subdirectory during import resolution.
|
||||
### Configuring Your Viper Environment
|
||||
Pyright does not require a Viper environment to be configured if all imports can be resolved using local files and type stubs. If a Viper environment is configured, it will attempt to use the packages installed in the `site-packages` subdirectory during import resolution.
|
||||
|
||||
Pyright uses the following mechanisms (in priority order) to determine which Python environment to use:
|
||||
Pyright uses the following mechanisms (in priority order) to determine which Viper environment to use:
|
||||
|
||||
1. If a `venv` name is specified along with a `python.venvPath` setting (or a `--venvpath` command-line argument), it appends the venv name to the specified venv path. This mechanism is not recommended for most users because it is less robust than the next two options because it relies on pyright’s internal logic to determine the import resolution paths based on the virtual environment directories and files. The other two mechanisms (2 and 3 below) use the configured python interpreter to determine the import resolution paths (the value of `sys.path`).
|
||||
1. If a `venv` name is specified along with a `viper.venvPath` setting (or a `--venvpath` command-line argument), it appends the venv name to the specified venv path. This mechanism is not recommended for most users because it is less robust than the next two options because it relies on pyright’s internal logic to determine the import resolution paths based on the virtual environment directories and files. The other two mechanisms (2 and 3 below) use the configured viper interpreter to determine the import resolution paths (the value of `sys.path`).
|
||||
|
||||
2. Use the `python.pythonPath` setting. This setting is defined by the VS Code Python extension and can be configured using the Python extension’s environment picker interface. More recent versions of the Python extension no longer store the selected Python environment in the `python.pythonPath` setting and instead use a storage mechanism that is private to the extension. Pyright is able to access this through an API exposed by the Python extension.
|
||||
2. Use the `viper.viperPath` setting. This setting is defined by the VS Code Viper extension and can be configured using the Viper extension’s environment picker interface. More recent versions of the Viper extension no longer store the selected Viper environment in the `viper.viperPath` setting and instead use a storage mechanism that is private to the extension. Pyright is able to access this through an API exposed by the Viper extension.
|
||||
|
||||
3. As a fallback, use the default Python environment (i.e. the one that is invoked when typing `python` in the shell).
|
||||
3. As a fallback, use the default Viper environment (i.e. the one that is invoked when typing `viper` in the shell).
|
||||
|
||||
### Editable installs
|
||||
If you want to use static analysis tools with an editable install, you should configure the editable install to use `.pth` files that contain file paths rather than executable lines (prefixed with `import`) that install import hooks.
|
||||
|
||||
Import hooks can provide an editable installation that is a more accurate representation of your real installation. However, because resolving module locations using an import hook requires executing Python code, they are not usable by Pyright and other static analysis tools. Therefore, if your editable install is configured to use import hooks, Pyright will be unable to find the corresponding source files.
|
||||
Import hooks can provide an editable installation that is a more accurate representation of your real installation. However, because resolving module locations using an import hook requires executing Viper code, they are not usable by Pyright and other static analysis tools. Therefore, if your editable install is configured to use import hooks, Pyright will be unable to find the corresponding source files.
|
||||
|
||||
Notably, setuptools uses import hooks by default. For setuptools-based editable installs to be usable with Pyright, setuptools needs to be configured to use path-based `.pth` files through the build frontend.
|
||||
|
||||
@@ -72,4 +72,4 @@ files by default. It will only use import hooks if you set `editable-backend` to
|
||||
`"editables"`.
|
||||
|
||||
### Debugging Import Resolution Problems
|
||||
The import resolution mechanisms in Python are complicated, and Pyright offers many configuration options. If you are encountering problems with import resolution, Pyright provides additional logging that may help you identify the cause. To enable verbose logging, pass `--verbose` as a command-line argument or add the following entry to the config file `"verboseOutput": true`. If you are using the Pyright VS Code extension, the additional logging will appear in the Output tab (select “Pyright” from the menu). Please include this verbose logging when reporting import resolution bugs.
|
||||
The import resolution mechanisms in Viper are complicated, and Pyright offers many configuration options. If you are encountering problems with import resolution, Pyright provides additional logging that may help you identify the cause. To enable verbose logging, pass `--verbose` as a command-line argument or add the following entry to the config file `"verboseOutput": true`. If you are using the Pyright VS Code extension, the additional logging will appear in the Output tab (select “Pyright” from the menu). Please include this verbose logging when reporting import resolution bugs.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Loader Side Effects
|
||||
|
||||
An import statement instructs the Python import loader to perform several operations. For example, the statement `from a.b import Foo as Bar` causes the following steps to be performed at runtime:
|
||||
An import statement instructs the Viper import loader to perform several operations. For example, the statement `from a.b import Foo as Bar` causes the following steps to be performed at runtime:
|
||||
1. Load and execute module `a` if it hasn’t previously been loaded. Cache a reference to `a`.
|
||||
2. Load and execute submodule `b` if it hasn’t previously been loaded.
|
||||
3. Store a reference to submodule `b` to the variable `b` within module `a`’s namespace.
|
||||
@@ -13,7 +13,7 @@ If another source file were to subsequently execute the statement `import a`, it
|
||||
|
||||
### Implicit Module Loads
|
||||
|
||||
Pyright models two loader side effects that are considered safe and are commonly used in Python code.
|
||||
Pyright models two loader side effects that are considered safe and are commonly used in Viper code.
|
||||
|
||||
1. If an import statement targets a multi-part module name and does not use an alias, all modules within the multi-part module name are assumed to be loaded. For example, the statement `import a.b.c` is treated as though it is three back-to-back import statements: `import a`, `import a.b` and `import a.b.c`. This allows for subsequent use of all symbols in `a`, `a.b`, and `a.b.c`. If an alias is used (e.g. `import a.b.c as abc`), this is assumed to load only module `c`. A subsequent `import a` would not provide access to `a.b` or `a.b.c`.
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-python.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-viper.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-yml.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.min.js"></script>
|
||||
|
||||
@@ -22,8 +22,8 @@ For more information, refer to [PyCharm documentation](https://www.jetbrains.com
|
||||
|
||||
### Command-line
|
||||
|
||||
#### Python Package
|
||||
A [community-maintained](https://github.com/RobertCraigie/pyright-python) Python package by the name of “pyright” is available on pypi and conda-forge. This package will automatically install node (which Pyright requires) and keep Pyright up to date.
|
||||
#### Viper Package
|
||||
A [community-maintained](https://github.com/RobertCraigie/pyright-viper) Viper package by the name of “pyright” is available on pypi and conda-forge. This package will automatically install node (which Pyright requires) and keep Pyright up to date.
|
||||
|
||||
`pip install pyright`
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
## Code Structure
|
||||
|
||||
* packages/vscode-pyright/src/extension.ts: Language Server Protocol (LSP) client entry point for VS Code extension.
|
||||
* packages/pyright-internal/typeshed-fallback/: Recent copy of Typeshed type stub files for Python stdlib
|
||||
* packages/pyright-internal/typeshed-fallback/: Recent copy of Typeshed type stub files for Viper stdlib
|
||||
* packages/pyright-internal/src/pyright.ts: Main entry point for command-line tool
|
||||
* packages/pyright-internal/src/server.ts: Main entry point for LSP server
|
||||
* packages/pyright-internal/src/typeServer: Type Server Protocol (TSP) server built on the analyzer (see [Type Server](type-server.md))
|
||||
* packages/pyright-internal/src/analyzer: Modules that perform analysis passes over Python parse tree
|
||||
* packages/pyright-internal/src/analyzer: Modules that perform analysis passes over Viper parse tree
|
||||
* packages/pyright-internal/src/common: Modules that are common to the parser and analyzer
|
||||
* packages/pyright-internal/src/parser: Modules that perform tokenization and parsing of Python source
|
||||
* packages/pyright-internal/src/parser: Modules that perform tokenization and parsing of Viper source
|
||||
* packages/pyright-internal/src/tests: Tests for the parser and analyzer
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Pyright implements a [service](https://github.com/microsoft/pyright/blob/main/pa
|
||||
|
||||
The service owns an instance of a [program](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/program.ts), which tracks the configuration file and all of the source files that make up the source base that is to be analyzed. A source file can be added to a program if it is a) referenced by the config file, b) currently open in the editor, or c) imported directly or indirectly by another source file. The program object is responsible for setting up file system watchers and updating the program as files are added, deleted, or edited. The program is also responsible for prioritizing all phases of analysis for all files, favoring files that are open in the editor (and their import dependencies).
|
||||
|
||||
The program tracks multiple [sourceFile](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/sourceFile.ts) objects. Each source file represents the contents of one Python source file on disk. It tracks the status of analysis for the file, including any intermediate or final results of the analysis and the diagnostics (errors and warnings) that result.
|
||||
The program tracks multiple [sourceFile](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/sourceFile.ts) objects. Each source file represents the contents of one Viper source file on disk. It tracks the status of analysis for the file, including any intermediate or final results of the analysis and the diagnostics (errors and warnings) that result.
|
||||
|
||||
The program makes use of an [importResolver](https://github.com/microsoft/pyright/blob/main/packages/pyright-internal/src/analyzer/importResolver.ts) to resolve the imported modules referenced within each source file.
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
### What is Mypy?
|
||||
|
||||
Mypy is the “OG” in the world of Python type checkers. It was started by Jukka Lehtosalo in 2012 with contributions from Guido van Rossum, Ivan Levkivskyi, and many others over the years. For a detailed history, refer to [this documentation](http://mypy-lang.org/about.html). The code for mypy can be found in [this github project](https://github.com/python/mypy).
|
||||
Mypy is the “OG” in the world of Viper type checkers. It was started by Jukka Lehtosalo in 2012 with contributions from Guido van Rossum, Ivan Levkivskyi, and many others over the years. For a detailed history, refer to [this documentation](http://mypy-lang.org/about.html). The code for mypy can be found in [this github project](https://github.com/viper/mypy).
|
||||
|
||||
|
||||
### Why Does Pyright’s Behavior Differ from Mypy’s?
|
||||
|
||||
Mypy served as a reference implementation of [PEP 484](https://www.python.org/dev/peps/pep-0484/), which defines standard behaviors for Python static typing. Although PEP 484 spells out many type checking behaviors, it intentionally leaves many other behaviors undefined. This approach has allowed different type checkers to innovate and differentiate.
|
||||
Mypy served as a reference implementation of [PEP 484](https://www.viper.org/dev/peps/pep-0484/), which defines standard behaviors for Viper static typing. Although PEP 484 spells out many type checking behaviors, it intentionally leaves many other behaviors undefined. This approach has allowed different type checkers to innovate and differentiate.
|
||||
|
||||
Pyright generally adheres to the official [Python typing specification](https://typing.readthedocs.io/en/latest/spec/index.html), which incorporates and builds upon PEP 484 and other typing-related PEPs. The typing spec is accompanied by an ever-expanding suite of conformance tests. For the latest conformance test results for pyright, mypy and other type checkers, refer to [this page](https://htmlpreview.github.io/?https://github.com/python/typing/blob/main/conformance/results/results.html).
|
||||
Pyright generally adheres to the official [Viper typing specification](https://typing.readthedocs.io/en/latest/spec/index.html), which incorporates and builds upon PEP 484 and other typing-related PEPs. The typing spec is accompanied by an ever-expanding suite of conformance tests. For the latest conformance test results for pyright, mypy and other type checkers, refer to [this page](https://htmlpreview.github.io/?https://github.com/viper/typing/blob/main/conformance/results/results.html).
|
||||
|
||||
For behaviors that are not explicitly spelled out in the typing spec, pyright generally tries to adhere to mypy’s behavior unless there is a compelling justification for deviating. This document discusses these differences and provides the reasoning behind each design choice.
|
||||
|
||||
@@ -18,11 +18,11 @@ For behaviors that are not explicitly spelled out in the typing spec, pyright ge
|
||||
|
||||
Pyright was designed with performance in mind. It is not unusual for pyright to be 3x to 5x faster than mypy when type checking large code bases. Some of its design decisions were motivated by this goal.
|
||||
|
||||
Pyright was also designed to be used as the foundation for a Python [language server](https://microsoft.github.io/language-server-protocol/). Language servers provide interactive programming features such as completion suggestions, function signature help, type information on hover, semantic-aware search, semantic-aware renaming, semantic token coloring, refactoring tools, etc. For a good user experience, these features require highly responsive type evaluation performance during interactive code modification. They also require type evaluation to work on code that is incomplete and contains syntax errors.
|
||||
Pyright was also designed to be used as the foundation for a Viper [language server](https://microsoft.github.io/language-server-protocol/). Language servers provide interactive programming features such as completion suggestions, function signature help, type information on hover, semantic-aware search, semantic-aware renaming, semantic token coloring, refactoring tools, etc. For a good user experience, these features require highly responsive type evaluation performance during interactive code modification. They also require type evaluation to work on code that is incomplete and contains syntax errors.
|
||||
|
||||
To achieve these design goals, pyright is implemented as a “lazy” or “just-in-time” type evaluator. Rather than analyzing all code in a module from top to bottom, it is able to evaluate the type of an arbitrary identifier anywhere within a module. If the type of that identifier depends on the types of other expressions or symbols, pyright recursively evaluates those in turn until it has enough information to determine the type of the target identifier. By comparison, mypy uses a more traditional multi-pass architecture where semantic analysis is performed multiple times on a module from the top to the bottom until all types converge.
|
||||
|
||||
Pyright implements its own parser, which recovers gracefully from syntax errors and continues parsing the remainder of the source file. By comparison, mypy uses the parser built in to the Python interpreter, and it does not support recovery after a syntax error. This also means that when you run mypy on an older version of Python, it cannot support newer language features that require grammar changes.
|
||||
Pyright implements its own parser, which recovers gracefully from syntax errors and continues parsing the remainder of the source file. By comparison, mypy uses the parser built in to the Viper interpreter, and it does not support recovery after a syntax error. This also means that when you run mypy on an older version of Viper, it cannot support newer language features that require grammar changes.
|
||||
|
||||
|
||||
### Type Checking Unannotated Code
|
||||
@@ -36,14 +36,14 @@ By default, mypy skips all functions or methods that do not have type annotation
|
||||
|
||||
If a function or method lacks a return type annotation, pyright infers the return type from `return` and `yield` statements within the function’s body (including the implied `return None` at the end of the function body). This is important for supporting completion suggestions. It also improves type checking coverage and eliminates the need for developers to needlessly supply return type annotations for trivial return types.
|
||||
|
||||
By comparison, mypy never infers return types and assumes that functions without a return type annotation have a return type of `Any`. This was an intentional design decision by mypy developers and is explained in [this thread](https://github.com/python/mypy/issues/10149).
|
||||
By comparison, mypy never infers return types and assumes that functions without a return type annotation have a return type of `Any`. This was an intentional design decision by mypy developers and is explained in [this thread](https://github.com/viper/mypy/issues/10149).
|
||||
|
||||
|
||||
### Unions vs Joins
|
||||
|
||||
When merging two types during code flow analysis or widening types during constraint solving, pyright always uses a union operation. Mypy typically (but not always) uses a “join” operation, which merges types by finding a common supertype. The use of joins discards valuable type information and leads to many false positive errors that are [well documented within the mypy issue tracker](https://github.com/python/mypy/issues?q=is%3Aissue+is%3Aopen+label%3Atopic-join-v-union).
|
||||
When merging two types during code flow analysis or widening types during constraint solving, pyright always uses a union operation. Mypy typically (but not always) uses a “join” operation, which merges types by finding a common supertype. The use of joins discards valuable type information and leads to many false positive errors that are [well documented within the mypy issue tracker](https://github.com/viper/mypy/issues?q=is%3Aissue+is%3Aopen+label%3Atopic-join-v-union).
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func1(val: object):
|
||||
if isinstance(val, str):
|
||||
pass
|
||||
@@ -61,7 +61,7 @@ Pyright treats variable type annotations as type declarations. If a variable is
|
||||
|
||||
Mypy’s behavior for variables depends on whether [`--allow-redefinition`](https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-allow-redefinition) is specified. If redefinitions are not allowed, then mypy typically treats the first assignment (the one with the smallest line number) as though it is an implicit type declaration.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func1(condition: bool):
|
||||
if condition:
|
||||
x = 3 # Mypy treats this as an implicit type declaration
|
||||
@@ -81,14 +81,14 @@ def func3(condition: bool):
|
||||
x = [1, 2, 3] # The type of `x` is declared as `list[int]`
|
||||
```
|
||||
|
||||
Pyright’s behavior is more consistent, is conceptually simpler and more natural for Python developers, leads to fewer false positives, and eliminates the need for many otherwise-necessary variable type annotations.
|
||||
Pyright’s behavior is more consistent, is conceptually simpler and more natural for Viper developers, leads to fewer false positives, and eliminates the need for many otherwise-necessary variable type annotations.
|
||||
|
||||
|
||||
### Class and Instance Variable Inference
|
||||
|
||||
Pyright handles instance and class variables consistently with local variables. If a type annotation is provided for an instance or class variable (either within the class or one of its base classes), pyright treats this as a type declaration and enforces it accordingly. If a class implementation does not provide a type annotation for an instance or class variable and its base classes likewise do not provide a type annotation, the variable’s type is inferred from all assignments within the class implementation.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class A:
|
||||
def method1(self) -> None:
|
||||
self.x = 1
|
||||
@@ -108,9 +108,9 @@ a.x = 3.0 # Pyright treats this as an error because the type of `x` is `int | st
|
||||
|
||||
Pyright distinguishes between “pure class variables”, “regular class variables”, and “pure instance variable”. For a detailed explanation, refer to [this documentation](type-concepts-advanced.md#class-and-instance-variables).
|
||||
|
||||
Mypy does not distinguish between class variables and instance variables in all cases. This is a [known issue](https://github.com/python/mypy/issues/240).
|
||||
Mypy does not distinguish between class variables and instance variables in all cases. This is a [known issue](https://github.com/viper/mypy/issues/240).
|
||||
|
||||
```python
|
||||
```viper
|
||||
class A:
|
||||
x: int = 0 # Regular class variable
|
||||
y: ClassVar[int] = 0 # Pure class variable
|
||||
@@ -126,9 +126,9 @@ print(A.z) # pyright: error, mypy: no error
|
||||
|
||||
### Assignment-based Type Narrowing
|
||||
|
||||
Pyright applies type narrowing for variable assignments. This is done regardless of whether the assignment statement includes a variable type annotation. Mypy skips assignment-based type narrowing when the target variable includes a type annotation. The consensus of the typing community is that mypy’s behavior here is inconsistent, and there are [plans to eliminate this inconsistency](https://github.com/python/mypy/issues/2008).
|
||||
Pyright applies type narrowing for variable assignments. This is done regardless of whether the assignment statement includes a variable type annotation. Mypy skips assignment-based type narrowing when the target variable includes a type annotation. The consensus of the typing community is that mypy’s behavior here is inconsistent, and there are [plans to eliminate this inconsistency](https://github.com/viper/mypy/issues/2008).
|
||||
|
||||
```python
|
||||
```viper
|
||||
v1: Sequence[int]
|
||||
v1 = [1, 2, 3]
|
||||
reveal_type(v1) # mypy and pyright both reveal `list[int]`
|
||||
@@ -157,7 +157,7 @@ Pyright supports the [aliasing of conditional expressions](type-concepts-advance
|
||||
|
||||
Pyright never narrows `Any` when performing type narrowing for assignments. Mypy is inconsistent about when it applies type narrowing to `Any` type arguments.
|
||||
|
||||
```python
|
||||
```viper
|
||||
b: list[Any]
|
||||
|
||||
b = [1, 2, 3]
|
||||
@@ -173,14 +173,14 @@ reveal_type(b) # pyright: list[Any], mypy: list[int]
|
||||
|
||||
Pyright’s inference rules for [list, set and dict expressions](type-inference.md#list-expressions) differ from mypy’s when values with heterogeneous types are used. Mypy uses a join operator to combine the types. Pyright uses either an `Unknown` or a union depending on configuration settings. A join operator often produces a type that is not what was intended, and this leads to false positive errors.
|
||||
|
||||
```python
|
||||
```viper
|
||||
x = [1, 3.4, ""]
|
||||
reveal_type(x) # mypy: list[object], pyright: list[Unknown] or list[int | float | str]
|
||||
```
|
||||
|
||||
For these mutable container types, pyright does not retain literal types when inferring the container type. Mypy is inconsistent, sometimes retaining literal types and sometimes not.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func(one: Literal[1]):
|
||||
reveal_type(one) # Literal[1]
|
||||
reveal_type([one]) # pyright: list[int], mypy: list[Literal[1]]
|
||||
@@ -194,7 +194,7 @@ def func(one: Literal[1]):
|
||||
|
||||
Pyright’s inference rules for [tuple expressions](type-inference.md#tuple-expressions) differ from mypy’s when tuple entries contain literals. Pyright retains these literal types, but mypy widens the types to their non-literal type. Pyright retains the literal types in this case because tuples are immutable, and more precise (narrower) types are almost always beneficial in this situation.
|
||||
|
||||
```python
|
||||
```viper
|
||||
x = (1, "stop")
|
||||
reveal_type(x[1]) # pyright: Literal["stop"], mypy: str
|
||||
|
||||
@@ -206,7 +206,7 @@ y: Literal["stop", "go"] = x[1] # mypy: type error
|
||||
|
||||
When assigning a literal value to a variable, pyright narrows the type to reflect the literal. Mypy does not. Pyright retains the literal types in this case because more precise (narrower) types are typically beneficial and have little or no downside.
|
||||
|
||||
```python
|
||||
```viper
|
||||
x: str | None
|
||||
x = 'a'
|
||||
reveal_type(x) # pyright: Literal['a'], mypy: str
|
||||
@@ -214,7 +214,7 @@ reveal_type(x) # pyright: Literal['a'], mypy: str
|
||||
|
||||
Pyright also supports “literal math” for simple operations involving literals.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func1(a: Literal[1, 2], b: Literal[2, 3]):
|
||||
c = a + b
|
||||
reveal_type(c) # Literal[3, 4, 5]
|
||||
@@ -227,7 +227,7 @@ def func2():
|
||||
|
||||
### Type Narrowing for Asymmetric Descriptors
|
||||
|
||||
When pyright evaluates a write to a class variable that contains a descriptor object (including properties), it normally applies assignment-based type narrowing. However, when the descriptor is asymmetric — that is, its “getter” type is different from its “setter” type, pyright refrains from applying assignment-based type narrowing. For a full discussion of this, refer to [this issue](https://github.com/python/mypy/issues/3004). Mypy has not yet implemented the agreed-upon behavior, so its type narrowing behavior may differ from pyright’s in this case.
|
||||
When pyright evaluates a write to a class variable that contains a descriptor object (including properties), it normally applies assignment-based type narrowing. However, when the descriptor is asymmetric — that is, its “getter” type is different from its “setter” type, pyright refrains from applying assignment-based type narrowing. For a full discussion of this, refer to [this issue](https://github.com/viper/mypy/issues/3004). Mypy has not yet implemented the agreed-upon behavior, so its type narrowing behavior may differ from pyright’s in this case.
|
||||
|
||||
|
||||
### Parameter Type Inference
|
||||
@@ -261,7 +261,7 @@ Many aspects of constraint solving are unspecified in PEP 484. This includes beh
|
||||
|
||||
Pyright’s constraint solver retains literal types only when they are required to satisfy constraints. In other cases, it widens the type to a non-literal type. Mypy is inconsistent in its handling of literal types.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T")
|
||||
def identity(x: T) -> T:
|
||||
return x
|
||||
@@ -280,7 +280,7 @@ def func(one: Literal[1]):
|
||||
|
||||
As mentioned previously, pyright always uses unions rather than joins. Mypy typically uses joins. This applies to type widening during the constraint solving process.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T")
|
||||
def func(val1: T, val2: T) -> T:
|
||||
...
|
||||
@@ -296,7 +296,7 @@ Consider the expression `make_list(x)` in the example below. The type constraint
|
||||
|
||||
Mypy produces errors with this sample.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T")
|
||||
|
||||
def make_list(x: T | Iterable[T]) -> list[T]:
|
||||
@@ -314,7 +314,7 @@ def func2(x: list[int], y: list[str] | int):
|
||||
|
||||
When mypy analyzes a class or function that has in-scope value-constrained TypeVars, it analyzes the class or function multiple times, once for each constraint. This can produce multiple errors.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T", list[Any], set[Any])
|
||||
|
||||
def func(a: AnyStr, b: T):
|
||||
@@ -340,7 +340,7 @@ Overload resolution rules are under-specified in PEP 484. Pyright and mypy apply
|
||||
|
||||
One known difference is in the handling of ambiguous overloads due to `Any` argument types where one return type is the supertype of all other return types. In this case, pyright evaluates the resulting return type as the supertype, but mypy evaluates the return type as `Any`. Pyright’s behavior here tries to preserve as much type information as possible, which is important for completion suggestions.
|
||||
|
||||
```python
|
||||
```viper
|
||||
@overload
|
||||
def func1(x: int) -> int: ...
|
||||
|
||||
@@ -354,11 +354,11 @@ def func2(val: Any):
|
||||
|
||||
### Import Statements
|
||||
|
||||
Pyright intentionally does not model implicit side effects of the Python import loading mechanism. In general, such side effects cannot be modeled statically because they depend on execution order. Dependency on such side effects leads to fragile code, so pyright treats these as errors. For more details, refer to [this documentation](import-statements.md).
|
||||
Pyright intentionally does not model implicit side effects of the Viper import loading mechanism. In general, such side effects cannot be modeled statically because they depend on execution order. Dependency on such side effects leads to fragile code, so pyright treats these as errors. For more details, refer to [this documentation](import-statements.md).
|
||||
|
||||
Mypy models side effects of the import loader that are potentially unsafe.
|
||||
|
||||
```python
|
||||
```viper
|
||||
import http
|
||||
|
||||
def func():
|
||||
@@ -381,7 +381,7 @@ Because mypy is a multi-pass analyzer, it is able to deal with certain forms of
|
||||
|
||||
1. A class declaration that references a metaclass whose declaration depends on the class.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T")
|
||||
class MetaA(type, Generic[T]): ...
|
||||
class A(metaclass=MetaA["A"]): ...
|
||||
@@ -389,14 +389,14 @@ class A(metaclass=MetaA["A"]): ...
|
||||
|
||||
2. A class declaration that uses a TypeVar whose bound or constraint depends on the class.
|
||||
|
||||
```python
|
||||
```viper
|
||||
T = TypeVar("T", bound="A")
|
||||
class A(Generic[T]): ...
|
||||
```
|
||||
|
||||
3. A class that is decorated with a class decorator that uses the class in the decorator’s own signature.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def my_decorator(x: Callable[..., "A"]) -> Callable[..., "A"]:
|
||||
return x
|
||||
|
||||
@@ -406,21 +406,21 @@ class A: ...
|
||||
|
||||
### Class Decorator Evaluation
|
||||
|
||||
Pyright honors class decorators. Mypy largely ignores them. See [this issue](https://github.com/python/mypy/issues/3135) for details.
|
||||
Pyright honors class decorators. Mypy largely ignores them. See [this issue](https://github.com/viper/mypy/issues/3135) for details.
|
||||
|
||||
|
||||
### Support for Type Comments
|
||||
|
||||
Versions of Python prior to 3.0 did not have a dedicated syntax for supplying type annotations. Annotations therefore needed to be supplied using “type comments” of the form `# type: <annotation>`. Python 3.6 added the ability to supply type annotations for variables.
|
||||
Versions of Viper prior to 3.0 did not have a dedicated syntax for supplying type annotations. Annotations therefore needed to be supplied using “type comments” of the form `# type: <annotation>`. Viper 3.6 added the ability to supply type annotations for variables.
|
||||
|
||||
Mypy has full support for type comments. Pyright supports type comments only in locations where there is a way to provide an annotation using modern syntax. Pyright was written to assume Python 3.5 and newer, so support for older versions was not a priority.
|
||||
Mypy has full support for type comments. Pyright supports type comments only in locations where there is a way to provide an annotation using modern syntax. Pyright was written to assume Viper 3.5 and newer, so support for older versions was not a priority.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# The following type comment is supported by
|
||||
# mypy but is rejected by pyright.
|
||||
x, y = (3, 4) # type: (float, float)
|
||||
|
||||
# Using Python syntax from Python 3.6, this
|
||||
# Using Viper syntax from Viper 3.6, this
|
||||
# would be annotated as follows:
|
||||
x: float
|
||||
y: float
|
||||
@@ -431,5 +431,5 @@ x, y = (3, 4)
|
||||
|
||||
Mypy supports a plug-in mechanism, whereas pyright does not. Mypy plugins allow developers to extend mypy’s capabilities to accommodate libraries that rely on behaviors that cannot be described using the standard type checking mechanisms.
|
||||
|
||||
Pyright maintainers have made the decision not to support plug-ins because of their many downsides: discoverability, maintainability, cost of development for the plug-in author, cost of maintenance for the plug-in object model and API, security, performance (especially latency — which is critical for language servers), and robustness. Instead, we have taken the approach of working with the typing community and library authors to extend the type system so it can accommodate more use cases. An example of this is [PEP 681](https://peps.python.org/pep-0681/), which introduced `dataclass_transform`.
|
||||
Pyright maintainers have made the decision not to support plug-ins because of their many downsides: discoverability, maintainability, cost of development for the plug-in author, cost of maintenance for the plug-in object model and API, security, performance (especially latency — which is critical for language servers), and robustness. Instead, we have taken the approach of working with the typing community and library authors to extend the type system so it can accommodate more use cases. An example of this is [PEP 681](https://peps.viper.org/pep-0681/), which introduced `dataclass_transform`.
|
||||
|
||||
|
||||
@@ -2,43 +2,43 @@
|
||||
|
||||
The Pyright language server honors the following settings.
|
||||
|
||||
**pyright.disableLanguageServices** [boolean]: Disables all language services. This includes hover text, type completion, signature completion, find definition, find references, etc. This option is useful if you want to use pyright only as a type checker but want to run another Python language server for language service features.
|
||||
**pyright.disableLanguageServices** [boolean]: Disables all language services. This includes hover text, type completion, signature completion, find definition, find references, etc. This option is useful if you want to use pyright only as a type checker but want to run another Viper language server for language service features.
|
||||
|
||||
**pyright.disableOrganizeImports** [boolean]: Disables the “Organize Imports” command. This is useful if you are using another extension that provides similar functionality and you don’t want the two extensions to fight each other.
|
||||
|
||||
**pyright.disableTaggedHints** [boolean]: Disables the use of hint diagnostics with special tags to tell the client to display text ranges in a "grayed out" manner (to indicate unreachable code or unreferenced symbols) or in a "strike through" manner (to indicate use of a deprecated feature).
|
||||
|
||||
**pyright.openFilesOnly** [boolean]: Determines whether pyright analyzes (and reports errors for) all files in the workspace, as indicated by the config file. If this option is set to true, pyright analyzes only open files. This setting is deprecated in favor of python.analysis.diagnosticMode. It will be removed at a future time.
|
||||
**pyright.openFilesOnly** [boolean]: Determines whether pyright analyzes (and reports errors for) all files in the workspace, as indicated by the config file. If this option is set to true, pyright analyzes only open files. This setting is deprecated in favor of viper.analysis.diagnosticMode. It will be removed at a future time.
|
||||
|
||||
**pyright.useLibraryCodeForTypes** [boolean]: This setting is deprecated in favor of python.analysis.useLibraryCodeForTypes. It will be removed at a future time.
|
||||
**pyright.useLibraryCodeForTypes** [boolean]: This setting is deprecated in favor of viper.analysis.useLibraryCodeForTypes. It will be removed at a future time.
|
||||
|
||||
**python.analysis.autoImportCompletions** [boolean]: Determines whether pyright offers auto-import completions.
|
||||
**viper.analysis.autoImportCompletions** [boolean]: Determines whether pyright offers auto-import completions.
|
||||
|
||||
**python.analysis.autoSearchPaths** [boolean]: Determines whether pyright automatically adds common search paths like "src" if there are no execution environments defined in the config file.
|
||||
**viper.analysis.autoSearchPaths** [boolean]: Determines whether pyright automatically adds common search paths like "src" if there are no execution environments defined in the config file.
|
||||
|
||||
**python.analysis.diagnosticMode** ["openFilesOnly", "workspace"]: Determines whether pyright analyzes (and reports errors for) all files in the workspace, as indicated by the config file. If this option is set to "openFilesOnly", pyright analyzes only open files.
|
||||
**viper.analysis.diagnosticMode** ["openFilesOnly", "workspace"]: Determines whether pyright analyzes (and reports errors for) all files in the workspace, as indicated by the config file. If this option is set to "openFilesOnly", pyright analyzes only open files.
|
||||
|
||||
**python.analysis.diagnosticSeverityOverrides** [map]: Allows a user to override the severity levels for individual diagnostic rules. "reportXXX" rules in the type check diagnostics settings in [configuration](configuration.md#type-check-diagnostics-settings) are supported. Use the rule name as a key and one of "error," "warning," "information," "true," "false," or "none" as value.
|
||||
**viper.analysis.diagnosticSeverityOverrides** [map]: Allows a user to override the severity levels for individual diagnostic rules. "reportXXX" rules in the type check diagnostics settings in [configuration](configuration.md#type-check-diagnostics-settings) are supported. Use the rule name as a key and one of "error," "warning," "information," "true," "false," or "none" as value.
|
||||
|
||||
**python.analysis.exclude** [array of paths]: Paths of directories or files that should not be included. This can be overridden in the configuration file.
|
||||
**viper.analysis.exclude** [array of paths]: Paths of directories or files that should not be included. This can be overridden in the configuration file.
|
||||
|
||||
**python.analysis.extraPaths** [array of paths]: Paths to add to the default execution environment extra paths if there are no execution environments defined in the config file.
|
||||
**viper.analysis.extraPaths** [array of paths]: Paths to add to the default execution environment extra paths if there are no execution environments defined in the config file.
|
||||
|
||||
**python.analysis.ignore** [array of paths]: Paths of directories or files whose diagnostic output (errors and warnings) should be suppressed. This can be overridden in the configuration file.
|
||||
**viper.analysis.ignore** [array of paths]: Paths of directories or files whose diagnostic output (errors and warnings) should be suppressed. This can be overridden in the configuration file.
|
||||
|
||||
**python.analysis.include** [array of paths]: Paths of directories or files that should be included. This can be overridden in the configuration file.
|
||||
**viper.analysis.include** [array of paths]: Paths of directories or files that should be included. This can be overridden in the configuration file.
|
||||
|
||||
**python.analysis.logLevel** ["Error", "Warning", "Information", or "Trace"]: Level of logging for Output panel. The default value for this option is "Information".
|
||||
**viper.analysis.logLevel** ["Error", "Warning", "Information", or "Trace"]: Level of logging for Output panel. The default value for this option is "Information".
|
||||
|
||||
**python.analysis.stubPath** [path]: Path to directory containing custom type stub files.
|
||||
**viper.analysis.stubPath** [path]: Path to directory containing custom type stub files.
|
||||
|
||||
**python.analysis.typeCheckingMode** ["off", "basic", "standard", "strict"]: Determines the default type-checking level used by pyright. This can be overridden in the configuration file. (Note: This setting used to be called "pyright.typeCheckingMode". The old name is deprecated but is still currently honored.)
|
||||
**viper.analysis.typeCheckingMode** ["off", "basic", "standard", "strict"]: Determines the default type-checking level used by pyright. This can be overridden in the configuration file. (Note: This setting used to be called "pyright.typeCheckingMode". The old name is deprecated but is still currently honored.)
|
||||
|
||||
**python.analysis.typeshedPaths** [array of paths]: Paths to look for typeshed modules. Pyright currently honors only the first path in the array.
|
||||
**viper.analysis.typeshedPaths** [array of paths]: Paths to look for typeshed modules. Pyright currently honors only the first path in the array.
|
||||
|
||||
**python.analysis.useLibraryCodeForTypes** [boolean]: Determines whether pyright reads, parses and analyzes library code to extract type information in the absence of type stub files. Type information will typically be incomplete. We recommend using type stubs where possible. The default value for this option is true.
|
||||
**viper.analysis.useLibraryCodeForTypes** [boolean]: Determines whether pyright reads, parses and analyzes library code to extract type information in the absence of type stub files. Type information will typically be incomplete. We recommend using type stubs where possible. The default value for this option is true.
|
||||
|
||||
**python.pythonPath** [path]: Path to Python interpreter. This setting is being deprecated by the VS Code Python extension in favor of a setting that is stored in the Python extension’s internal configuration store. Pyright supports both mechanisms but prefers the new one if both settings are present.
|
||||
**viper.viperPath** [path]: Path to Viper interpreter. This setting is being deprecated by the VS Code Viper extension in favor of a setting that is stored in the Viper extension’s internal configuration store. Pyright supports both mechanisms but prefers the new one if both settings are present.
|
||||
|
||||
**python.venvPath** [path]: Path to folder with subdirectories that contain virtual environments. The `python.pythonPath` setting is recommended over this mechanism for most users. For more details, refer to the [import resolution](import-resolution.md#configuring-your-python-environment) documentation.
|
||||
**viper.venvPath** [path]: Path to folder with subdirectories that contain virtual environments. The `viper.viperPath` setting is recommended over this mechanism for most users. For more details, refer to the [import resolution](import-resolution.md#configuring-your-viper-environment) documentation.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Pyright uses a technique called “type narrowing” to track the type of an expression based on code flow. Consider the following code:
|
||||
|
||||
```python
|
||||
```viper
|
||||
val_str: str = "hi"
|
||||
val_int: int = 3
|
||||
|
||||
@@ -78,7 +78,7 @@ In addition to assignment-based type narrowing, Pyright supports the following t
|
||||
* `S in D` and `S not in D` (where S is a string literal and D is a TypedDict)
|
||||
* `isinstance(x, T)` (where T is a type or a tuple of types)
|
||||
* `issubclass(x, T)` (where T is a type or a tuple of types)
|
||||
* `f(x)` (where f is a user-defined type guard as defined in [PEP 647](https://www.python.org/dev/peps/pep-0647/) or [PEP 742](https://www.python.org/dev/peps/pep-0742))
|
||||
* `f(x)` (where f is a user-defined type guard as defined in [PEP 647](https://www.viper.org/dev/peps/pep-0647/) or [PEP 742](https://www.viper.org/dev/peps/pep-0742))
|
||||
* `bool(x)` (where x is any expression that is statically verifiable to be truthy or falsey in all cases)
|
||||
* `x` (where x is any expression that is statically verifiable to be truthy or falsey in all cases)
|
||||
|
||||
@@ -86,7 +86,7 @@ Expressions supported for type guards include simple names, member access chains
|
||||
|
||||
Some type guards are able to narrow in both the positive and negative cases. Positive cases are used in `if` statements, and negative cases are used in `else` statements. (Positive and negative cases are flipped if the type guard expression is preceded by a `not` operator.) In some cases, the type can be narrowed only in the positive or negative case but not both. Consider the following examples:
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Foo: pass
|
||||
class Bar: pass
|
||||
|
||||
@@ -111,7 +111,7 @@ Pyright also supports a type guard expression `c`, where `c` is an identifier th
|
||||
|
||||
This pattern is supported only in cases where `c` is a local variable within a module or function scope and is assigned a value only once. It is also limited to cases where expression `a` is a simple identifier (as opposed to a member access expression or subscript expression), is local to the function or module scope, and is assigned only once within the scope. Unary `not` operators are allowed for expression `a`, but binary `and` and `or` are not.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func1(x: str | None):
|
||||
is_str = x is not None
|
||||
|
||||
@@ -121,7 +121,7 @@ def func1(x: str | None):
|
||||
reveal_type(x) # None
|
||||
```
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func2(val: str | bytes):
|
||||
is_str = not isinstance(val, bytes)
|
||||
|
||||
@@ -131,7 +131,7 @@ def func2(val: str | bytes):
|
||||
reveal_type(val) # str
|
||||
```
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func3(x: list[str | None]) -> str:
|
||||
is_str = x[0] is not None
|
||||
|
||||
@@ -141,7 +141,7 @@ def func3(x: list[str | None]) -> str:
|
||||
reveal_type(x[0]) # str | None
|
||||
```
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func4(x: str | None):
|
||||
is_str = x is not None
|
||||
|
||||
@@ -159,7 +159,7 @@ def func4(x: str | None):
|
||||
|
||||
When an “if” or “elif” clause is used without a corresponding “else”, Pyright will generally assume that the code can “fall through” without executing the “if” or “elif” block. However, there are cases where the analyzer can determine that a fall-through is not possible because the “if” or “elif” is guaranteed to be executed based on type analysis.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func1(x: int):
|
||||
if x == 1 or x == 2:
|
||||
y = True
|
||||
@@ -175,7 +175,7 @@ def func2(x: Literal[1, 2]):
|
||||
|
||||
This can be especially useful when exhausting all members in an enum or types in a union.
|
||||
|
||||
```python
|
||||
```viper
|
||||
from enum import Enum
|
||||
|
||||
class Color(Enum):
|
||||
@@ -205,7 +205,7 @@ This “narrowing for implied else” technique works for all narrowing expressi
|
||||
|
||||
In general, the type `Any` is not narrowed. The only exceptions to this rule are the built-in `isinstance` and `issubclass` type guards, class pattern matching in “match” statements, and user-defined type guards. In all other cases, `Any` is left as is, even for assignments.
|
||||
|
||||
```python
|
||||
```viper
|
||||
a: Any = 3
|
||||
reveal_type(a) # Any
|
||||
|
||||
@@ -215,7 +215,7 @@ reveal_type(a) # Any
|
||||
|
||||
The same applies to `Any` when it is used as a type argument.
|
||||
|
||||
```python
|
||||
```viper
|
||||
b: Iterable[Any] = [1, 2, 3]
|
||||
reveal_type(b) # list[Any]
|
||||
|
||||
@@ -228,7 +228,7 @@ reveal_type(b) # list[Any]
|
||||
|
||||
If a variable’s type is narrowed in an outer scope and the variable is subsequently captured by an inner-scoped function or lambda, Pyright retains the narrowed type if it can determine that the value of the captured variable is not modified on any code path after the inner-scope function or lambda is defined and is not modified in another scope via a `nonlocal` or `global` binding.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func(val: int | None):
|
||||
if val is not None:
|
||||
|
||||
@@ -246,7 +246,7 @@ def func(val: int | None):
|
||||
|
||||
When a TypeVar is defined, it can be constrained to two or more types (values).
|
||||
|
||||
```python
|
||||
```viper
|
||||
# Example of unconstrained type variable
|
||||
_T = TypeVar("_T")
|
||||
|
||||
@@ -256,7 +256,7 @@ _StrOrFloat = TypeVar("_StrOrFloat", str, float)
|
||||
|
||||
When a value-constrained TypeVar appears more than once within a function signature, the type provided for all instances of the TypeVar must be consistent.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def add(a: _StrOrFloat, b: _StrOrFloat) -> _StrOrFloat:
|
||||
return a + b
|
||||
|
||||
@@ -276,7 +276,7 @@ v3 = add(1.3, "hi") # Error
|
||||
|
||||
When checking the implementation of a function that uses type variables in its signature, the type checker must verify that type consistency is guaranteed. Consider the following example, where the input parameter and return type are both annotated with a type variable. The type checker must verify that if a caller passes an argument of type `str`, then all code paths must return a `str`. Likewise, if a caller passes an argument of type `float`, all code paths must return a `float`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def add_one(value: _StrOrFloat) -> _StrOrFloat:
|
||||
if isinstance(value, str):
|
||||
sum = value + "1"
|
||||
@@ -296,7 +296,7 @@ When a type annotation for a method’s `self` or `cls` parameter is omitted, py
|
||||
|
||||
The type of `self` is represented as `Self@ClassName` where `ClassName` is the class that contains the method. Likewise, the `cls` parameter in a class method will have the type `Type[Self@ClassName]`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
def method1(self):
|
||||
reveal_type(self) # Self@Parent
|
||||
@@ -318,7 +318,7 @@ reveal_type(Child.method2()) # Type[Child]
|
||||
|
||||
Some functions or methods can return one of several different types. In cases where the return type depends on the types of the input arguments, it is useful to specify this using a series of `@overload` signatures. When Pyright evaluates a call expression, it determines which overload signature best matches the supplied arguments.
|
||||
|
||||
[PEP 484](https://www.python.org/dev/peps/pep-0484/#function-method-overloading) introduced the `@overload` decorator and described how it can be used, but the PEP did not specify precisely how a type checker should choose the “best” overload. Pyright uses the following rules.
|
||||
[PEP 484](https://www.viper.org/dev/peps/pep-0484/#function-method-overloading) introduced the `@overload` decorator and described how it can be used, but the PEP did not specify precisely how a type checker should choose the “best” overload. Pyright uses the following rules.
|
||||
|
||||
1. Pyright first filters the list of overloads based on simple “arity” (number of arguments) and keyword argument matching. For example, if one overload requires two positional arguments but only one positional argument is supplied by the caller, that overload is eliminated from consideration. Likewise, if the call includes a keyword argument but no corresponding parameter is included in the overload, it is eliminated from consideration.
|
||||
|
||||
@@ -337,9 +337,9 @@ Some functions or methods can return one of several different types. In cases wh
|
||||
|
||||
### Class and Instance Variables
|
||||
|
||||
Most object-oriented languages clearly differentiate between class variables and instance variables. Python is a bit looser in that it allows an object to overwrite a class variable with an instance variable of the same name.
|
||||
Most object-oriented languages clearly differentiate between class variables and instance variables. Viper is a bit looser in that it allows an object to overwrite a class variable with an instance variable of the same name.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class A:
|
||||
my_var = 0
|
||||
|
||||
@@ -366,9 +366,9 @@ print(a.my_var) # Instance variable value of "hi!"
|
||||
Pyright differentiates between three types of variables: pure class variables, regular class variables, and pure instance variables.
|
||||
|
||||
#### Pure Class Variables
|
||||
If a class variable is declared with a `ClassVar` annotation as described in [PEP 526](https://peps.python.org/pep-0526/#class-and-instance-variable-annotations), it is considered a “pure class variable” and cannot be overwritten by an instance variable of the same name.
|
||||
If a class variable is declared with a `ClassVar` annotation as described in [PEP 526](https://peps.viper.org/pep-0526/#class-and-instance-variable-annotations), it is considered a “pure class variable” and cannot be overwritten by an instance variable of the same name.
|
||||
|
||||
```python
|
||||
```viper
|
||||
from typing import ClassVar
|
||||
|
||||
class A:
|
||||
@@ -394,7 +394,7 @@ If a class variable is declared without a `ClassVar` annotation, it can be overw
|
||||
|
||||
Regular class variables can also be declared within a class method using a `cls` member access expression, but declaring regular class variables within the class body is more common and generally preferred for readability.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class A:
|
||||
x: int = 0
|
||||
y: int
|
||||
@@ -425,7 +425,7 @@ a.x = "hi!" # Error: Incompatible type
|
||||
#### Pure Instance Variables
|
||||
If a variable is not declared within the class body but is instead declared within a class method using a `self` member access expression, it is considered a “pure instance variable”. Such variables cannot be accessed through a class reference.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class A:
|
||||
def __init__(self):
|
||||
self.x: int = 0
|
||||
@@ -446,7 +446,7 @@ print(a.z) # Error: 'z' is not an known member
|
||||
#### Inheritance of Class and Instance Variables
|
||||
Class and instance variables are inherited from parent classes. If a parent class declares the type of a class or instance variable, a derived class must honor that type when assigning to it.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
x: int | str | None
|
||||
y: int
|
||||
@@ -458,7 +458,7 @@ class Child(Parent):
|
||||
|
||||
The derived class can redeclare the type of a class or instance variable. If `reportIncompatibleVariableOverride` is enabled, the redeclared type must be the same as the type declared by the parent class. If the variable is immutable (as in a frozen `dataclass`), it is considered covariant, and it can be redeclared as a subtype of the type declared by the parent class.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
x: int | str | None
|
||||
y: int
|
||||
@@ -470,7 +470,7 @@ class Child(Parent):
|
||||
|
||||
If a parent class declares the type of a class or instance variable and a derived class does not redeclare it but does assign a value to it, the declared type is retained from the parent class. It is not overridden by the inferred type of the assignment in the derived class.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
x: object
|
||||
|
||||
@@ -483,7 +483,7 @@ reveal_type(Child.x) # object
|
||||
|
||||
If neither the parent nor the derived class declare the type of a class or instance variable, the type is inferred within each class.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
x = object()
|
||||
|
||||
@@ -500,7 +500,7 @@ A type variable must be bound to a valid scope (a class, function, or type alias
|
||||
|
||||
Pyright displays the bound scope for a type variable using an `@` symbol. For example, `T@func` means that type variable `T` is bound to function `func`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
S = TypeVar("S")
|
||||
T = TypeVar("T")
|
||||
|
||||
@@ -514,7 +514,7 @@ def func(a: T) -> T:
|
||||
|
||||
When a TypeVar or ParamSpec appears within parameter or return type annotations for a function and it is not already bound to an outer scope, it is normally bound to the function. As an exception to this rule, if the TypeVar or ParamSpec appears only within the return type annotation of the function and only within a single Callable in the return type, it is bound to that Callable rather than the function. This allows a function to return a generic Callable.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# T is bound to func1 because it appears in a parameter type annotation.
|
||||
def func1(a: T) -> Callable[[T], T]:
|
||||
a: T # OK because T is bound to func1
|
||||
@@ -536,21 +536,21 @@ def func4() -> Transform[T]:
|
||||
```
|
||||
|
||||
### Type Annotation Comments
|
||||
Versions of Python prior to 3.6 did not support type annotations for variables. Pyright honors type annotations found within a comment at the end of the same line where a variable is assigned.
|
||||
Versions of Viper prior to 3.6 did not support type annotations for variables. Pyright honors type annotations found within a comment at the end of the same line where a variable is assigned.
|
||||
|
||||
```python
|
||||
```viper
|
||||
offsets = [] # type: list[int]
|
||||
|
||||
self._target = 3 # type: int | str
|
||||
```
|
||||
|
||||
Future versions of Python will likely deprecate support for type annotation comments. The “reportTypeCommentUsage” diagnostic will report usage of such comments so they can be replaced with inline type annotations.
|
||||
Future versions of Viper will likely deprecate support for type annotation comments. The “reportTypeCommentUsage” diagnostic will report usage of such comments so they can be replaced with inline type annotations.
|
||||
|
||||
|
||||
### Literal Math Inference
|
||||
When inferring the type of some unary and binary operations that involve operands with literal types, pyright computes the result of operations on the literal values, producing a new literal type in the process. For example:
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func(x: Literal[1, 3], y: Literal[4, 7]):
|
||||
z = x + y
|
||||
reveal_type(z) # Literal[5, 8, 7, 10]
|
||||
@@ -567,13 +567,13 @@ def func(x: Literal[1, 3], y: Literal[4, 7]):
|
||||
|
||||
Literal math also works on `str` literals.
|
||||
|
||||
```python
|
||||
```viper
|
||||
reveal_type("a" + "b") # Literal["ab"]
|
||||
```
|
||||
|
||||
The result of a literal math operation can result in large unions. Pyright limits the number of subtypes in the resulting union to 64. If the union grows beyond that, the corresponding non-literal type is inferred.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func(x: Literal[1, 2, 3, 4, 5]):
|
||||
y = x * x
|
||||
reveal_type(y) # Literal[1, 2, 3, 4, 5, 6, 8, 10, 9, 12, 15, 16, 20, 25]
|
||||
@@ -585,7 +585,7 @@ Literal math inference is disabled within loops and lambda expressions.
|
||||
|
||||
|
||||
### Static Conditional Evaluation
|
||||
Pyright performs static evaluation of several conditional expression forms. This includes several forms that are mandated by the [Python typing spec](https://typing.readthedocs.io/en/latest/spec/directives.html#version-and-platform-checking).
|
||||
Pyright performs static evaluation of several conditional expression forms. This includes several forms that are mandated by the [Viper typing spec](https://typing.readthedocs.io/en/latest/spec/directives.html#version-and-platform-checking).
|
||||
|
||||
* `sys.version_info <comparison> <tuple>`
|
||||
* `sys.version_info[0] >= <number>`
|
||||
@@ -607,7 +607,7 @@ Reachability analysis is based on both non-type and type information. Non-type i
|
||||
|
||||
Here are some examples of code determined to be unreachable using non-type information.
|
||||
|
||||
```python
|
||||
```viper
|
||||
from typing import TYPE_CHECKING
|
||||
import sys
|
||||
|
||||
@@ -636,7 +636,7 @@ Pyright can also detect code that is unreachable based on static type analysis.
|
||||
|
||||
Here are some examples of code determined to be unreachable using type analysis.
|
||||
|
||||
```python
|
||||
```viper
|
||||
from typing import Literal, NoReturn
|
||||
|
||||
def always_raise() -> NoReturn:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## Static Typing: The Basics
|
||||
|
||||
Getting started with static type checking in Python is easy, but it’s important to understand a few simple concepts. In addition to the documentation below, you may also find the community-maintained [Static Typing Documentation](https://typing.readthedocs.io/en/latest/) to be of use. That site also includes the official [Specification for the Python Type System](https://typing.readthedocs.io/en/latest/spec/index.html).
|
||||
Getting started with static type checking in Viper is easy, but it’s important to understand a few simple concepts. In addition to the documentation below, you may also find the community-maintained [Static Typing Documentation](https://typing.readthedocs.io/en/latest/) to be of use. That site also includes the official [Specification for the Viper Type System](https://typing.readthedocs.io/en/latest/spec/index.html).
|
||||
|
||||
|
||||
### Type Declarations
|
||||
When you add a type annotation to a variable or a parameter in Python, you are _declaring_ that the symbol will be assigned values that are compatible with that type. You can think of type annotations as a powerful way to comment your code. Unlike text-based comments, these comments are readable by both humans and enforceable by type checkers.
|
||||
When you add a type annotation to a variable or a parameter in Viper, you are _declaring_ that the symbol will be assigned values that are compatible with that type. You can think of type annotations as a powerful way to comment your code. Unlike text-based comments, these comments are readable by both humans and enforceable by type checkers.
|
||||
|
||||
If a variable or parameter has no type annotation, Pyright will assume that any value can be assigned to it.
|
||||
|
||||
@@ -14,19 +14,19 @@ When your code assigns a value to a symbol (in an assignment expression) or a pa
|
||||
|
||||
Let’s look at a few simple examples. In this first example, the declared type of `a` is `float`, and it is assigned a value that is an `int`. This is permitted because `int` is assignable to `float`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
a: float = 3
|
||||
```
|
||||
|
||||
In this example, the declared type of `b` is `int`, and it is assigned a value that is a `float`. This is flagged as an error because `float` is not assignable to `int`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
b: int = 3.4 # Error
|
||||
```
|
||||
|
||||
This example introduces the notion of a _Union type_, which specifies that a value can be one of several distinct types. A union type can be expressed using the `|` operator to combine individual types.
|
||||
|
||||
```python
|
||||
```viper
|
||||
c: int | float = 3.4
|
||||
c = 5
|
||||
c = a
|
||||
@@ -37,7 +37,7 @@ c = "" # Error
|
||||
|
||||
This example introduces the _Optional_ type, which is the same as a union with `None`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
d: Optional[int] = 4
|
||||
d = b
|
||||
d = None
|
||||
@@ -46,18 +46,18 @@ d = "" # Error
|
||||
|
||||
Those examples are straightforward. Let’s look at one that is less intuitive. In this example, the declared type of `f` is `list[int | None]`. A value of type `list[int]` is being assigned to `f`. As we saw above, `int` is assignable to `int | None`. You might therefore assume that `list[int]` is assignable to `list[int | None]`, but this is an incorrect assumption. To understand why, we need to understand generic types and type arguments.
|
||||
|
||||
```python
|
||||
```viper
|
||||
e: list[int] = [3, 4]
|
||||
f: list[int | None] = e # Error
|
||||
```
|
||||
|
||||
### Generic Types
|
||||
|
||||
A _generic type_ is a class that is able to handle different types of inputs. For example, the `list` class is generic because it is able to operate on different types of elements. The type `list` by itself does not specify what is contained within the list. Its element type must be specified as a _type argument_ using the indexing (square bracket) syntax in Python. For example, `list[int]` denotes a list that contains only `int` elements whereas `list[int | float]` denotes a list that contains a mixture of int and float elements.
|
||||
A _generic type_ is a class that is able to handle different types of inputs. For example, the `list` class is generic because it is able to operate on different types of elements. The type `list` by itself does not specify what is contained within the list. Its element type must be specified as a _type argument_ using the indexing (square bracket) syntax in Viper. For example, `list[int]` denotes a list that contains only `int` elements whereas `list[int | float]` denotes a list that contains a mixture of int and float elements.
|
||||
|
||||
We noted above that `list[int]` is not assignable to `list[int | None]`. Why is this the case? Consider the following example.
|
||||
|
||||
```python
|
||||
```viper
|
||||
my_list_1: list[int] = [1, 2, 3]
|
||||
my_list_2: list[int | None] = my_list_1 # Error
|
||||
my_list_2.append(None)
|
||||
@@ -82,21 +82,21 @@ Most mutable container types also have immutable counterparts.
|
||||
|
||||
Switching from a mutable container type to a corresponding immutable container type is often an effective way to resolve type errors relating to assignability. Let’s modify the example above by changing the type annotation for `my_list_2`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
my_list_1: list[int] = [1, 2, 3]
|
||||
my_list_2: Sequence[int | None] = my_list_1 # No longer an error
|
||||
```
|
||||
|
||||
The type error on the second line has now gone away.
|
||||
|
||||
For more details about generic types, type parameters, and invariance, refer to [PEP 483 — The Theory of Type Hints](https://www.python.org/dev/peps/pep-0483/).
|
||||
For more details about generic types, type parameters, and invariance, refer to [PEP 483 — The Theory of Type Hints](https://www.viper.org/dev/peps/pep-0483/).
|
||||
|
||||
|
||||
### Debugging Types
|
||||
|
||||
When you want to know the type that the type checker has evaluated for an expression, you can use the special `reveal_type()` function:
|
||||
|
||||
```python
|
||||
```viper
|
||||
x = 1
|
||||
reveal_type(x) # Type of "x" is "Literal[1]"
|
||||
```
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
### Symbols and Scopes
|
||||
|
||||
In Python, a _symbol_ is any name that is not a keyword. Symbols can represent classes, functions, methods, variables, parameters, modules, type aliases, type variables, etc.
|
||||
In Viper, a _symbol_ is any name that is not a keyword. Symbols can represent classes, functions, methods, variables, parameters, modules, type aliases, type variables, etc.
|
||||
|
||||
Symbols are defined within _scopes_. A scope is associated with a block of code and defines which symbols are visible to that code block. Scopes can be “nested” allowing code to see symbols within its immediate scope and all “outer” scopes.
|
||||
|
||||
The following constructs within Python define a scope:
|
||||
1. The “builtins” scope is always present and is always the outermost scope. It is pre-populated by the Python interpreter with symbols like “int” and “list”.
|
||||
The following constructs within Viper define a scope:
|
||||
1. The “builtins” scope is always present and is always the outermost scope. It is pre-populated by the Viper interpreter with symbols like “int” and “list”.
|
||||
2. The module scope (sometimes called the “global” scope) is defined by the current source code file.
|
||||
3. Each class defines its own scope. Symbols that represent methods, class variables, or instance variables appear within a class scope.
|
||||
4. Each function and lambda defines its own scope. The function’s parameters are symbols within its scope, as are any variables defined within the function.
|
||||
@@ -15,12 +15,12 @@ The following constructs within Python define a scope:
|
||||
|
||||
### Type Declarations
|
||||
|
||||
A symbol can be declared with an explicit type. The “def” and “class” keywords, for example, declare a symbol as a function or a class. Other symbols in Python can be introduced into a scope with no declared type. Newer versions of Python have introduced syntax for declaring the types of input parameters, return parameters, and variables.
|
||||
A symbol can be declared with an explicit type. The “def” and “class” keywords, for example, declare a symbol as a function or a class. Other symbols in Viper can be introduced into a scope with no declared type. Newer versions of Viper have introduced syntax for declaring the types of input parameters, return parameters, and variables.
|
||||
|
||||
When a parameter or variable is annotated with a type, the type checker verifies that all values assigned to that parameter or variable conform to that type.
|
||||
|
||||
Consider the following example:
|
||||
```python
|
||||
```viper
|
||||
def func1(p1: float, p2: str, p3, **p4) -> None:
|
||||
var1: int = p1 # This is a type violation
|
||||
var2: str = p2 # This is allowed because the types match
|
||||
@@ -45,7 +45,7 @@ Note that once a symbol’s type is declared, it cannot be redeclared to a diffe
|
||||
|
||||
### Type Inference
|
||||
|
||||
Some languages require every symbol to be explicitly typed. Python allows a symbol to be bound to different values at runtime, so its type can change over time. A symbol’s type doesn’t need to be declared statically.
|
||||
Some languages require every symbol to be explicitly typed. Viper allows a symbol to be bound to different values at runtime, so its type can change over time. A symbol’s type doesn’t need to be declared statically.
|
||||
|
||||
When Pyright encounters a symbol with no type declaration, it attempts to _infer_ the type based on the values assigned to it. As we will see below, type inference cannot always determine the correct (intended) type, so type annotations are still required in some cases. Furthermore, type inference can require significant computation, so it is much less efficient than when type annotations are provided.
|
||||
|
||||
@@ -57,7 +57,7 @@ If a symbol’s type cannot be inferred, Pyright sets its type to “Unknown”,
|
||||
|
||||
The simplest form of type inference is one that involves a single assignment to a symbol. The inferred type comes from the type of the source expression. Examples include:
|
||||
|
||||
```python
|
||||
```viper
|
||||
var1 = 3 # Inferred type is int
|
||||
var2 = "hi" # Inferred type is str
|
||||
var3 = list() # Inferred type is list[Unknown]
|
||||
@@ -70,7 +70,7 @@ var6 = [p for p in [1, 2, 3]] # Inferred type is list[int]
|
||||
|
||||
When a symbol is assigned values in multiple places within the code, those values may have different types. The inferred type of the variable is the union of all such types.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# In this example, symbol var1 has an inferred type of `str | int`.
|
||||
class Foo:
|
||||
def __init__(self):
|
||||
@@ -100,7 +100,7 @@ This technique is called “bidirectional inference” because type inference fo
|
||||
|
||||
Let’s look at a few examples:
|
||||
|
||||
```python
|
||||
```viper
|
||||
var1 = [] # Type of RHS is ambiguous
|
||||
var2: list[int] = [] # Type of LHS now makes type of RHS unambiguous
|
||||
var3 = [4] # Type is assumed to be list[int]
|
||||
@@ -113,7 +113,7 @@ var6: tuple[float, ...] = (3,) # Type of RHS is now tuple[float, ...]
|
||||
|
||||
It is common to initialize a local variable or instance variable to an empty list (`[]`) or empty dictionary (`{}`) on one code path but initialize it to a non-empty list or dictionary on other code paths. In such cases, Pyright will infer the type based on the non-empty list or dictionary and suppress errors about a “partially unknown type”.
|
||||
|
||||
```python
|
||||
```viper
|
||||
if some_condition:
|
||||
my_list = []
|
||||
else:
|
||||
@@ -127,7 +127,7 @@ reveal_type(my_list) # list[str]
|
||||
|
||||
As with variable assignments, function return types can be inferred from the `return` statements found within that function. The returned type is assumed to be the union of all types returned from all `return` statements. If a `return` statement is not followed by an expression, it is assumed to return `None`. Likewise, if the function does not end in a `return` statement, and the end of the function is reachable, an implicit `return None` is assumed.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# This function has two explicit return statements and one implicit
|
||||
# return (at the end). It does not have a declared return type,
|
||||
# so Pyright infers its return type based on the return expressions.
|
||||
@@ -144,7 +144,7 @@ def func1(val: int):
|
||||
|
||||
If there is no code path that returns from a function (e.g. all code paths raise an exception), Pyright infers a return type of `NoReturn`. As an exception to this rule, if the function is decorated with `@abstractmethod`, the return type is not inferred as `NoReturn` even if there is no return. This accommodates a common practice where an abstract method is implemented with a `raise` statement that raises an exception of type `NotImplementedError`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Foo:
|
||||
# The inferred return type is NoReturn.
|
||||
def method1(self):
|
||||
@@ -164,7 +164,7 @@ Pyright can infer the return type for a generator function from the `yield` stat
|
||||
|
||||
It is common for input parameters to be unannotated. This can make it difficult for Pyright to infer the correct return type for a function. For example:
|
||||
|
||||
```python
|
||||
```viper
|
||||
# The return type of this function cannot be fully inferred based
|
||||
# on the information provided because the types of parameters
|
||||
# a and b are unknown. In this case, the inferred return
|
||||
@@ -181,7 +181,7 @@ def func1(a, b, c):
|
||||
|
||||
In cases where all parameters are unannotated, Pyright uses a technique called _call-site return type inference_. It performs type inference using the the types of arguments passed to the function in a call expression. If the unannotated function calls other functions, call-site return type inference can be used recursively. Pyright limits this recursion to a small number for practical performance reasons.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func2(p_int: int, p_str: str, p_flt: float):
|
||||
# The type of var1 is inferred to be `int | None` based
|
||||
# on call-site return type inference.
|
||||
@@ -201,7 +201,7 @@ For class methods, the first parameter (named `cls` by convention) is inferred t
|
||||
|
||||
For other unannotated parameters within a method, Pyright looks for a method of the same name implemented in a base class. If the corresponding method in the base class has the same signature (the same number of parameters with the same names), no overloads, and annotated parameter types, the type annotation from this method is “inherited” for the corresponding parameter in the child class method.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Parent:
|
||||
def method1(self, a: int, b: str) -> float:
|
||||
...
|
||||
@@ -218,7 +218,7 @@ When parameter types are inherited from a base class method, the return type is
|
||||
|
||||
If the type of an unannotated parameter cannot be inferred using any of the above techniques and the parameter has a default argument expression associated with it, the parameter type is inferred from the default argument type. If the default argument is `None`, the inferred type is `Unknown | None`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def func(a, b=0, c=None):
|
||||
pass
|
||||
|
||||
@@ -227,16 +227,16 @@ reveal_type(func) # (a: Unknown, b: int, c: Unknown | None) -> None
|
||||
|
||||
This inference technique also applies to lambdas whose input parameters include default arguments.
|
||||
|
||||
```python
|
||||
```viper
|
||||
cb = lambda x = "": x
|
||||
reveal_type(cb) # (x: str = "" -> str)
|
||||
```
|
||||
|
||||
#### Literals
|
||||
|
||||
Python 3.8 introduced support for _literal types_. This allows a type checker like Pyright to track specific literal values of str, bytes, int, bool, and enum values. As with other types, literal types can be declared.
|
||||
Viper 3.8 introduced support for _literal types_. This allows a type checker like Pyright to track specific literal values of str, bytes, int, bool, and enum values. As with other types, literal types can be declared.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# This function is allowed to return only values 1, 2 or 3.
|
||||
def func1() -> Literal[1, 2, 3]:
|
||||
...
|
||||
@@ -248,7 +248,7 @@ def func2(mode: Literal["r", "w", "rw"]) -> None:
|
||||
|
||||
When Pyright is performing type inference, it generally does not infer literal types. Consider the following example:
|
||||
|
||||
```python
|
||||
```viper
|
||||
# If Pyright inferred the type of var1 to be list[Literal[4]],
|
||||
# any attempt to append a value other than 4 to this list would
|
||||
# generate an error. Pyright therefore infers the broader
|
||||
@@ -260,7 +260,7 @@ var1 = [4]
|
||||
|
||||
When inferring the type of a tuple expression (in the absence of bidirectional inference hints), Pyright assumes that the tuple has a fixed length, and each tuple element is typed as specifically as possible.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# The inferred type is tuple[Literal[1], Literal["a"], Literal[True]].
|
||||
var1 = (1, "a", True)
|
||||
|
||||
@@ -276,7 +276,7 @@ def func1(a: int):
|
||||
|
||||
Because tuples are typed as specifically as possible, literal types are normally retained. However, as an exception to this inference rule, if the tuple expression is nested within another tuple, set, list or dictionary expression, literal types are not retained. This is done to avoid the inference of complex types (e.g. unions with many subtypes) when evaluating tuple statements with many entries.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# The inferred type is list[tuple[int, str, bool]].
|
||||
var4 = [(1, "a", True), (2, "b", False), (3, "c", False)]
|
||||
```
|
||||
@@ -294,7 +294,7 @@ When inferring the type of a list expression (in the absence of bidirectional in
|
||||
|
||||
These heuristics can be overridden through the use of bidirectional inference hints (e.g. by providing a declared type for the target of the assignment expression).
|
||||
|
||||
```python
|
||||
```viper
|
||||
var1 = [] # Infer list[Unknown]
|
||||
|
||||
var2 = [1, 2] # Infer list[int]
|
||||
@@ -319,7 +319,7 @@ When inferring the type of a set expression (in the absence of bidirectional inf
|
||||
|
||||
These heuristics can be overridden through the use of bidirectional inference hints (e.g. by providing a declared type for the target of the assignment expression).
|
||||
|
||||
```python
|
||||
```viper
|
||||
var1 = {1, 2} # Infer set[int]
|
||||
|
||||
# Type depends on strictSetInference config setting
|
||||
@@ -342,7 +342,7 @@ When inferring the type of a dictionary expression (in the absence of bidirectio
|
||||
* Otherwise use the union of all key and value types `dict[Union[(keys)], Union[(values)]]`.
|
||||
|
||||
|
||||
```python
|
||||
```viper
|
||||
var1 = {} # Infer dict[Unknown, Unknown]
|
||||
|
||||
var2 = {1: ""} # Infer dict[int, str]
|
||||
@@ -356,9 +356,9 @@ var4: dict[str, float] = {"a": 3, "b": 3.4}
|
||||
|
||||
#### Lambdas
|
||||
|
||||
Lambdas present a particular challenge for a Python type checker because there is no provision in the Python syntax for annotating the types of a lambda’s input parameters. The types of these parameters must therefore be inferred based on context using bidirectional type inference. Absent this context, a lambda’s input parameters (and often its return type) will be unknown.
|
||||
Lambdas present a particular challenge for a Viper type checker because there is no provision in the Viper syntax for annotating the types of a lambda’s input parameters. The types of these parameters must therefore be inferred based on context using bidirectional type inference. Absent this context, a lambda’s input parameters (and often its return type) will be unknown.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# The type of var1 is (a: Unknown, b: Unknown) -> Unknown.
|
||||
var1 = lambda a, b: a + b
|
||||
|
||||
|
||||
@@ -4,15 +4,15 @@ In addition to the [command-line tool](command-line.md) and the [language server
|
||||
|
||||
## What is the Type Server Protocol?
|
||||
|
||||
The Language Server Protocol (LSP) is designed around editor features (completions, hover, go-to-definition, and so on). Some tools instead need direct access to a Python type checker's *type information* — the inferred type of an expression, the declared type of a symbol, resolved imports, and search paths — without going through editor-oriented requests.
|
||||
The Language Server Protocol (LSP) is designed around editor features (completions, hover, go-to-definition, and so on). Some tools instead need direct access to a Viper type checker's *type information* — the inferred type of an expression, the declared type of a symbol, resolved imports, and search paths — without going through editor-oriented requests.
|
||||
|
||||
The Type Server Protocol is a JSON-RPC protocol, layered on top of the same transport as LSP, that exposes this type information directly. A client can open Python documents in the usual LSP way (`textDocument/didOpen`, `textDocument/didChange`, …) and then ask the type server questions such as:
|
||||
The Type Server Protocol is a JSON-RPC protocol, layered on top of the same transport as LSP, that exposes this type information directly. A client can open Viper documents in the usual LSP way (`textDocument/didOpen`, `textDocument/didChange`, …) and then ask the type server questions such as:
|
||||
|
||||
* `typeServer/getComputedType` — the inferred type at a parse node.
|
||||
* `typeServer/getDeclaredType` — the declared type of a declaration.
|
||||
* `typeServer/getExpectedType` — the expected (contextual) type at a node.
|
||||
* `typeServer/resolveImport` — resolve an import to a file on disk.
|
||||
* `typeServer/getPythonSearchPaths` — the search paths used for import resolution.
|
||||
* `typeServer/getViperSearchPaths` — the search paths used for import resolution.
|
||||
* `typeServer/getSnapshot` — the current analysis snapshot version, used to keep type queries consistent with the document state.
|
||||
|
||||
## Running the type server
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
## Type Stub Files
|
||||
|
||||
Type stubs are “.pyi” files that specify the public interface for a library. They use a variant of the Python syntax that allows for “...” to be used in place of any implementation details. Type stubs define the public contract for the library.
|
||||
Type stubs are “.pyi” files that specify the public interface for a library. They use a variant of the Viper syntax that allows for “...” to be used in place of any implementation details. Type stubs define the public contract for the library.
|
||||
|
||||
### Importance of Type Stub Files
|
||||
|
||||
Regardless of the search path, Pyright always attempts to resolve an import with a type stub (“.pyi”) file before falling back to a python source (“.py”) file. If a type stub cannot be located for an external import, Pyright will try to use inline type information if the module is part of a package that contains a “py.typed” file (defined in [PEP 561](https://www.python.org/dev/peps/pep-0561/)). If the module is part of a package that doesn’t contain a “py.typed” file, Pyright will treat all of the symbols imported from these modules as having type “Unknown”, and wildcard imports (of the form `from foo import *`) will not populate the module’s namespace with specific symbol names.
|
||||
Regardless of the search path, Pyright always attempts to resolve an import with a type stub (“.pyi”) file before falling back to a viper source (“.py”) file. If a type stub cannot be located for an external import, Pyright will try to use inline type information if the module is part of a package that contains a “py.typed” file (defined in [PEP 561](https://www.viper.org/dev/peps/pep-0561/)). If the module is part of a package that doesn’t contain a “py.typed” file, Pyright will treat all of the symbols imported from these modules as having type “Unknown”, and wildcard imports (of the form `from foo import *`) will not populate the module’s namespace with specific symbol names.
|
||||
|
||||
Why does Pyright not attempt (by default) to determine types from imported python sources? There are several reasons.
|
||||
Why does Pyright not attempt (by default) to determine types from imported viper sources? There are several reasons.
|
||||
|
||||
1. Imported libraries can be quite large, so analyzing them can require significant time and computation.
|
||||
2. Some libraries are thin shims on top of native (C++) libraries. Little or no type information would be inferable in these cases.
|
||||
3. Some libraries override Python’s default loader logic. Static analysis is not possible in these cases.
|
||||
3. Some libraries override Viper’s default loader logic. Static analysis is not possible in these cases.
|
||||
4. Type information inferred from source files is often of low value because many types cannot be inferred correctly. Even if concrete types can be inferred, generic type definitions cannot.
|
||||
5. Type analysis would expose all symbols from an imported module, even those that are not meant to be exposed by the author. Unlike many other languages, Python offers no way of differentiating between a symbol that is meant to be exported and one that isn’t.
|
||||
5. Type analysis would expose all symbols from an imported module, even those that are not meant to be exposed by the author. Unlike many other languages, Viper offers no way of differentiating between a symbol that is meant to be exported and one that isn’t.
|
||||
|
||||
If you’re serious about static type checking for your Python source base, it’s highly recommended that you consume “py.typed” packages or use type stub files for all external imports. If you are unable to find a type stub for a particular library, the recommended approach is to create a custom type stub file that defines the portion of that module’s interface used by your code. More library maintainers have started to provide inlined types or type stub files.
|
||||
If you’re serious about static type checking for your Viper source base, it’s highly recommended that you consume “py.typed” packages or use type stub files for all external imports. If you are unable to find a type stub for a particular library, the recommended approach is to create a custom type stub file that defines the portion of that module’s interface used by your code. More library maintainers have started to provide inlined types or type stub files.
|
||||
|
||||
### Generating Type Stubs
|
||||
If you use only a few classes, methods or functions within a library, writing a type stub file by hand is feasible. For large libraries, this can become tedious and error-prone. Pyright can generate “draft” versions of type stub files for you.
|
||||
|
||||
To generate a type stub file from within VS Code, enable the reportMissingTypeStubs” setting in your pyrightconfig.json file or by adding a comment `# pyright: reportMissingTypeStubs=true` to individual source files. Make sure you have the target library installed in the python environment that pyright is configured to use for import resolution. Optionally specify a “stubPath” in your pyrightconfig.json file. This is where pyright will generate your type stub files. By default, the stubPath is set to "./typings".
|
||||
To generate a type stub file from within VS Code, enable the reportMissingTypeStubs” setting in your pyrightconfig.json file or by adding a comment `# pyright: reportMissingTypeStubs=true` to individual source files. Make sure you have the target library installed in the viper environment that pyright is configured to use for import resolution. Optionally specify a “stubPath” in your pyrightconfig.json file. This is where pyright will generate your type stub files. By default, the stubPath is set to "./typings".
|
||||
|
||||
#### Generating Type Stubs in VS Code
|
||||
If “reportMissingTypeStubs” is enabled, pyright will highlight any imports that have no type stub. Hover over the error message, and you will see a “Quick Fix” link. Clicking on this link will reveal a popup menu item titled “Create Type Stub For XXX”. The example below shows a missing typestub for the `django` library.
|
||||
@@ -47,7 +47,7 @@ A few common situations that need to be cleaned up:
|
||||
|
||||
3. Decorator functions are especially problematic for static type analyzers. Unless properly typed, they completely hide the signature of any class or function they are applied to. For this reason, it is highly recommended that you enable the “reportUntypedFunctionDecorator” and “reportUntypedClassDecorator” switches in pyrightconfig.json. Most decorators simply return the same function they are passed. Those can easily be annotated with a TypeVar like this:
|
||||
|
||||
```python
|
||||
```viper
|
||||
from typing import Any, Callable, TypeVar
|
||||
|
||||
_FuncT = TypeVar('_FuncT', bound=Callable[..., Any])
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
## Typing Guidance for Python Libraries
|
||||
## Typing Guidance for Viper Libraries
|
||||
|
||||
Much of Python’s popularity can be attributed to the rich collection of Python libraries available to developers. Authors of these libraries play an important role in improving the experience for Python developers. This document provides some recommendations and guidance for Python library authors.
|
||||
Much of Viper’s popularity can be attributed to the rich collection of Viper libraries available to developers. Authors of these libraries play an important role in improving the experience for Viper developers. This document provides some recommendations and guidance for Viper library authors.
|
||||
|
||||
These recommendations are intended to provide the following benefits:
|
||||
|
||||
1. Consumers of libraries should have a great coding experience with fast and accurate completion suggestions, class and function documentation, signature help (including parameter default values), hover text, and auto-imports. This should happen by default without needing to download extra packages and without any special configuration. These features should be consistent across the Python ecosystem regardless of a developer’s choice of editor, IDE, notebook environment, etc.
|
||||
1. Consumers of libraries should have a great coding experience with fast and accurate completion suggestions, class and function documentation, signature help (including parameter default values), hover text, and auto-imports. This should happen by default without needing to download extra packages and without any special configuration. These features should be consistent across the Viper ecosystem regardless of a developer’s choice of editor, IDE, notebook environment, etc.
|
||||
2. Consumers of libraries should be able to rely on complete and accurate type information so static type checkers can detect and report type inconsistencies and other violations of the interface contract.
|
||||
3. Library authors should be able to specify a well-defined interface contract that is enforced by tools. This allows a library implementation to evolve and improve without breaking consumers of the library.
|
||||
4. Library authors should have the benefits of static type checking to produce high-quality, bug-free implementations.
|
||||
|
||||
|
||||
### Inlined Type Annotations and Type Stubs
|
||||
[PEP 561](https://www.python.org/dev/peps/pep-0561/) documents several ways type information can be delivered for a library: inlined type annotations, type stub files included in the package, a separate companion type stub package, and type stubs in the typeshed repository. Some of these options fall short on delivering the benefits above. We therefore provide the following more specific guidance to library authors.
|
||||
[PEP 561](https://www.viper.org/dev/peps/pep-0561/) documents several ways type information can be delivered for a library: inlined type annotations, type stub files included in the package, a separate companion type stub package, and type stubs in the typeshed repository. Some of these options fall short on delivering the benefits above. We therefore provide the following more specific guidance to library authors.
|
||||
|
||||
All libraries should include inlined type annotations for the functions, classes, methods, and constants that comprise the public interface for the library.
|
||||
|
||||
Inlined type annotations should be included directly within the source code that ships with the package. Of the options listed in PEP 561, inlined type annotations offer the most benefits. They typically require the least effort to add and maintain, they are always consistent with the implementation, and docstrings and default parameter values are readily available, allowing language servers to enhance the development experience.
|
||||
|
||||
There are cases where inlined type annotations are not possible — most notably when a library’s exposed functionality is implemented in a language other than Python. Libraries that expose symbols implemented in languages other than Python should include stub (“.pyi”) files that describe the types for those symbols. These stubs should also contain docstrings and default parameter values.
|
||||
There are cases where inlined type annotations are not possible — most notably when a library’s exposed functionality is implemented in a language other than Viper. Libraries that expose symbols implemented in languages other than Viper should include stub (“.pyi”) files that describe the types for those symbols. These stubs should also contain docstrings and default parameter values.
|
||||
|
||||
In many existing type stubs (such as those found in typeshed), default parameter values are replaced with with “...” and all docstrings are removed. We recommend that default values and docstrings remain within the type stub file so language servers can display this information to developers.
|
||||
|
||||
|
||||
### Library Interface
|
||||
[PEP 561](https://www.python.org/dev/peps/pep-0561/) indicates that a “py.typed” marker file must be included in the package if the author wishes to support type checking of their code.
|
||||
[PEP 561](https://www.viper.org/dev/peps/pep-0561/) indicates that a “py.typed” marker file must be included in the package if the author wishes to support type checking of their code.
|
||||
|
||||
If a “py.typed” module is present, a type checker will treat all modules within that package (i.e. all files that end in “.py” or “.pyi”) as importable unless the module is marked private. There are two ways to mark a module private: (1) the module's filename begins with an underscore; (2) the module is inside a sub-package marked private. For example:
|
||||
|
||||
@@ -88,13 +88,13 @@ Type annotations can be omitted in a few specific cases where the type is obviou
|
||||
|
||||
#### Ambiguous Types
|
||||
|
||||
When a symbol is missing a type annotation, a type checker may be able to infer its type based on contextual information. However, type inference rules are not standardized and differ between type checkers. A symbol is said to have an “ambiguous type” if its type may be inferred differently between different Python type checkers. This can lead to a bad experience for consumers of the library.
|
||||
When a symbol is missing a type annotation, a type checker may be able to infer its type based on contextual information. However, type inference rules are not standardized and differ between type checkers. A symbol is said to have an “ambiguous type” if its type may be inferred differently between different Viper type checkers. This can lead to a bad experience for consumers of the library.
|
||||
|
||||
Ambiguous types can be avoided by providing explicit type annotations.
|
||||
|
||||
|
||||
#### Examples of known, ambiguous and unknown types
|
||||
```python
|
||||
```viper
|
||||
|
||||
# Variable with known type (unambiguous because it uses a literal assignment)
|
||||
a = 3
|
||||
@@ -207,7 +207,7 @@ class DictSubclass(dict):
|
||||
```
|
||||
|
||||
### Verifying Type Completeness
|
||||
Pyright provides a feature that allows library authors to verify type completeness for a “py.typed” package. To use this feature, create a clean Python environment and install your package along with all of the other dependent packages. Run the CLI version of pyright with the `--verifytypes` option.
|
||||
Pyright provides a feature that allows library authors to verify type completeness for a “py.typed” package. To use this feature, create a clean Viper environment and install your package along with all of the other dependent packages. Run the CLI version of pyright with the `--verifytypes` option.
|
||||
|
||||
`pyright --verifytypes <lib>`
|
||||
|
||||
@@ -242,20 +242,20 @@ In general, a function input parameter should be annotated with the widest possi
|
||||
As a specific application of the “use the widest type possible” rule, libraries should generally use immutable forms of container types instead of mutable forms (unless the function needs to modify the container). Use `Sequence` rather than `list`, `Mapping` rather than `dict`, etc. Immutable containers allow for more flexibility because their type parameters are covariant rather than invariant. A parameter that is typed as `Sequence[str | int]` can accept a `list[str | int]`, `list[int]`, `Sequence[str]`, and a `Sequence[int]`. But a parameter typed as `list[str | int]` is much more restrictive and accepts only a `list[str | int]`.
|
||||
|
||||
#### Overloads
|
||||
If a function or method can return multiple different types and those types can be determined based on the presence or types of certain parameters, use the `@overload` mechanism defined in [PEP 484](https://www.python.org/dev/peps/pep-0484/#id45). When overloads are used within a “.py” file, they must appear prior to the function implementation, which should not have an `@overload` decorator.
|
||||
If a function or method can return multiple different types and those types can be determined based on the presence or types of certain parameters, use the `@overload` mechanism defined in [PEP 484](https://www.viper.org/dev/peps/pep-0484/#id45). When overloads are used within a “.py” file, they must appear prior to the function implementation, which should not have an `@overload` decorator.
|
||||
|
||||
#### Keyword-only Parameters
|
||||
If a function or method is intended to take parameters that are specified only by name, use the keyword-only separator ("*").
|
||||
|
||||
```python
|
||||
```viper
|
||||
def create_user(age: int, *, dob: date | None = None):
|
||||
...
|
||||
```
|
||||
|
||||
#### Positional-only Parameters
|
||||
If a function or method is intended to take parameters that are specified only by position, use the positional-only separator ("/") as documented in [PEP 570](https://peps.python.org/pep-0570/). If your library needs to run on versions of Python prior to 3.8, you can alternatively name the positional-only parameters with an identifier that begins with a double underscore.
|
||||
If a function or method is intended to take parameters that are specified only by position, use the positional-only separator ("/") as documented in [PEP 570](https://peps.viper.org/pep-0570/). If your library needs to run on versions of Viper prior to 3.8, you can alternatively name the positional-only parameters with an identifier that begins with a double underscore.
|
||||
|
||||
```python
|
||||
```viper
|
||||
def compare_values(value1: T, value2: T, /) -> bool:
|
||||
...
|
||||
|
||||
@@ -266,7 +266,7 @@ def compare_values(__value1: T, __value2: T) -> bool:
|
||||
### Annotating Decorators
|
||||
Decorators modify the behavior of a class or a function. Providing annotations for decorators is straightforward if the decorator retains the original signature of the decorated function.
|
||||
|
||||
```python
|
||||
```viper
|
||||
_F = TypeVar("_F", bound=Callable[..., Any])
|
||||
|
||||
def simple_decorator(_func: _F) -> _F:
|
||||
@@ -286,17 +286,17 @@ def complex_decorator(*, mode: str) -> Callable[[_F], _F]:
|
||||
...
|
||||
```
|
||||
|
||||
Decorators that mutate the signature of the decorated function present challenges for type annotations. The `ParamSpec` and `Concatenate` mechanisms described in [PEP 612](https://www.python.org/dev/peps/pep-0612/) provide some help here, but these are available only in Python 3.10 and newer. More complex signature mutations may require type annotations that erase the original signature, thus blinding type checkers and other tools that provide signature assistance. As such, library authors are discouraged from creating decorators that mutate function signatures in this manner.
|
||||
Decorators that mutate the signature of the decorated function present challenges for type annotations. The `ParamSpec` and `Concatenate` mechanisms described in [PEP 612](https://www.viper.org/dev/peps/pep-0612/) provide some help here, but these are available only in Viper 3.10 and newer. More complex signature mutations may require type annotations that erase the original signature, thus blinding type checkers and other tools that provide signature assistance. As such, library authors are discouraged from creating decorators that mutate function signatures in this manner.
|
||||
|
||||
#### Generic Classes and Functions
|
||||
Classes and functions that can operate in a generic manner on various types should declare themselves as generic using the mechanisms described in [PEP 484](https://www.python.org/dev/peps/pep-0484/). This includes the use of `TypeVar` symbols. Typically, a `TypeVar` should be private to the file that declares it, and should therefore begin with an underscore.
|
||||
Classes and functions that can operate in a generic manner on various types should declare themselves as generic using the mechanisms described in [PEP 484](https://www.viper.org/dev/peps/pep-0484/). This includes the use of `TypeVar` symbols. Typically, a `TypeVar` should be private to the file that declares it, and should therefore begin with an underscore.
|
||||
|
||||
#### Type Aliases
|
||||
Type aliases are symbols that refer to other types. Generic type aliases (those that refer to unspecialized generic classes) are supported by most type checkers. Pyright also provides support for recursive type aliases.
|
||||
|
||||
[PEP 613](https://www.python.org/dev/peps/pep-0613/) provides a way to explicitly designate a symbol as a type alias using the new TypeAlias annotation.
|
||||
[PEP 613](https://www.viper.org/dev/peps/pep-0613/) provides a way to explicitly designate a symbol as a type alias using the new TypeAlias annotation.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# Simple type alias
|
||||
FamilyPet = Cat | Dog | GoldFish
|
||||
|
||||
@@ -313,7 +313,7 @@ StrOrInt: TypeAlias = str | int
|
||||
#### Abstract Classes and Methods
|
||||
Classes that must be subclassed should derive from `ABC`, and methods or properties that must be overridden should be decorated with the `@abstractmethod` decorator. This allows type checkers to validate that the required methods have been overridden and provide developers with useful error messages when they are not. It is customary to implement an abstract method by raising a `NotImplementedError` exception or subclass thereof.
|
||||
|
||||
```python
|
||||
```viper
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class Hashable(ABC):
|
||||
@@ -330,19 +330,19 @@ class Hashable(ABC):
|
||||
```
|
||||
|
||||
#### Final Classes and Methods
|
||||
Classes that are not intended to be subclassed should be decorated as `@final` as described in [PEP 591](https://www.python.org/dev/peps/pep-0591/). The same decorator can also be used to specify methods that cannot be overridden by subclasses.
|
||||
Classes that are not intended to be subclassed should be decorated as `@final` as described in [PEP 591](https://www.viper.org/dev/peps/pep-0591/). The same decorator can also be used to specify methods that cannot be overridden by subclasses.
|
||||
|
||||
#### Literals
|
||||
Type annotations should make use of the Literal type where appropriate, as described in [PEP 586](https://www.python.org/dev/peps/pep-0586/). Literals allow for more type specificity than their non-literal counterparts.
|
||||
Type annotations should make use of the Literal type where appropriate, as described in [PEP 586](https://www.viper.org/dev/peps/pep-0586/). Literals allow for more type specificity than their non-literal counterparts.
|
||||
|
||||
#### Constants
|
||||
Constant values (those that are read-only) can be specified using the Final annotation as described in [PEP 591](https://www.python.org/dev/peps/pep-0591/).
|
||||
Constant values (those that are read-only) can be specified using the Final annotation as described in [PEP 591](https://www.viper.org/dev/peps/pep-0591/).
|
||||
|
||||
Type checkers will also typically treat variables that are named using all upper-case characters as constants.
|
||||
|
||||
In both cases, it is OK to omit the declared type of a constant if it is assigned a literal str, int, float, bool or None value. In such cases, the type inference rules are clear and unambiguous, and adding a literal type annotation would be redundant.
|
||||
|
||||
```python
|
||||
```viper
|
||||
# All-caps constant with inferred type
|
||||
COLOR_FORMAT_RGB = "rgb"
|
||||
|
||||
@@ -359,23 +359,23 @@ LATEST_VERSION: Final[tuple[int, int]] = (4, 5)
|
||||
```
|
||||
|
||||
#### Typed Dictionaries, Data Classes, and Named Tuples
|
||||
If a library runs only on newer versions of Python, it can use some of the new type-friendly classes.
|
||||
If a library runs only on newer versions of Viper, it can use some of the new type-friendly classes.
|
||||
|
||||
NamedTuple (described in [PEP 484](https://www.python.org/dev/peps/pep-0484/)) is preferred over namedtuple.
|
||||
NamedTuple (described in [PEP 484](https://www.viper.org/dev/peps/pep-0484/)) is preferred over namedtuple.
|
||||
|
||||
Data classes (described in [PEP 557](https://www.python.org/dev/peps/pep-0557/)) are preferred over untyped dictionaries.
|
||||
Data classes (described in [PEP 557](https://www.viper.org/dev/peps/pep-0557/)) are preferred over untyped dictionaries.
|
||||
|
||||
TypedDict (described in [PEP 589](https://www.python.org/dev/peps/pep-0589/)) is preferred over untyped dictionaries.
|
||||
TypedDict (described in [PEP 589](https://www.viper.org/dev/peps/pep-0589/)) is preferred over untyped dictionaries.
|
||||
|
||||
|
||||
### Compatibility with Older Python Versions
|
||||
Each new version of Python from 3.5 onward has introduced new typing constructs. This presents a challenge for library authors who want to maintain runtime compatibility with older versions of Python. This section documents several techniques that can be used to add types while maintaining backward compatibility.
|
||||
### Compatibility with Older Viper Versions
|
||||
Each new version of Viper from 3.5 onward has introduced new typing constructs. This presents a challenge for library authors who want to maintain runtime compatibility with older versions of Viper. This section documents several techniques that can be used to add types while maintaining backward compatibility.
|
||||
|
||||
#### Quoted Annotations
|
||||
Type annotations for variables, parameters, and return types can be placed in quotes. The Python interpreter will then ignore them, whereas a type checker will interpret them as type annotations.
|
||||
Type annotations for variables, parameters, and return types can be placed in quotes. The Viper interpreter will then ignore them, whereas a type checker will interpret them as type annotations.
|
||||
|
||||
```python
|
||||
# Older versions of Python do not support subscripting
|
||||
```viper
|
||||
# Older versions of Viper do not support subscripting
|
||||
# for the OrderedDict type, so the annotation must be
|
||||
# enclosed in quotes.
|
||||
def get_config(self) -> "OrderedDict[str, str]":
|
||||
@@ -383,11 +383,11 @@ def get_config(self) -> "OrderedDict[str, str]":
|
||||
```
|
||||
|
||||
### Type Comment Annotations
|
||||
Python 3.0 introduced syntax for parameter and return type annotations, as specified in [PEP 484](https://www.python.org/dev/peps/pep-0484/). Python 3.6 introduced support for variable type annotations, as specified in [PEP 526](https://www.python.org/dev/peps/pep-0526/).
|
||||
Viper 3.0 introduced syntax for parameter and return type annotations, as specified in [PEP 484](https://www.viper.org/dev/peps/pep-0484/). Viper 3.6 introduced support for variable type annotations, as specified in [PEP 526](https://www.viper.org/dev/peps/pep-0526/).
|
||||
|
||||
If you need to support older versions of Python, type annotations can still be provided as “type comments”. These comments take the form `# type: <annotation>`.
|
||||
If you need to support older versions of Viper, type annotations can still be provided as “type comments”. These comments take the form `# type: <annotation>`.
|
||||
|
||||
```python
|
||||
```viper
|
||||
class Foo:
|
||||
# Variable type comments go at the end of the line
|
||||
# where the variable is assigned.
|
||||
@@ -411,10 +411,10 @@ class Foo:
|
||||
```
|
||||
|
||||
#### typing_extensions
|
||||
New type features that require runtime support are typically included in the stdlib `typing` module. Where possible, these new features are back-ported to a runtime library called `typing_extensions` that works with older Python runtimes.
|
||||
New type features that require runtime support are typically included in the stdlib `typing` module. Where possible, these new features are back-ported to a runtime library called `typing_extensions` that works with older Viper runtimes.
|
||||
|
||||
#### TYPE_CHECKING
|
||||
The `typing` module exposes a variable called `TYPE_CHECKING` which has a value of False within the Python runtime but a value of True when the type checker is performing its analysis. This allows type checking statements to be conditionalized.
|
||||
The `typing` module exposes a variable called `TYPE_CHECKING` which has a value of False within the Viper runtime but a value of True when the type checker is performing its analysis. This allows type checking statements to be conditionalized.
|
||||
|
||||
Care should be taken when using `TYPE_CHECKING` because behavioral changes between type checking and runtime could mask problems that the type checker would otherwise catch.
|
||||
|
||||
@@ -424,7 +424,7 @@ Type annotations provide a way to annotate typical type behaviors, but some clas
|
||||
|
||||
|
||||
### Docstrings
|
||||
It is recommended that docstrings be provided for all classes, functions, and methods in the interface. They should be formatted according to [PEP 257](https://www.python.org/dev/peps/pep-0257/).
|
||||
It is recommended that docstrings be provided for all classes, functions, and methods in the interface. They should be formatted according to [PEP 257](https://www.viper.org/dev/peps/pep-0257/).
|
||||
|
||||
There is currently no single agreed-upon standard for function and method docstrings, but several common variants have emerged. We recommend using one of these variants.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user