diff --git a/src/Analysis/Ast/Impl/Analyzer/Handlers/ImportHandler.cs b/src/Analysis/Ast/Impl/Analyzer/Handlers/ImportHandler.cs
index 2efbd406e..d06f48b6e 100644
--- a/src/Analysis/Ast/Impl/Analyzer/Handlers/ImportHandler.cs
+++ b/src/Analysis/Ast/Impl/Analyzer/Handlers/ImportHandler.cs
@@ -86,6 +86,11 @@ private bool HandleImportSearchResult(in IImportSearchResult imports, in PythonV
return TryGetModulePossibleImport(possibleModuleImport, parent, location, out variableModule);
case ImplicitPackageImport packageImport:
return TryGetPackageFromImport(packageImport, parent, out variableModule);
+ case RelativeImportBeyondTopLevel importBeyondTopLevel:
+ var message = Resources.ErrorRelativeImportBeyondTopLevel.FormatInvariant(importBeyondTopLevel.RelativeImportName);
+ Eval.ReportDiagnostics(Eval.Module.Uri, new DiagnosticsEntry(message, location.Span, ErrorCodes.UnresolvedImport, Severity.Warning));
+ variableModule = default;
+ return false;
case ImportNotFound importNotFound:
var memberName = asNameExpression?.Name ?? importNotFound.FullName;
MakeUnresolvedImport(memberName, importNotFound.FullName, location);
diff --git a/src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs b/src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs
index bb9a976ab..4c3560284 100644
--- a/src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs
+++ b/src/Analysis/Ast/Impl/Analyzer/PythonAnalyzer.cs
@@ -41,7 +41,7 @@ public sealed class PythonAnalyzer : IPythonAnalyzer, IDisposable {
private readonly AsyncAutoResetEvent _analysisRunningEvent = new AsyncAutoResetEvent();
private readonly ProgressReporter _progress;
private readonly ILogger _log;
- private readonly int _maxTaskRunning = 8;
+ private readonly int _maxTaskRunning = Environment.ProcessorCount * 3;
private int _runningTasks;
private int _version;
diff --git a/src/Analysis/Ast/Impl/Resources.Designer.cs b/src/Analysis/Ast/Impl/Resources.Designer.cs
index f3d9da7c2..895e001d2 100644
--- a/src/Analysis/Ast/Impl/Resources.Designer.cs
+++ b/src/Analysis/Ast/Impl/Resources.Designer.cs
@@ -168,6 +168,15 @@ internal static string ErrorNotCallableEmpty {
}
}
+ ///
+ /// Looks up a localized string similar to Relative import '{0}' beyond top-level package.
+ ///
+ internal static string ErrorRelativeImportBeyondTopLevel {
+ get {
+ return ResourceManager.GetString("ErrorRelativeImportBeyondTopLevel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to unresolved import '{0}'.
///
diff --git a/src/Analysis/Ast/Impl/Resources.resx b/src/Analysis/Ast/Impl/Resources.resx
index 8769ae5f0..e2ed86638 100644
--- a/src/Analysis/Ast/Impl/Resources.resx
+++ b/src/Analysis/Ast/Impl/Resources.resx
@@ -312,6 +312,9 @@
unresolved import '{0}'
+
+ Relative import '{0}' beyond top-level package
+
'{0}' used before definition
diff --git a/src/Analysis/Ast/Impl/scrape_module.py b/src/Analysis/Ast/Impl/scrape_module.py
index fc3da8a31..c0de7239f 100644
--- a/src/Analysis/Ast/Impl/scrape_module.py
+++ b/src/Analysis/Ast/Impl/scrape_module.py
@@ -28,9 +28,12 @@
import tokenize
import warnings
-try:
- import builtins
-except ImportError:
+if sys.version_info >= (3, 0):
+ try:
+ import builtins
+ except ImportError:
+ import __builtin__ as builtins
+else:
import __builtin__ as builtins
try:
diff --git a/src/Analysis/Ast/Test/BasicTests.cs b/src/Analysis/Ast/Test/BasicTests.cs
index 47d47b8cd..2be4d75df 100644
--- a/src/Analysis/Ast/Test/BasicTests.cs
+++ b/src/Analysis/Ast/Test/BasicTests.cs
@@ -19,6 +19,8 @@
using Microsoft.Python.Analysis.Tests.FluentAssertions;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Analysis.Values;
+using Microsoft.Python.Parsing;
+using Microsoft.Python.Parsing.Tests;
using Microsoft.Python.Tests.Utilities.FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestUtilities;
@@ -83,12 +85,19 @@ import sys
.And.HaveVariable("x").OfType(BuiltinTypeId.List);
}
- [TestMethod, Priority(0)]
- public async Task BuiltinsTest() {
+ [DataRow(true, true)]
+ [DataRow(false, true)]
+ [DataRow(true, false)]
+ [DataRow(false, false)]
+ [DataTestMethod, Priority(0)]
+ public async Task BuiltinsTest(bool isPython3X, bool isAnaconda) {
const string code = @"
x = 1
";
- var analysis = await GetAnalysisAsync(code);
+ var configuration = isPython3X
+ ? isAnaconda ? PythonVersions.LatestAnaconda3X : PythonVersions.LatestAvailable3X
+ : isAnaconda ? PythonVersions.LatestAnaconda2X : PythonVersions.LatestAvailable2X;
+ var analysis = await GetAnalysisAsync(code, configuration);
var v = analysis.Should().HaveVariable("x").Which;
var t = v.Value.GetPythonType();
diff --git a/src/Analysis/Ast/Test/ImportTests.cs b/src/Analysis/Ast/Test/ImportTests.cs
index 85a597b97..ea26ebbd1 100644
--- a/src/Analysis/Ast/Test/ImportTests.cs
+++ b/src/Analysis/Ast/Test/ImportTests.cs
@@ -212,7 +212,7 @@ public async Task UnresolvedRelativeFromImportAs() {
var d = analysis.Diagnostics.First();
d.ErrorCode.Should().Be(ErrorCodes.UnresolvedImport);
d.SourceSpan.Should().Be(1, 6, 1, 19);
- d.Message.Should().Be(Resources.ErrorUnresolvedImport.FormatInvariant("nonexistent"));
+ d.Message.Should().Be(Resources.ErrorRelativeImportBeyondTopLevel.FormatInvariant("nonexistent"));
}
}
}
diff --git a/src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.cs b/src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.cs
index a7519ddea..dfa81d7c2 100644
--- a/src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.cs
+++ b/src/Analysis/Core/Impl/DependencyResolution/PathResolverSnapshot.cs
@@ -190,9 +190,9 @@ public IImportSearchResult GetImportsFromRelativePath(in string modulePath, in i
return default;
}
- if (parentCount > lastEdge.PathLength) {
+ if (parentCount >= lastEdge.PathLength) {
// Can't get outside of the root
- return default;
+ return new RelativeImportBeyondTopLevel(string.Join(".", relativePath));
}
var fullNameList = relativePath.TakeWhile(n => !string.IsNullOrEmpty(n)).ToList();
@@ -208,7 +208,7 @@ public IImportSearchResult GetImportsFromRelativePath(in string modulePath, in i
return new ImportNotFound(new StringBuilder(lastEdge.Start.Name)
.Append(".")
- .Append(fullNameList)
+ .Append(".", fullNameList)
.ToString());
}
diff --git a/src/Analysis/Core/Impl/DependencyResolution/RelativeImportBeyondTopLevel.cs b/src/Analysis/Core/Impl/DependencyResolution/RelativeImportBeyondTopLevel.cs
new file mode 100644
index 000000000..c255b36d5
--- /dev/null
+++ b/src/Analysis/Core/Impl/DependencyResolution/RelativeImportBeyondTopLevel.cs
@@ -0,0 +1,23 @@
+// Copyright(c) Microsoft Corporation
+// All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the License); you may not use
+// this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.apache.org/licenses/LICENSE-2.0
+//
+// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
+// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
+// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+// MERCHANTABILITY OR NON-INFRINGEMENT.
+//
+// See the Apache Version 2.0 License for specific language governing
+// permissions and limitations under the License.
+
+namespace Microsoft.Python.Analysis.Core.DependencyResolution {
+ public class RelativeImportBeyondTopLevel : IImportSearchResult {
+ public string RelativeImportName { get; }
+ public RelativeImportBeyondTopLevel(string relativeImportName) {
+ RelativeImportName = relativeImportName;
+ }
+ }
+}
diff --git a/src/LanguageServer/Test/CompletionTests.cs b/src/LanguageServer/Test/CompletionTests.cs
index 172d695c6..d832e4ccf 100644
--- a/src/LanguageServer/Test/CompletionTests.cs
+++ b/src/LanguageServer/Test/CompletionTests.cs
@@ -903,6 +903,26 @@ public async Task FromDotInRoot() {
result.Should().HaveNoCompletion();
}
+ [TestMethod, Priority(0)]
+ public async Task FromDotInRootWithInitPy() {
+ var initPyPath = TestData.GetTestSpecificUri("__init__.py");
+ var module1Path = TestData.GetTestSpecificUri("module1.py");
+
+ var root = TestData.GetTestSpecificRootUri().AbsolutePath;
+ await CreateServicesAsync(root, PythonVersions.LatestAvailable3X);
+ var rdt = Services.GetService();
+
+ rdt.OpenDocument(initPyPath, string.Empty);
+ var module1 = rdt.OpenDocument(module1Path, "from .");
+ module1.Interpreter.ModuleResolution.GetOrLoadModule("__init__");
+
+ var analysis = await module1.GetAnalysisAsync(-1);
+
+ var cs = new CompletionSource(new PlainTextDocumentationSource(), ServerSettings.completion);
+ var result = cs.GetCompletions(analysis, new SourceLocation(1, 7));
+ result.Should().HaveNoCompletion();
+ }
+
[TestMethod, Priority(0)]
public async Task FromDotInExplicitPackage() {
var initPyPath = TestData.GetTestSpecificUri("package", "__init__.py");
diff --git a/src/Parsing/Test/PythonVersions.cs b/src/Parsing/Test/PythonVersions.cs
index bebec8bb5..8ffc34b19 100644
--- a/src/Parsing/Test/PythonVersions.cs
+++ b/src/Parsing/Test/PythonVersions.cs
@@ -36,12 +36,16 @@ public static class PythonVersions {
public static readonly InterpreterConfiguration Anaconda27_x64 = GetAnacondaVersion(PythonLanguageVersion.V27, InterpreterArchitecture.x64);
public static readonly InterpreterConfiguration Anaconda36 = GetAnacondaVersion(PythonLanguageVersion.V36, InterpreterArchitecture.x86);
public static readonly InterpreterConfiguration Anaconda36_x64 = GetAnacondaVersion(PythonLanguageVersion.V36, InterpreterArchitecture.x64);
+ public static readonly InterpreterConfiguration Anaconda37 = GetAnacondaVersion(PythonLanguageVersion.V37, InterpreterArchitecture.x86);
+ public static readonly InterpreterConfiguration Anaconda37_x64 = GetAnacondaVersion(PythonLanguageVersion.V37, InterpreterArchitecture.x64);
public static readonly InterpreterConfiguration IronPython27_x64 = GetIronPythonVersion(true);
public static readonly InterpreterConfiguration Jython27 = GetJythonVersion(PythonLanguageVersion.V27);
public static IEnumerable AnacondaVersions => GetVersions(
Anaconda36,
Anaconda36_x64,
+ Anaconda37,
+ Anaconda37_x64,
Anaconda27,
Anaconda27_x64);
@@ -81,6 +85,16 @@ public static class PythonVersions {
Python27,
Python27_x64).FirstOrDefault() ?? NotInstalled("v2");
+ public static InterpreterConfiguration LatestAnaconda3X => GetVersions(
+ Anaconda37,
+ Anaconda37_x64,
+ Anaconda36,
+ Anaconda36_x64).FirstOrDefault() ?? NotInstalled("Anaconda v3");
+
+ public static InterpreterConfiguration LatestAnaconda2X => GetVersions(
+ Anaconda27,
+ Anaconda27_x64).FirstOrDefault() ?? NotInstalled("Anaconda v2");
+
public static InterpreterConfiguration EarliestAvailable => EarliestAvailable2X ?? EarliestAvailable3X;
public static InterpreterConfiguration EarliestAvailable3X => GetVersions(