Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main' into browser
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/pyright-internal/src/analyzer/cacheManager.ts
  • Loading branch information
DetachHead committed Aug 3, 2024
2 parents 187c8be + cf11460 commit d256bdc
Show file tree
Hide file tree
Showing 333 changed files with 10,538 additions and 8,251 deletions.
6 changes: 6 additions & 0 deletions .idea/externalDependencies.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
)](https://marketplace.visualstudio.com/items?itemName=detachhead.basedpyright)
[![open VSX](https://img.shields.io/open-vsx/dt/detachhead/basedpyright?logo=vscodium&color=2F80ED)](https://open-vsx.org/extension/detachhead/basedpyright)
[![sublime text](https://img.shields.io/packagecontrol/dt/LSP-basedpyright?logo=sublimetext&color=FF9800)](https://packagecontrol.io/packages/LSP-basedpyright)
[![pycharm](https://img.shields.io/jetbrains/plugin/v/24145?logo=pycharm)](./docs/installation.md#pycharm)
[![pycharm](https://img.shields.io/jetbrains/plugin/v/24145?logo=pycharm)](https://plugins.jetbrains.com/plugin/24145)
[![nvim-lspconfig](https://img.shields.io/badge/nvim--lspconfig-grey?logo=neovim)](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#basedpyright)
[![coc.nvim](https://img.shields.io/badge/coc.nvim-grey?logo=vim)](https://github.com/fannheyward/coc-basedpyright)
[![emacs](https://img.shields.io/badge/emacs-grey?logo=gnuemacs&logoColor=ffffff)](https://github.com/manateelazycat/lsp-bridge)
Expand Down Expand Up @@ -74,9 +74,7 @@ it's good practice to specify an error code in your `pyright: ignore` comments:
# pyright: ignore[reportUnreachable]
```

this way, if the error changes or a new error appears on the same line in the future, you'll get a new error because the comment doesn't account for the other error. unfortunately there are many rules in pyright that do not have error codes, so you can't always do this.

basedpyright resolves this by reporting those errors under the `reportGeneralTypeIssues` diagnostic rule. this isn't a perfect solution, but there were over 100 errors that didn't have diagnostic rules. i intend to split them into their own rules in the future, but this will do for now.
this way, if the error changes or a new error appears on the same line in the future, you'll get a new error because the comment doesn't account for the other error.

note that `type: ignore` comments (`enableTypeIgnoreComments`) are unsafe and are disabled by default (see [#330](https://github.com/DetachHead/basedpyright/issues/330) and [#55](https://github.com/DetachHead/basedpyright/issues/55)). we recommend using `pyright: ignore` comments instead.

Expand Down Expand Up @@ -352,7 +350,7 @@ basedpyright:

we aim to [port most of basedmypy's features to basedpyright](https://github.com/DetachHead/basedpyright/issues?q=is%3Aissue+is%3Aopen+label%3A%22basedmypy+feature+parity%22), however as mentioned above our priority is to first fix the critical problems with pyright.

note that any non-standard features we add will be optional, as we intend to support library developmers who can't control what type checker their library is used with.
note that any non-standard features we add will be optional, as we intend to support library developers who can't control what type checker their library is used with.

# pypi package

Expand Down
219 changes: 116 additions & 103 deletions docs/configuration.md

Large diffs are not rendered by default.

13 changes: 3 additions & 10 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,9 @@ with [lsp-pyright](https://github.com/emacs-lsp/lsp-pyright)
### PyCharm

### If using Community edition
install [pyright-for-pycharm](https://plugins.jetbrains.com/plugin/24145)
install the [Pyright](https://plugins.jetbrains.com/plugin/24145) plugin

configure it to use basedpyright by specifying the path to the `basedpyright` executable:
configure it to use basedpyright by specifying the path to the `basedpyright-langserver` executable and set "Running mode" to "LSP4IJ":

![image](https://github.com/DetachHead/basedpyright/assets/57028336/b373a5ee-c423-4b94-b833-00b5335a9611)
![](https://github.com/user-attachments/assets/accfc498-825c-4c39-9e2c-35195c41fd67)

### If using Professional edition
intsall [pyright-langserver-for-pycharm](https://plugins.jetbrains.com/plugin/24146-pyright-language-server). This plugin makes use of PyCharm's experimental [LSP API](https://plugins.jetbrains.com/docs/intellij/language-server-protocol.html).

configure it to use basedpyright by specifying the path to the `basedpyright-langserver` executable:

![image](https://github.com/DetachHead/basedpyright/assets/57028336/4ee471ad-68cb-410e-8b67-81c57f4bb80b)
112 changes: 112 additions & 0 deletions docs/type-concepts-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,3 +545,115 @@ 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.


### 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
def func(x: Literal[1, 3], y: Literal[4, 7]):
z = x + y
reveal_type(z) # Literal[5, 8, 7, 10]

z = x * y
reveal_type(z) # Literal[4, 7, 12, 21]

z = (x | y) ^ 1
reveal_type(z) # Literal[4, 6]

z = x ** y
reveal_type(z) # Literal[1, 81, 2187]
```

Literal math also works on `str` literals.

```python
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
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]
z = y * x
reveal_type(z) # int
```

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).

* `sys.version_info <comparison> <tuple>`
* `sys.version_info[0] >= <number>`
* `sys.platform == <string literal>`
* `os.name == <string literal>`
* `typing.TYPE_CHECKING` or `typing_extensions.TYPE_CHECKING`
* `True` or `False`
* An identifier defined with the "defineConstant" configuration option
* A `not` unary operator with any of the above forms
* An `and` or `or` binary operator with any of the above forms

If one of these conditional expressions evaluates statically to false, pyright does not analyze any of the code within it other than checking for and reporting syntax errors.


### Reachability
Pyright performs “reachability analysis” to determine whether statements will be executed at runtime.

Reachability analysis is based on both non-type and type information. Non-type information includes statements that unconditionally affect code flow such as `continue`, `raise` and `return`. It also includes conditional statements (`if`, `elif`, or `while`) where the conditional expression is one of these [supported expression forms](type-concepts-advanced#static-conditional-evaluation). Type analysis is not performed on code determined to be unreachable using non-type information. Therefore, language server features like completion suggestions are not available for this code.

Here are some examples of code determined to be unreachable using non-type information.

```python
from typing import TYPE_CHECKING
import sys

if False:
print('unreachable')

if not TYPE_CHECKING:
print('unreachable')

if sys.version_info < (3, 0):
print('unreachable')

if sys.platform == 'ENIAC':
print('unreachable')

def func1():
return
print('unreachable')

def func2():
raise NotImplemented
print('unreachable')
```

Pyright can also detect code that is unreachable based on static type analysis. This analysis is based on the assumption that any provided type annotations are accurate.

Here are some examples of code determined to be unreachable using type analysis.

```python
from typing import Literal, NoReturn

def always_raise() -> NoReturn:
raise ValueError

def func1():
always_raise()
print('unreachable')

def func2(x: str):
if not isinstance(x, str):
print('unreachable')

def func3(x: Literal[1, 2]):
if x == 1 or x == 2:
return

print("unreachable")
```

Code that is determined to be unreachable is reported through the use of “tagged hints”. These are special diagnostics that tell a language client to display the code in a visually distinctive manner, typically with a grayed-out appearance. Code determined to be unreachable using non-type information is always reported through this mechanism. Code determined to be unreachable using type analysis is reported only if “enableReachabilityAnalysis” is enabled in the configuration.
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "1.1.372",
"version": "1.1.374",
"command": {
"version": {
"push": false,
Expand Down
4 changes: 2 additions & 2 deletions packages/pyright-internal/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/pyright-internal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "pyright-internal",
"displayName": "pyright",
"description": "Type checker for the Python language",
"version": "1.1.372",
"version": "1.1.374",
"license": "MIT",
"private": true,
"files": [
Expand Down
6 changes: 3 additions & 3 deletions packages/pyright-internal/src/analyzer/analyzerNodeInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ interface AnalyzerNodeInfo {
dunderAllInfo?: DunderAllInfo | undefined;

// Indicates that the NameNode refers to a type parameter.
typeParameterSymbol?: Symbol;
typeParamSymbol?: Symbol;
}

export type ScopedNode = ModuleNode | ClassNode | FunctionNode | LambdaNode | ComprehensionNode;
Expand Down Expand Up @@ -114,8 +114,8 @@ export function cleanNodeAnalysisInfo(node: ParseNode) {
info.dunderAllInfo = undefined;
}

if (info?.typeParameterSymbol) {
info.typeParameterSymbol = undefined;
if (info?.typeParamSymbol) {
info.typeParamSymbol = undefined;
}
}

Expand Down
28 changes: 14 additions & 14 deletions packages/pyright-internal/src/analyzer/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { TextRange, getEmptyRange } from '../common/textRange';
import { Uri } from '../common/uri/uri';
import { LocAddendum, LocMessage } from '../localization/localize';
import {
ArgumentCategory,
ArgCategory,
AssertNode,
AssignmentExpressionNode,
AssignmentNode,
Expand Down Expand Up @@ -112,10 +112,10 @@ import {
FunctionDeclaration,
IntrinsicType,
ModuleLoaderActions,
ParameterDeclaration,
ParamDeclaration,
SpecialBuiltInClassDeclaration,
TypeAliasDeclaration,
TypeParameterDeclaration,
TypeParamDeclaration,
UnresolvedModuleMarker,
VariableDeclaration,
} from './declaration';
Expand Down Expand Up @@ -565,8 +565,8 @@ export class Binder extends ParseTreeWalker {
}

if (symbol) {
const paramDeclaration: ParameterDeclaration = {
type: DeclarationType.Parameter,
const paramDeclaration: ParamDeclaration = {
type: DeclarationType.Param,
node: paramNode,
uri: this._fileInfo.fileUri,
range: convertTextRangeToRange(paramNode, this._fileInfo.lines),
Expand Down Expand Up @@ -638,8 +638,8 @@ export class Binder extends ParseTreeWalker {
if (paramNode.d.name) {
const symbol = this._bindNameToScope(this._currentScope, paramNode.d.name);
if (symbol) {
const paramDeclaration: ParameterDeclaration = {
type: DeclarationType.Parameter,
const paramDeclaration: ParamDeclaration = {
type: DeclarationType.Param,
node: paramNode,
uri: this._fileInfo.fileUri,
range: convertTextRangeToRange(paramNode, this._fileInfo.lines),
Expand Down Expand Up @@ -672,7 +672,7 @@ export class Binder extends ParseTreeWalker {
this._disableTrueFalseTargets(() => {
this.walk(node.d.leftExpr);

const sortedArgs = ParseTreeUtils.getArgumentsByRuntimeOrder(node);
const sortedArgs = ParseTreeUtils.getArgsByRuntimeOrder(node);

sortedArgs.forEach((argNode) => {
if (this._currentFlowNode) {
Expand Down Expand Up @@ -793,8 +793,8 @@ export class Binder extends ParseTreeWalker {
node.d.params.forEach((param) => {
const name = param.d.name;
const symbol = typeParamScope.addSymbol(name.d.value, SymbolFlags.None);
const paramDeclaration: TypeParameterDeclaration = {
type: DeclarationType.TypeParameter,
const paramDeclaration: TypeParamDeclaration = {
type: DeclarationType.TypeParam,
node: param,
uri: this._fileInfo.fileUri,
range: convertTextRangeToRange(node, this._fileInfo.lines),
Expand Down Expand Up @@ -3049,7 +3049,7 @@ export class Binder extends ParseTreeWalker {
expression.nodeType === ParseNodeType.Index &&
expression.d.items.length === 1 &&
!expression.d.trailingComma &&
expression.d.items[0].d.argCategory === ArgumentCategory.Simple
expression.d.items[0].d.argCategory === ArgCategory.Simple
) {
if (isCodeFlowSupportedForReference(expression.d.leftExpr)) {
expressionList.push(expression.d.leftExpr);
Expand Down Expand Up @@ -3101,7 +3101,7 @@ export class Binder extends ParseTreeWalker {
expression.d.leftExpr.d.leftExpr.nodeType === ParseNodeType.Name &&
expression.d.leftExpr.d.leftExpr.d.value === 'type' &&
expression.d.leftExpr.d.args.length === 1 &&
expression.d.leftExpr.d.args[0].d.argCategory === ArgumentCategory.Simple
expression.d.leftExpr.d.args[0].d.argCategory === ArgCategory.Simple
) {
return this._isNarrowingExpression(
expression.d.leftExpr.d.args[0].d.valueExpr,
Expand Down Expand Up @@ -3976,7 +3976,7 @@ export class Binder extends ParseTreeWalker {
const finalInfo = this._isAnnotationFinal(typeAnnotation.d.leftExpr);
if (
finalInfo.isFinal &&
typeAnnotation.d.items[0].d.argCategory === ArgumentCategory.Simple &&
typeAnnotation.d.items[0].d.argCategory === ArgCategory.Simple &&
!typeAnnotation.d.items[0].d.name &&
!typeAnnotation.d.trailingComma
) {
Expand Down Expand Up @@ -4016,7 +4016,7 @@ export class Binder extends ParseTreeWalker {
const finalInfo = this._isAnnotationClassVar(typeAnnotation.d.leftExpr);
if (
finalInfo.isClassVar &&
typeAnnotation.d.items[0].d.argCategory === ArgumentCategory.Simple &&
typeAnnotation.d.items[0].d.argCategory === ArgCategory.Simple &&
!typeAnnotation.d.items[0].d.name &&
!typeAnnotation.d.trailingComma
) {
Expand Down
6 changes: 5 additions & 1 deletion packages/pyright-internal/src/analyzer/cacheManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { HeapInfo } from 'v8';
import { AnalysisRequest } from '../backgroundAnalysisBase';
import { ConsoleInterface } from '../common/console';
import { fail } from '../common/debug';
import { getHeapStatistics } from '../common/memUtils';
import { getHeapStatistics, getSystemMemoryInfo } from '../common/memUtils';
import { MessageSourceSink } from '../common/workersHost';

export interface CacheOwner {
Expand Down Expand Up @@ -125,8 +125,12 @@ export class CacheManager {
if (console && Date.now() - this._lastHeapStats > 1000) {
// This can fill up the user's console, so we only do it once per second.
this._lastHeapStats = Date.now();
const systemMemInfo = getSystemMemoryInfo();

console.info(
`Heap stats: ` +
`total_memory_size=${this._convertToMB(systemMemInfo.total)}, ` +
`total_free_size=${this._convertToMB(systemMemInfo.free)}, ` +
`total_heap_size=${this._convertToMB(heapStats.total_heap_size)}, ` +
`used_heap_size=${this._convertToMB(heapStats.used_heap_size)}, ` +
`cross_worker_used_heap_size=${this._convertToMB(usage)}, ` +
Expand Down
Loading

0 comments on commit d256bdc

Please sign in to comment.