Skip to content

Comments

Preserve diagnostic rule overrides when positional args override include#11285

Merged
rchiodo merged 2 commits intomicrosoft:mainfrom
ptarjan:claude/fix-pyright-config-overrides-iic7x
Feb 20, 2026
Merged

Preserve diagnostic rule overrides when positional args override include#11285
rchiodo merged 2 commits intomicrosoft:mainfrom
ptarjan:claude/fix-pyright-config-overrides-iic7x

Conversation

@ptarjan
Copy link
Contributor

@ptarjan ptarjan commented Feb 17, 2026

Summary

When pyright is invoked with positional directory arguments, diagnostic rule overrides from pyrightconfig.json are silently ignored.

Works correctly (config overrides applied):

pyright --project pyrightconfig.json

Broken (config overrides ignored):

pyright --project pyrightconfig.json src/

Reproduction steps

  1. Create pyrightconfig.json:
{
  "include": ["src"],
  "reportPrivateImportUsage": false
}
  1. Create src/mymodule/__init__.py that re-exports from src/mymodule/_internal.py
  2. Create src/consumer.py that imports from mymodule._internal
  3. pyright --project pyrightconfig.json — no errors (correct)
  4. pyright --project pyrightconfig.json src/ — reports reportPrivateImportUsage error (incorrect)

Root cause

Positional args flow through pyright.ts:253-272commandLineOptions.includeFileSpecsOverrideservice.ts:1152-1158 which replaces configOptions.include. The config file is still parsed and configOptions.diagnosticRuleSet has the correct overrides.

The problem is in Program.addTrackedFile(): the new SourceFile._diagnosticRuleSet is initialized to getBasicDiagnosticRuleSet(). The correct rule set from the execution environment is only applied during parse(). For tracked files, diagnostics can be consulted before parse() applies the execution environment rules, so basic defaults (e.g. reportPrivateImportUsage: "error") take effect instead of the config's overrides ("none").

Fix

Add SourceFile.setInitialDiagnosticRuleSet() and call it from Program.addTrackedFile() immediately after construction. Only addTrackedFile is changed — other createSourceFile call sites don't need this because imported/interim files always go through parse() before diagnostics are checked. The setter avoids changing ISourceFileFactory, keeping it non-invasive for third-party API consumers.

Changes

  • sourceFile.ts: Add setInitialDiagnosticRuleSet() public method
  • program.ts: Call the setter in addTrackedFile() after construction
  • privateImportUsage.test.ts: End-to-end test reproducing the bug
  • sourceFile.test.ts: Unit test for the setter

When pyright is invoked with positional directory arguments (e.g.,
`pyright --project pyrightconfig.json dir1`), the files could use
basic default diagnostic rules instead of the config file's overrides.

Root cause: SourceFile._diagnosticRuleSet was initialized to
getBasicDiagnosticRuleSet() at construction and only updated from
the execution environment during parse(). If the basic defaults were
consulted before parse() ran for positional-arg files, rules like
reportPrivateImportUsage='error' would take effect instead of the
config's override (reportPrivateImportUsage='none').

Fix: Add SourceFile.setInitialDiagnosticRuleSet() and call it from
Program.addTrackedFile() immediately after construction. This resolves
the execution environment and applies config-level overrides so the
file has the correct rules before parse/bind. Only addTrackedFile is
changed — imported files and interim files get their rules during
parse() which always runs before diagnostics are checked.

The setter approach avoids changing the ISourceFileFactory interface,
keeping the fix non-invasive for third-party consumers.

https://claude.ai/code/session_01BFGmz4kzVMV9yZgRukHs3z
@ptarjan
Copy link
Contributor Author

ptarjan commented Feb 17, 2026

@microsoft-github-policy-service agree [company="Anthropic"]

@ptarjan
Copy link
Contributor Author

ptarjan commented Feb 17, 2026

