Skip to content

Commit

Permalink
feat: implemented allowed-untyped-libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
Wizzerinus committed Jan 9, 2025
1 parent dd2ebd8 commit e302c06
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/pyright-internal/src/analyzer/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,12 @@ export class Binder extends ParseTreeWalker {
}

// A source file was found, but the type stub was missing.
// If the module is allowed as an untyped library, we don't need the stub
if (
!importResult.isStubFile &&
importResult.importType === ImportType.ThirdParty &&
!importResult.pyTypedInfo
!importResult.pyTypedInfo &&
!this._ignoreUntypedModule(importResult.importName)
) {
const diagnostic = this._addDiagnostic(
DiagnosticRule.reportMissingTypeStubs,
Expand Down Expand Up @@ -4331,6 +4333,10 @@ export class Binder extends ParseTreeWalker {
private _addSyntaxError(message: string, textRange: TextRange) {
return this._fileInfo.diagnosticSink.addDiagnosticWithTextRange('error', message, textRange);
}

private _ignoreUntypedModule(module: string) {
return this._fileInfo.diagnosticRuleSet.allowedUntypedLibraries.some(x => (module + ".").startsWith(x + "."));
}
}

export class YieldFinder extends ParseTreeWalker {
Expand Down
12 changes: 12 additions & 0 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15114,6 +15114,10 @@ export function createTypeEvaluator(
return { type, isIncomplete, typeErrors };
}

function _ignoreUntypedModule(ruleset: DiagnosticRuleSet, module: string) {
return ruleset.allowedUntypedLibraries.some(x => (module + ".").startsWith(x + "."));
}

function reportPossibleUnknownAssignment(
ruleset: DiagnosticRuleSet,
rule: DiagnosticRule,
Expand All @@ -15127,6 +15131,14 @@ export function createTypeEvaluator(
return;
}

// Or if the object is in an untyped library that was explicitly mentioned.
if (type.shared && "moduleName" in type.shared) {
const moduleName = type.shared.moduleName;
if (_ignoreUntypedModule(ruleset, moduleName)) {
return;
}
}

const nameValue = target.d.value;

// Sometimes variables contain an "unbound" type if they're
Expand Down
26 changes: 26 additions & 0 deletions packages/pyright-internal/src/common/configOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ export interface DiagnosticRuleSet {
reportUnusedParameter: DiagnosticLevel;
reportImplicitAbstractClass: DiagnosticLevel;
reportUnannotatedClassAttribute: DiagnosticLevel;
allowedUntypedLibraries: string[];
}

export function cloneDiagnosticRuleSet(diagSettings: DiagnosticRuleSet): DiagnosticRuleSet {
Expand Down Expand Up @@ -687,6 +688,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
reportUnusedParameter: 'hint',
reportImplicitAbstractClass: 'none',
reportUnannotatedClassAttribute: 'none',
allowedUntypedLibraries: [],
};

return diagSettings;
Expand Down Expand Up @@ -803,6 +805,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
reportUnusedParameter: 'hint',
reportImplicitAbstractClass: 'none',
reportUnannotatedClassAttribute: 'none',
allowedUntypedLibraries: [],
};

return diagSettings;
Expand Down Expand Up @@ -919,6 +922,7 @@ export function getStandardDiagnosticRuleSet(): DiagnosticRuleSet {
reportUnusedParameter: 'hint',
reportImplicitAbstractClass: 'none',
reportUnannotatedClassAttribute: 'none',
allowedUntypedLibraries: [],
};

return diagSettings;
Expand Down Expand Up @@ -1034,6 +1038,7 @@ export const getRecommendedDiagnosticRuleSet = (): DiagnosticRuleSet => ({
reportUnusedParameter: 'warning',
reportImplicitAbstractClass: 'warning',
reportUnannotatedClassAttribute: 'warning',
allowedUntypedLibraries: [],
});

export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({
Expand Down Expand Up @@ -1146,6 +1151,7 @@ export const getAllDiagnosticRuleSet = (): DiagnosticRuleSet => ({
reportUnusedParameter: 'error',
reportImplicitAbstractClass: 'error',
reportUnannotatedClassAttribute: 'error',
allowedUntypedLibraries: [],
});

export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
Expand Down Expand Up @@ -1259,6 +1265,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
reportUnusedParameter: 'hint',
reportImplicitAbstractClass: 'none',
reportUnannotatedClassAttribute: 'none',
allowedUntypedLibraries: [],
};

return diagSettings;
Expand Down Expand Up @@ -1601,6 +1608,25 @@ export class ConfigOptions {
console
);
});

// Read the config "allowedUntypedLibraries".
const allowedUntypedLibraries: string[] = [];
if (configObj.allowedUntypedLibraries !== undefined) {
if (!Array.isArray(configObj.allowedUntypedLibraries)) {
console.error(`Config "allowedUntypedLibraries" field must contain an array.`);
} else {
const pathList = configObj.allowedUntypedLibraries as string[];
pathList.forEach((lib, libIndex) => {
if (typeof lib !== 'string') {
console.error(`Config "allowedUntypedLibraries" field ${libIndex} must be a string.`);
} else {
allowedUntypedLibraries.push(lib);
}
});
configRuleSet.allowedUntypedLibraries = allowedUntypedLibraries;
}
}

this.diagnosticRuleSet = { ...configRuleSet };

// Read the "venvPath".
Expand Down

0 comments on commit e302c06

Please sign in to comment.