Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 74aa212

Browse files
author
Mikhail Arkhipov
authored
Allow exporting of instances from modules and prefer real types to Any (#1153)
* Allow re-export of instances * Add test * Fix test
1 parent 5387499 commit 74aa212

File tree

6 files changed

+53
-6
lines changed

6 files changed

+53
-6
lines changed

src/Analysis/Ast/Impl/Analyzer/ModuleWalker.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.Python.Analysis.Analyzer.Evaluation;
2020
using Microsoft.Python.Analysis.Documents;
2121
using Microsoft.Python.Analysis.Modules;
22+
using Microsoft.Python.Analysis.Specializations.Typing;
2223
using Microsoft.Python.Analysis.Types;
2324
using Microsoft.Python.Analysis.Types.Collections;
2425
using Microsoft.Python.Analysis.Values;
@@ -239,6 +240,11 @@ private void MergeStub() {
239240

240241
var sourceVar = Eval.GlobalScope.Variables[v.Name];
241242
var sourceType = sourceVar?.Value.GetPythonType();
243+
244+
// If stub says 'Any' but we have better type, keep the current type.
245+
if (!IsStubBetterType(sourceType, stubType)) {
246+
continue;;
247+
}
242248

243249
// If types are the classes, merge members.
244250
// Otherwise, replace type from one from the stub.
@@ -250,9 +256,15 @@ private void MergeStub() {
250256
var stubMember = stubType.GetMember(name);
251257
var member = cls.GetMember(name);
252258

259+
var memberType = member?.GetPythonType();
260+
var stubMemberType = stubMember.GetPythonType();
261+
if (!IsStubBetterType(memberType, stubMemberType)) {
262+
continue; ;
263+
}
264+
253265
// Get documentation from the current type, if any, since stubs
254266
// typically do not contain documentation while scraped code does.
255-
member?.GetPythonType()?.TransferDocumentationAndLocation(stubMember.GetPythonType());
267+
memberType?.TransferDocumentationAndLocation(stubMemberType);
256268
cls.AddMember(name, stubMember, overwrite: true);
257269
}
258270
} else {
@@ -268,5 +280,9 @@ private void MergeStub() {
268280
}
269281
}
270282
}
283+
284+
private static bool IsStubBetterType(IPythonType sourceType, IPythonType stubType)
285+
// If stub says 'Any' but we have better type, keep the current type.
286+
=> sourceType.IsUnknown() || !(stubType.DeclaringModule is TypingModule) || stubType.Name != "Any";
271287
}
272288
}

src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ private void UpdateClassMembers() {
150150
// Add members from this file
151151
var members = Eval.CurrentScope.Variables.Where(v => v.Source == VariableSource.Declaration || v.Source == VariableSource.Import);
152152
_class.AddMembers(members, false);
153-
// Add members from stub
154-
var stubClass = Eval.Module.Stub?.GetMember<IPythonClassType>(_class.Name);
155-
_class.AddMembers(stubClass, false);
156153
}
157154

158155
// Classes and functions are walked by their respective evaluators

src/Analysis/Ast/Impl/Modules/PythonModule.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,18 @@ public virtual string Documentation {
153153
public virtual IEnumerable<string> GetMemberNames() {
154154
// drop imported modules and typing.
155155
return Analysis.GlobalScope.Variables
156-
.Where(v => !(v.Value?.GetPythonType() is PythonModule)
157-
&& !(v.Value?.GetPythonType().DeclaringModule is TypingModule && !(this is TypingModule)))
156+
.Where(v => {
157+
// Instances are always fine.
158+
if (v.Value is IPythonInstance) {
159+
return true;
160+
}
161+
var valueType = v.Value?.GetPythonType();
162+
if (valueType is PythonModule) {
163+
return false; // Do not re-export modules.
164+
}
165+
// Do not re-export types from typing
166+
return !(valueType?.DeclaringModule is TypingModule) || this is TypingModule;
167+
})
158168
.Select(v => v.Name);
159169
}
160170
#endregion

src/Analysis/Ast/Test/ImportTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,5 +222,14 @@ public async Task FromFuture() {
222222
analysis.Diagnostics.Should().BeEmpty();
223223
analysis.Should().HaveFunction("print");
224224
}
225+
226+
[TestMethod, Priority(0)]
227+
public async Task PreferTypeToAny() {
228+
var analysis = await GetAnalysisAsync(@"from TypingConstants import *", PythonVersions.LatestAvailable3X);
229+
analysis.Should().HaveVariable("ONE").Which.Should().HaveType("Any");
230+
analysis.Should().HaveVariable("TWO").Which.Should().HaveType(BuiltinTypeId.Str);
231+
var a = analysis.Should().HaveClass("A").Which;
232+
a.GetMember("x").Should().HaveType(BuiltinTypeId.Int);
233+
}
225234
}
226235
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import Any
2+
3+
ONE = ... # type: Any
4+
TWO = 'a'
5+
6+
class A:
7+
x = 1
8+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from typing import Any
2+
3+
ONE = ... # type: Any
4+
TWO = ... # type: Any
5+
6+
class A:
7+
x: Any

0 commit comments

Comments
 (0)