@microsoft-github-policy-service agree

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

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/single.py:867:9 - error: Expression with type "tuple[Unknown | Any | NaN | Expr, list[tuple[Unknown, Unknown]] | list[Unknown]] | tuple[Unknown | Any | NaN | Expr, list[tuple[Unknown, Unknown]] | list[Unknown], list[tuple[Unknown, Unknown]] | list[Unknown]]" cannot be assigned to target tuple
-     Type "tuple[Unknown | Any | NaN | Expr, list[tuple[Unknown, Unknown]] | list[Unknown], list[tuple[Unknown, Unknown]] | list[Unknown]]" is incompatible with target tuple
+   .../projects/sympy/sympy/solvers/ode/single.py:867:9 - error: Expression with type "tuple[ComplexInfinity | NaN | Rational | Zero | Infinity | NegativeInfinity | Float | NotImplementedType | Expr | Unknown | Any, list[tuple[Unknown, Unknown]] | list[Unknown]] | tuple[ComplexInfinity | NaN | Rational | Zero | Infinity | NegativeInfinity | Float | NotImplementedType | Expr | Unknown | Any, list[tuple[Unknown, Unknown]] | list[Unknown], list[tuple[Unknown, Unknown]] | list[Unknown]]" cannot be assigned to target tuple
+     Type "tuple[ComplexInfinity | NaN | Rational | Zero | Infinity | NegativeInfinity | Float | NotImplementedType | Expr | Unknown | Any, list[tuple[Unknown, Unknown]] | list[Unknown], list[tuple[Unknown, Unknown]] | list[Unknown]]" is incompatible with target tuple
+   .../projects/sympy/sympy/solvers/ode/single.py:1404:20 - error: Operator "/" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/ode/single.py:1883:22 - error: "is_Rational" is not a known attribute of "None" (reportOptionalMemberAccess)
+   .../projects/sympy/sympy/solvers/ode/single.py:1886:22 - error: "is_Rational" is not a known attribute of "None" (reportOptionalMemberAccess)
+   .../projects/sympy/sympy/solvers/ode/single.py:1905:25 - error: Operator "*" not supported for types "Zero | One | Expr | Unknown | None" and "Zero | One | Expr | Unknown | None"
+     Operator "*" not supported for types "Expr" and "None"
+     Operator "*" not supported for types "None" and "Expr"
+     Operator "*" not supported for types "None" and "None" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/ode/single.py:1905:33 - error: Operator "*" not supported for types "Zero | One | Expr | Unknown | None" and "Zero | One | Expr | Unknown | None"
+     Operator "*" not supported for types "Expr" and "None"
+     Operator "*" not supported for types "None" and "Expr"
+     Operator "*" not supported for types "None" and "None" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/ode/single.py:1914:21 - error: Operator "*" not supported for "None" (reportOptionalOperand)
+   .../projects/sympy/sympy/solvers/ode/single.py:1914:29 - error: Operator "*" not supported for "None" (reportOptionalOperand)
+   .../projects/sympy/sympy/solvers/ode/single.py:1914:44 - error: Operator "*" not supported for "None" (reportOptionalOperand)
+   .../projects/sympy/sympy/solvers/ode/single.py:1914:52 - error: Operator "*" not supported for "None" (reportOptionalOperand)
-   .../projects/sympy/sympy/solvers/ode/single.py:2652:9 - error: Operator "+=" not supported for types "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Infinity | NegativeInfinity | Float | Number | Expr | Unknown | Any" and "Basic | Any | Unknown"
+   .../projects/sympy/sympy/solvers/ode/single.py:2652:9 - error: Operator "+=" not supported for types "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Infinity | NegativeInfinity | Float | Number | Expr | Any | Unknown" and "Basic"
+   .../projects/sympy/sympy/solvers/ode/single.py:2760:30 - error: Object of type "None" is not subscriptable (reportOptionalSubscript)
-   .../projects/sympy/sympy/solvers/tests/test_solveset.py:444:30 - error: Cannot access attribute "limit_denominator" for class "NaN"
-     Attribute "limit_denominator" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/solvers/tests/test_solveset.py:444:30 - error: Cannot access attribute "limit_denominator" for class "ComplexInfinity"
-     Attribute "limit_denominator" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/solvers/tests/test_solveset.py:619:16 - error: No overloads for "__new__" match the provided arguments (reportCallIssue)
+   .../projects/sympy/sympy/solvers/tests/test_solveset.py:619:19 - error: Argument of type "Expr | Unknown | float" cannot be assigned to parameter "arg" of type "Expr" in function "__new__"
+     Type "Expr | Unknown | float" is not assignable to type "Expr"
+       "float" is not assignable to "Expr" (reportArgumentType)
+   .../projects/sympy/sympy/solvers/tests/test_solveset.py:624:16 - error: No overloads for "__new__" match the provided arguments (reportCallIssue)
+   .../projects/sympy/sympy/solvers/tests/test_solveset.py:624:19 - error: Argument of type "Expr | Unknown | float" cannot be assigned to parameter "arg" of type "Expr" in function "__new__"
+     Type "Expr | Unknown | float" is not assignable to type "Expr"
+       "float" is not assignable to "Expr" (reportArgumentType)
-   .../projects/sympy/sympy/stats/joint_rv_types.py:575:27 - error: Argument of type "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Infinity | NegativeInfinity | Float | Number | Expr" cannot be assigned to parameter "stop" of type "SupportsIndex" in function "__new__"
+   .../projects/sympy/sympy/stats/joint_rv_types.py:575:27 - error: Argument of type "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Unknown | Infinity | NegativeInfinity | Float | Number | Expr" cannot be assigned to parameter "stop" of type "SupportsIndex" in function "__new__"
-     Type "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Infinity | NegativeInfinity | Float | Number | Expr" is not assignable to type "SupportsIndex"
+     Type "One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Unknown | Infinity | NegativeInfinity | Float | Number | Expr" is not assignable to type "SupportsIndex"
-   .../projects/sympy/sympy/stats/rv_interface.py:450:42 - error: Operator "-" not supported for types "Unknown | Basic | Any" and "Rational | NaN | ComplexInfinity"
+   .../projects/sympy/sympy/stats/rv_interface.py:450:42 - error: Operator "-" not supported for types "Unknown | Basic | Any" and "Rational | Unknown"
-     Operator "-" not supported for types "Basic" and "Rational"
-     Operator "-" not supported for types "Basic" and "NaN"
-     Operator "-" not supported for types "Basic" and "ComplexInfinity" (reportOperatorIssue)
+     Operator "-" not supported for types "Basic" and "Rational" (reportOperatorIssue)
-   .../projects/sympy/sympy/stats/tests/test_finite_rv.py:34:23 - error: Operator "/" not supported for types "Unknown | Any | One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Expr | MatMul | tuple[Unknown, ...] | Infinity | NegativeInfinity | Float | NotImplementedType | int" and "Unknown | Any | BernoulliDistribution | Probability | Zero | One | tuple[Unknown, ...] | Sum | Expr | ZeroMatrix | NaN | Piecewise | Basic | ComplexInfinity | Float | Infinity | Integer | Lambda | Mul | NegativeInfinity | NegativeOne | Number | Rational | Integral | Literal[0]"
+   .../projects/sympy/sympy/stats/tests/test_finite_rv.py:34:23 - error: Operator "/" not supported for types "Unknown | Any | One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Expr | MatMul | Infinity | NegativeInfinity | Float | NotImplementedType | tuple[Unknown, ...] | int" and "Unknown | Any | BernoulliDistribution | Probability | Zero | One | tuple[Unknown, ...] | Sum | Expr | ZeroMatrix | NaN | Piecewise | Basic | ComplexInfinity | Float | Infinity | Integer | Lambda | Mul | NegativeInfinity | NegativeOne | Number | Rational | Integral | Literal[0]"
-   .../projects/sympy/sympy/stats/tests/test_finite_rv.py:246:19 - error: Argument of type "Rational | NaN | ComplexInfinity" cannot be assigned to parameter "p" of type "Half" in function "Coin"
+   .../projects/sympy/sympy/stats/tests/test_finite_rv.py:246:19 - error: Argument of type "Rational | Unknown" cannot be assigned to parameter "p" of type "Half" in function "Coin"
-     Type "Rational | NaN | ComplexInfinity" is not assignable to type "Half"
+     Type "Rational | Unknown" is not assignable to type "Half"
-       "ComplexInfinity" is not assignable to "Half" (reportArgumentType)
+       "Rational" is not assignable to "Half" (reportArgumentType)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:403:32 - error: Cannot access attribute "shape" for class "Infinity"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:403:32 - error: Cannot access attribute "shape" for class "NegativeInfinity"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:403:32 - error: Cannot access attribute "shape" for class "Float"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:429:25 - error: Cannot access attribute "shape" for class "Infinity"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:429:25 - error: Cannot access attribute "shape" for class "NegativeInfinity"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)
+   .../projects/sympy/sympy/tensor/array/expressions/from_array_to_matrix.py:429:25 - error: Cannot access attribute "shape" for class "Float"
+     Attribute "shape" is unknown (reportAttributeAccessIssue)

... (truncated 996 lines) ...

@rchiodo rchiodo merged commit f6bdd93 into microsoft:main Feb 20, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants