Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

report explicit usages of Any #83

Merged
merged 3 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions based_build/localization_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import json
from pathlib import Path
from typing import TYPE_CHECKING, Any, ClassVar, Dict, TypedDict, Union, cast, final
from typing import TYPE_CHECKING, ClassVar, Dict, TypedDict, Union, cast, final

from rich.highlighter import ReprHighlighter
from rich.text import Text
Expand All @@ -14,6 +14,8 @@
from typing_extensions import override

if TYPE_CHECKING:
from collections.abc import Mapping

from textual.widgets.tree import TreeNode

highlighter = ReprHighlighter()
Expand Down Expand Up @@ -41,7 +43,7 @@ def read_locfile(language: str = "en-us") -> dict[str, LocMessages]:
LOCDATA_EN_US = read_locfile()


def diff_keys(orig: dict[str, Any], comp: dict[str, Any]):
def diff_keys(orig: Mapping[str, object], comp: Mapping[str, object]):
msgs: list[str] = []
orig_set = set(orig.keys())
comp_set = set(comp.keys())
Expand Down
16 changes: 15 additions & 1 deletion docs/benefits-over-pyright/new-diagnostic-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,21 @@ def foo(bar, baz: Any) -> Any:
print(baz) # no error
```

basedpyright introduces the `reportAny` option, which will report an error on usages of anything typed as `Any`.
basedpyright introduces the `reportAny` option, which will report an error on usages of anything typed as `Any`:

```py
def foo(baz: Any) -> Any:
print(baz) # error: reportAny
```

## `reportExplicitAny`

similar to [`reportAny`](#reportany), however this rule bans usages of the `Any` type itself rather than expressions that are typed as `Any`:

```py
def foo(baz: Any) -> Any: # error: reportExplicitAny
print(baz) # error: reportAny
```

## `reportIgnoreCommentWithoutRule`

Expand Down
4 changes: 3 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ the following additional options are not available in regular pyright:

- <a name="reportUnreachable"></a> **reportUnreachable** [boolean or string, optional]: Generate or suppress diagnostics for unreachable code.

- <a name="reportAny"></a> **reportAny** [boolean or string, optional]: Ban all usages of the `Any` type. this accounts for all scenarios not covered by the `reportUnknown*` rules (since "Unknown" isn't a real type, but a distinction pyright makes to disallow the `Any` type only in certain circumstances).
- <a name="reportAny"></a> **reportAny** [boolean or string, optional]: Generate or suppress diagnostics for expressions that have the `Any` type. this accounts for all scenarios not covered by the `reportUnknown*` rules (since "Unknown" isn't a real type, but a distinction pyright makes to disallow the `Any` type only in certain circumstances).

- <a name="reportExplicitAny"></a> **reportExplicitAny** [boolean or string, optional]: Ban all explicit usages of the `Any` type. While `reportAny` bans expressions typed as `Any`, this rule bans using the `Any` type directly eg. in a type annotation.

- <a name="reportIgnoreCommentWithoutRule"></a> **reportIgnoreCommentWithoutRule** [boolean or string, optional]: Enforce that all `# type:ignore`/`# pyright:ignore` comments specify a rule in brackets (eg. `# pyright:ignore[reportAny]`)

Expand Down
4 changes: 4 additions & 0 deletions packages/pyright-internal/src/analyzer/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,10 @@ export class Checker extends ParseTreeWalker {
const type = this._evaluator.getType(node);
this._reportDeprecatedUseForType(node, type);

if (type && isAny(type) && type.props?.specialForm) {
this._evaluator.addDiagnostic(DiagnosticRule.reportExplicitAny, LocMessage.explicitAny(), node);
}

return true;
}

