Add noImplicitReexport Config Option#11290
Add noImplicitReexport Config Option#11290GregMFriedman wants to merge 4 commits intomicrosoft:mainfrom
Conversation
Introduces a new boolean diagnostic rule `noImplicitReexport` (default: true) that mirrors mypy's `no_implicit_reexport` flag. No behavior change yet — this commit adds the enum value, DiagnosticRuleSet field, preset defaults, and JSON schema definition/references.
@microsoft-github-policy-service agree |
| "title": "Treat typing-specific aliases to standard types as deprecated", | ||
| "default": false | ||
| }, | ||
| "noImplicitReexport": { |
There was a problem hiding this comment.
I think you need a setting for this in the vscode-pyright package.json. Like the example here:
pyright/packages/vscode-pyright/package.json
Line 194 in c971180
There was a problem hiding this comment.
Shouldn't the title be the same for both?
There was a problem hiding this comment.
yes, sorry--fixed now (and i've simplified the failing tests b/c I couldn't figure out why the strings weren't matching, they looked exactly the same)
2d79d6e to
fe8aac0
Compare
This comment has been minimized.
This comment has been minimized.
fe8aac0 to
da7c318
Compare
Adds two unit tests to the noImplicitReexport describe block: - A test.failing() asserting that public names should not produce reportPrivateImportUsage errors when noImplicitReexport=false - A passing test confirming the default (noImplicitReexport=true) still errors on both public and private implicit imports The test.failing() will be un-failed in the next commit when the behavior is implemented in typeEvaluator.ts.
da7c318 to
1e6d878
Compare
This comment has been minimized.
This comment has been minimized.
When noImplicitReexport=false, reportPrivateImportUsage is suppressed for public names (no leading underscore) that are implicitly re-exported via plain `from X import Y` in py.typed packages, mirroring mypy's no_implicit_reexport=false behavior. Names with a leading underscore continue to be reported regardless of this setting. Changes: - typeEvaluator.ts: guard both reportPrivateImportUsage raise sites - privateImportUsage.test.ts: promote test.failing() -> test() - docs/configuration.md: document noImplicitReexport with table row - import.pytyped.noImplicitReexport.fourslash.ts: fourslash test covering public names (no error) and underscore-prefixed names (still errors) Closes microsoft#11288
1e6d878 to
391c541
Compare
packages/vscode-pyright/package.json
Outdated
| "python.analysis.noImplicitReexport": { | ||
| "type": "boolean", | ||
| "default": true, | ||
| "description": "Require explicit re-export of imported symbols in py.typed packages (mirrors mypy's no_implicit_reexport)", |
There was a problem hiding this comment.
Sorry I still find this confusing. Might this be better?
"When true, imported symbols in py.typed packages require explicit re-export (via all or 'as' alias). Set to false to allow plain imports as re-exports for public names."
There was a problem hiding this comment.
done, i agree that is better
|
Diff from mypy_primer, showing the effect of this PR on open source code: sympy (https://github.com/sympy/sympy)
- .../projects/sympy/sympy/solvers/ode/lie_group.py:618:61 - error: Operator "-" not supported for type "Basic | Unknown" (reportOperatorIssue)
- .../projects/sympy/sympy/solvers/ode/nonhomogeneous.py:467:28 - error: Argument of type "Unknown | None" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
+ .../projects/sympy/sympy/solvers/ode/nonhomogeneous.py:467:28 - error: Argument of type "Expr | Unknown | None" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
- Type "Unknown | None" is not assignable to type "Expr"
+ Type "Expr | Unknown | None" is not assignable to type "Expr"
+ Attribute "pop" is unknown (reportAttributeAccessIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:609:22 - error: Cannot access attribute "pop" for class "tuple[()]"
+ Attribute "pop" is unknown (reportAttributeAccessIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:609:22 - error: Cannot access attribute "pop" for class "tuple[str, ...]"
+ .../projects/sympy/sympy/solvers/ode/ode.py:1515:38 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1516:38 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1526:9 - error: No overloads for "update" match the provided arguments (reportCallIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1526:12 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1526:19 - error: Argument of type "Unknown | dict[Unknown, Unknown] | None" cannot be assigned to parameter "m" of type "Iterable[tuple[str, Unknown]]" in function "update"
+ Type "Unknown | dict[Unknown, Unknown] | None" is not assignable to type "Iterable[tuple[str, Unknown]]"
+ "None" is incompatible with protocol "Iterable[tuple[str, Unknown]]"
+ "__iter__" is not present (reportArgumentType)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1533:43 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1533:64 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1539:9 - error: No overloads for "update" match the provided arguments (reportCallIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1539:12 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1539:19 - error: Argument of type "Unknown | dict[Unknown, Unknown] | None" cannot be assigned to parameter "m" of type "Iterable[tuple[str, Unknown]]" in function "update"
+ Type "Unknown | dict[Unknown, Unknown] | None" is not assignable to type "Iterable[tuple[str, Unknown]]"
+ "None" is incompatible with protocol "Iterable[tuple[str, Unknown]]"
+ "__iter__" is not present (reportArgumentType)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1546:43 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1546:74 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1552:9 - error: No overloads for "update" match the provided arguments (reportCallIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1552:12 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1552:19 - error: Argument of type "Unknown | dict[Unknown, Unknown] | None" cannot be assigned to parameter "m" of type "Iterable[tuple[str, Unknown]]" in function "update"
+ Type "Unknown | dict[Unknown, Unknown] | None" is not assignable to type "Iterable[tuple[str, Unknown]]"
+ "None" is incompatible with protocol "Iterable[tuple[str, Unknown]]"
+ "__iter__" is not present (reportArgumentType)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1559:49 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:1559:70 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
- .../projects/sympy/sympy/solvers/ode/ode.py:1689:36 - error: Cannot access attribute "lhs" for class "Expr"
- Attribute "lhs" is unknown (reportAttributeAccessIssue)
- .../projects/sympy/sympy/solvers/ode/ode.py:1689:55 - error: Cannot access attribute "rhs" for class "Expr"
- Attribute "rhs" is unknown (reportAttributeAccessIssue)
- .../projects/sympy/sympy/solvers/ode/ode.py:1690:36 - error: Cannot access attribute "lhs" for class "Expr"
- Attribute "lhs" is unknown (reportAttributeAccessIssue)
- .../projects/sympy/sympy/solvers/ode/ode.py:1691:17 - error: No overloads for "__setitem__" match the provided arguments (reportCallIssue)
- .../projects/sympy/sympy/solvers/ode/ode.py:1691:17 - error: Argument of type "Equality | BooleanFalse | BooleanTrue | Unknown | Expr" cannot be assigned to parameter "value" of type "Equality | BooleanFalse | BooleanTrue" in function "__setitem__"
- Type "Equality | BooleanFalse | BooleanTrue | Unknown | Expr" is not assignable to type "Equality | BooleanFalse | BooleanTrue"
- Type "Expr" is not assignable to type "Equality | BooleanFalse | BooleanTrue"
- "Expr" is not assignable to "Equality"
- "Expr" is not assignable to "BooleanFalse"
- "Expr" is not assignable to "BooleanTrue" (reportArgumentType)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3378:7 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3378:38 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3379:7 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3379:38 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3380:14 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3381:14 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3382:14 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3394:50 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3395:50 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3396:50 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3436:5 - error: No overloads for "update" match the provided arguments (reportCallIssue)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3436:7 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3436:14 - error: Argument of type "Unknown | dict[Unknown, Unknown] | None" cannot be assigned to parameter "m" of type "Iterable[tuple[str, Unknown]]" in function "update"
+ Type "Unknown | dict[Unknown, Unknown] | None" is not assignable to type "Iterable[tuple[str, Unknown]]"
+ "None" is incompatible with protocol "Iterable[tuple[str, Unknown]]"
+ "__iter__" is not present (reportArgumentType)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3437:18 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3437:43 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3438:9 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3438:16 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3438:24 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3438:31 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3439:9 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3439:15 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3439:23 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3439:30 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3440:7 - error: "update" is not a known attribute of "None" (reportOptionalMemberAccess)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3440:46 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3440:54 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3441:9 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3441:19 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
+ .../projects/sympy/sympy/solvers/ode/ode.py:3441:29 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
... (truncated 275 lines) ...
|
Addresses review feedback requesting a VS Code setting entry for the new noImplicitReexport config option.
391c541 to
bb1dd82
Compare
|
Sorry I'm going to defer to Eric's judgement on the issue. Unless you can convince him otherwise, I don't think we'll accept this PR. |
Summary
Adds a
noImplicitReexportboolean config option (default:true) that mirrors mypy'sno_implicit_reexportflag. When set tofalse, plainfrom X import Yimports inpy.typedpackages are treated as valid re-exports for public names (no leading underscore), suppressing false-positivereportPrivateImportUsageerrors. Names with a leading underscore remain private regardless of this setting.Closes #11288
Motivation
Projects that use both mypy and Pyright encounter false positives when a
py.typedlibrary re-exports symbols via plain imports without__all__or the redundant-alias form. mypy's default (no_implicit_reexport = false) accepts these as valid re-exports; Pyright previously had no equivalent escape hatch.Changes
diagnosticRules.ts: addnoImplicitReexportenum valueconfigOptions.ts: add toDiagnosticRuleSet,getBooleanDiagnosticRules(), and all four preset defaultspyrightconfig.schema.json: add definition and property referencestypeEvaluator.ts: guard bothreportPrivateImportUsageraise sites to skip public names whennoImplicitReexport=falsedocs/configuration.md: document the new option and add comparison table rowimport.pytyped.noImplicitReexport.fourslash.ts: fourslash test verifying public names pass and_-prefixed names still errorprivateImportUsage.test.ts: unit tests for bothnoImplicitReexport=falseand=truebehavior