Expand Down
8 changes: 8 additions & 0 deletions packages/pyright-internal/src/common/configOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ export interface DiagnosticRuleSet {
failOnWarnings: boolean;
reportUnreachable: DiagnosticLevel;
reportAny: DiagnosticLevel;
reportExplicitAny: DiagnosticLevel;
reportIgnoreCommentWithoutRule: DiagnosticLevel;
reportPrivateLocalImportUsage: DiagnosticLevel;
reportImplicitRelativeImport: DiagnosticLevel;
Expand Down Expand Up @@ -540,6 +541,7 @@ export function getDiagLevelDiagnosticRules() {
DiagnosticRule.reportImplicitOverride,
DiagnosticRule.reportUnreachable,
DiagnosticRule.reportAny,
DiagnosticRule.reportExplicitAny,
DiagnosticRule.reportIgnoreCommentWithoutRule,
DiagnosticRule.reportInvalidCast,
DiagnosticRule.reportImplicitRelativeImport,
Expand Down Expand Up @@ -673,6 +675,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
failOnWarnings: false,
reportUnreachable: 'hint',
reportAny: 'none',
reportExplicitAny: 'none',
reportIgnoreCommentWithoutRule: 'none',
reportPrivateLocalImportUsage: 'none',
reportImplicitRelativeImport: 'none',
Expand Down Expand Up @@ -787,6 +790,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
failOnWarnings: false,
reportUnreachable: 'hint',
reportAny: 'none',
reportExplicitAny: 'none',
reportIgnoreCommentWithoutRule: 'none',
reportPrivateLocalImportUsage: 'none',
reportImplicitRelativeImport: 'none',
Expand Down Expand Up @@ -901,6 +905,7 @@ export function getStandardDiagnosticRuleSet(): DiagnosticRuleSet {
failOnWarnings: false,
reportUnreachable: 'hint',
reportAny: 'none',
reportExplicitAny: 'none',
reportIgnoreCommentWithoutRule: 'none',
reportPrivateLocalImportUsage: 'none',
reportImplicitRelativeImport: 'none',
Expand Down Expand Up @@ -1014,6 +1019,7 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({
failOnWarnings: true,
reportUnreachable: 'warning',
reportAny: 'warning',
reportExplicitAny: 'warning',
reportIgnoreCommentWithoutRule: 'warning',
reportPrivateLocalImportUsage: 'warning',
reportImplicitRelativeImport: 'error',
Expand Down Expand Up @@ -1124,6 +1130,7 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({
failOnWarnings: true,
reportUnreachable: 'error',
reportAny: 'error',
reportExplicitAny: 'error',
reportIgnoreCommentWithoutRule: 'error',
reportPrivateLocalImportUsage: 'error',
reportImplicitRelativeImport: 'error',
Expand Down Expand Up @@ -1235,6 +1242,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
failOnWarnings: false,
reportUnreachable: 'hint',
reportAny: 'none',
reportExplicitAny: 'none',
reportIgnoreCommentWithoutRule: 'none',
reportPrivateLocalImportUsage: 'none',
reportImplicitRelativeImport: 'none',
Expand Down
1 change: 1 addition & 0 deletions packages/pyright-internal/src/common/diagnosticRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export enum DiagnosticRule {
failOnWarnings = 'failOnWarnings',
reportUnreachable = 'reportUnreachable',
reportAny = 'reportAny',
reportExplicitAny = 'reportExplicitAny',
reportIgnoreCommentWithoutRule = 'reportIgnoreCommentWithoutRule',
reportPrivateLocalImportUsage = 'reportPrivateLocalImportUsage',
reportImplicitRelativeImport = 'reportImplicitRelativeImport',
Expand Down
1 change: 1 addition & 0 deletions packages/pyright-internal/src/localization/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ export namespace Localizer {
new ParameterizedString<{ classes: string }>(getRawString('Diagnostic.multipleInheritance'));
export const unannotatedClassAttribute = () =>
new ParameterizedString<{ name: string }>(getRawString('Diagnostic.unannotatedClassAttribute'));
export const explicitAny = () => getRawString('Diagnostic.explicitAny');
}

export namespace DiagnosticAddendum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1730,7 +1730,8 @@
"implicitRelativeImport": "Import from `{importName}` is implicitly relative and will not work if this file is imported as a module",
"invalidCast": "Conversion of type `{fromType}` to type `{toType}` may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to `object` first.",
"multipleInheritance": "Multiple inheritance is not allowed because the following base classes contain `__init__` or `__new__` methods that may not get called: {classes}",
"unannotatedClassAttribute": "Type annotation for attribute `{name}` is required because this class is not decorated with `@final`"
"unannotatedClassAttribute": "Type annotation for attribute `{name}` is required because this class is not decorated with `@final`",
"explicitAny": "Type `Any` is not allowed"
},
"DiagnosticAddendum": {
"annotatedNotAllowed": {
Expand Down
14 changes: 14 additions & 0 deletions packages/pyright-internal/src/tests/reportAny.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,17 @@ test('reportAny', () => {
],
});
});

test('reportExplicitAny', () => {
const configOptions = new ConfigOptions(Uri.empty());
configOptions.diagnosticRuleSet.reportExplicitAny = 'error';
const analysisResults = typeAnalyzeSampleFiles(['reportAny.py'], configOptions);

validateResultsButBased(analysisResults, {
errors: [3, 3, 7, 15].map((lineNumber) => ({
line: lineNumber,
code: DiagnosticRule.reportExplicitAny,
message: LocMessage.explicitAny(),
})),
});
});
19 changes: 18 additions & 1 deletion packages/vscode-pyright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,24 @@
"string",
"boolean"
],
"description": "Diagnostics for anything with the `Any` type",
"description": "Diagnostics for expressions with the `Any` type",
"default": "none",
"enum": [
"none",
"hint",
"information",
"warning",
"error",
true,
false
]
},
"reportExplicitAny": {
"type": [
"string",
"boolean"
],
"description": "Diagnostics for type annotations that use the `Any` type",
"default": "none",
"enum": [
"none",
Expand Down
13 changes: 12 additions & 1 deletion packages/vscode-pyright/schemas/pyrightconfig.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,12 @@
},
"reportAny": {
"$ref": "#/definitions/diagnostic",
"title": "Controls reporting of values typed as `Any`",
"title": "Controls reporting of expressions typed as `Any`",
"default": "none"
},
"reportExplicitAny": {
"$ref": "#/definitions/diagnostic",
"title": "Controls reporting of type annotations that use the `Any` type",
"default": "none"
},
"reportIgnoreCommentWithoutRule": {
Expand Down Expand Up @@ -920,6 +925,9 @@
"reportAny": {
"$ref": "#/definitions/reportAny"
},
"reportExplicitAny": {
"$ref": "#/definitions/reportExplicitAny"
},
"reportIgnoreCommentWithoutRule": {
"$ref": "#/definitions/reportIgnoreCommentWithoutRule"
},
Expand Down Expand Up @@ -1268,6 +1276,9 @@
"reportAny": {
"$ref": "#/definitions/reportAny"
},
"reportExplicitAny": {
"$ref": "#/definitions/reportExplicitAny"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add it to the playground

},
"reportIgnoreCommentWithoutRule": {
"$ref": "#/definitions/reportIgnoreCommentWithoutRule"
},
Expand Down
Loading