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

Handle on-the-fly search path configuration changes, read search paths from config directly #1492

Merged
merged 13 commits into from
Aug 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions src/Analysis/Ast/Impl/Analyzer/PythonInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Microsoft.Python.Analysis.Specializations.Typing;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Core;
using Microsoft.Python.Core.Collections;
using Microsoft.Python.Core.Services;
using Microsoft.Python.Parsing;

Expand All @@ -43,20 +44,33 @@ private PythonInterpreter(InterpreterConfiguration configuration) {
LanguageVersion = Configuration.Version.ToLanguageVersion();
}

private async Task InitializeAsync(string root, IServiceManager sm, CancellationToken cancellationToken = default) {
private async Task InitializeAsync(
string root,
IServiceManager sm,
string typeshedPath,
ImmutableArray<string> userConfiguredPaths,
CancellationToken cancellationToken
) {
cancellationToken.ThrowIfCancellationRequested();

sm.AddService(this);
_moduleResolution = new MainModuleResolution(root, sm);
_stubResolution = new TypeshedResolution(Configuration.TypeshedPath, sm);
_moduleResolution = new MainModuleResolution(root, sm, userConfiguredPaths);
_stubResolution = new TypeshedResolution(typeshedPath, sm);

await _stubResolution.ReloadAsync(cancellationToken);
await _moduleResolution.ReloadAsync(cancellationToken);
}

public static async Task<IPythonInterpreter> CreateAsync(InterpreterConfiguration configuration, string root, IServiceManager sm, CancellationToken cancellationToken = default) {
public static async Task<IPythonInterpreter> CreateAsync(
InterpreterConfiguration configuration,
string root,
IServiceManager sm,
string typeshedPath = null,
ImmutableArray<string> userConfiguredPaths = default,
CancellationToken cancellationToken = default
) {
var pi = new PythonInterpreter(configuration);
await pi.InitializeAsync(root, sm, cancellationToken);
await pi.InitializeAsync(root, sm, typeshedPath, userConfiguredPaths, cancellationToken);

// Specialize typing
TypingModule.Create(sm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Python.Analysis.Caching;
using Microsoft.Python.Analysis.Core.Interpreter;
using Microsoft.Python.Analysis.Types;
Expand All @@ -25,7 +24,7 @@ namespace Microsoft.Python.Analysis.Modules {
/// <summary>
/// Represents module resolution and search subsystem.
/// </summary>
public interface IModuleManagement: IModuleResolution {
public interface IModuleManagement : IModuleResolution {
/// <summary>
/// Builtins module name.
/// </summary>
Expand Down Expand Up @@ -75,5 +74,7 @@ public interface IModuleManagement: IModuleResolution {
/// Set of interpreter paths.
/// </summary>
ImmutableArray<string> InterpreterPaths { get; }

bool SetUserConfiguredPaths(ImmutableArray<string> paths);
}
}
27 changes: 18 additions & 9 deletions src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ internal sealed class MainModuleResolution : ModuleResolutionBase, IModuleManage
private readonly IUIService _ui;
private IRunningDocumentTable _rdt;

private ImmutableArray<string> _userPaths = ImmutableArray<string>.Empty;
private ImmutableArray<string> _userConfiguredPaths;

public MainModuleResolution(string root, IServiceContainer services)
public MainModuleResolution(string root, IServiceContainer services, ImmutableArray<string> userConfiguredPaths)
: base(root, services) {

_ui = services.GetService<IUIService>();
_userConfiguredPaths = userConfiguredPaths;
}

public string BuiltinModuleName => BuiltinTypeId.Unknown.GetModuleName(Interpreter.LanguageVersion);

public IBuiltinsPythonModule BuiltinsModule { get; private set; }
Expand Down Expand Up @@ -173,11 +173,11 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) {

await ReloadSearchPaths(cancellationToken);

PathResolver = new PathResolver(Interpreter.LanguageVersion, Root, InterpreterPaths, _userPaths);
PathResolver = new PathResolver(Interpreter.LanguageVersion, Root, InterpreterPaths, UserPaths);

var addedRoots = new HashSet<string> { Root };
addedRoots.UnionWith(InterpreterPaths);
addedRoots.UnionWith(_userPaths);
addedRoots.UnionWith(UserPaths);
ReloadModulePaths(addedRoots);

if (!builtinsIsCreated) {
Expand All @@ -198,10 +198,10 @@ private static IBuiltinsPythonModule CreateBuiltinsModule(IServiceContainer serv

private async Task ReloadSearchPaths(CancellationToken cancellationToken = default) {
var paths = await GetInterpreterSearchPathsAsync(cancellationToken);
var (interpreterPaths, userPaths) = PythonLibraryPath.ClassifyPaths(Root, FileSystem, paths, Configuration.SearchPaths);
var (interpreterPaths, userPaths) = PythonLibraryPath.ClassifyPaths(Root, FileSystem, paths, _userConfiguredPaths);

InterpreterPaths = interpreterPaths.Select(p => p.Path);
_userPaths = userPaths.Select(p => p.Path);
UserPaths = userPaths.Select(p => p.Path);

if (Log != null) {
Log.Log(TraceEventType.Information, "Interpreter search paths:");
Expand All @@ -210,12 +210,21 @@ private async Task ReloadSearchPaths(CancellationToken cancellationToken = defau
}

Log.Log(TraceEventType.Information, "User search paths:");
foreach (var s in _userPaths) {
foreach (var s in UserPaths) {
Log.Log(TraceEventType.Information, $" {s}");
}
}
}

public bool SetUserConfiguredPaths(ImmutableArray<string> paths) {
if (paths.SequentiallyEquals(_userConfiguredPaths)) {
return false;
}

_userConfiguredPaths = paths;
return true;
}

public bool TryAddModulePath(in string path, in long fileSize, in bool allowNonRooted, out string fullModuleName)
=> PathResolver.TryAddModulePath(path, fileSize, allowNonRooted, out fullModuleName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Python.Analysis.Caching;
using Microsoft.Python.Analysis.Core.DependencyResolution;
using Microsoft.Python.Analysis.Core.Interpreter;
using Microsoft.Python.Analysis.Documents;
using Microsoft.Python.Analysis.Types;
using Microsoft.Python.Core;
using Microsoft.Python.Core.Collections;
Expand Down Expand Up @@ -55,6 +53,7 @@ protected ModuleResolutionBase(string root, IServiceContainer services) {
}

public ImmutableArray<string> InterpreterPaths { get; protected set; } = ImmutableArray<string>.Empty;
public ImmutableArray<string> UserPaths { get; protected set; } = ImmutableArray<string>.Empty;

/// <summary>
/// Path resolver providing file resolution in module imports.
Expand Down Expand Up @@ -83,7 +82,7 @@ public IPythonModule GetOrLoadModule(string name) {
public ModulePath FindModule(string filePath) {
var bestLibraryPath = string.Empty;

foreach (var p in Configuration.SearchPaths) {
foreach (var p in InterpreterPaths.Concat(UserPaths)) {
if (PathEqualityComparer.Instance.StartsWith(filePath, p)) {
if (p.Length > bestLibraryPath.Length) {
bestLibraryPath = p;
Expand Down
8 changes: 4 additions & 4 deletions src/Analysis/Ast/Test/AnalysisTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// permissions and limitations under the License.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
Expand Down Expand Up @@ -66,8 +65,9 @@ protected async Task<IServiceManager> CreateServicesAsync(string root, Interpret
configuration.AssertInstalled();
stubCacheFolderPath = stubCacheFolderPath ?? TestData.GetAstAnalysisCachePath(configuration.Version, true);
Trace.TraceInformation("Cache Path: " + stubCacheFolderPath);
configuration.SearchPaths = searchPaths ?? new[] { GetAnalysisTestDataFilesPath() };
configuration.TypeshedPath = TestData.GetDefaultTypeshedPath();

searchPaths = searchPaths ?? new[] { GetAnalysisTestDataFilesPath() };
var typeshedPath = TestData.GetDefaultTypeshedPath();

sm = sm ?? CreateServiceManager();

Expand All @@ -84,7 +84,7 @@ protected async Task<IServiceManager> CreateServicesAsync(string root, Interpret
sm.AddService(analyzer);

TestLogger.Log(TraceEventType.Information, "Create PythonInterpreter");
var interpreter = await PythonInterpreter.CreateAsync(configuration, root, sm);
var interpreter = await PythonInterpreter.CreateAsync(configuration, root, sm, typeshedPath, searchPaths.ToImmutableArray());
sm.AddService(interpreter);

TestLogger.Log(TraceEventType.Information, "Create RunningDocumentTable");
Expand Down
20 changes: 0 additions & 20 deletions src/Analysis/Core/Impl/Interpreter/InterpreterConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,6 @@ private InterpreterConfiguration(IReadOnlyDictionary<string, object> properties)
} catch (Exception ex) when (ex is ArgumentException || ex is FormatException) {
Version = new Version();
}
if (properties.TryGetValue(nameof(SearchPaths), out object o)) {
var sp = new List<string>();
if (o is string s) {
sp.AddRange(s.Split(';'));
} else if (o is IEnumerable<string> ss) {
sp.AddRange(ss);
}
SearchPaths = sp.ToArray();
}
}

public void WriteToDictionary(IDictionary<string, object> properties) {
Expand All @@ -83,7 +74,6 @@ public void WriteToDictionary(IDictionary<string, object> properties) {
if (Version != null) {
properties[nameof(Version)] = Version.ToString();
}
properties[nameof(SearchPaths)] = SearchPaths.ToArray();
}

/// <summary>
Expand Down Expand Up @@ -163,16 +153,6 @@ public void SwitchToFullDescription() {
/// </summary>
public string SitePackagesPath { get; }

/// <summary>
/// The fixed search paths of the interpreter.
/// </summary>
public IReadOnlyList<string> SearchPaths { get; set; } = Array.Empty<string>();

/// <summary>
/// Typeshed root folder.
/// </summary>
public string TypeshedPath { get; set; }

public static bool operator ==(InterpreterConfiguration x, InterpreterConfiguration y)
=> x?.Equals(y) ?? ReferenceEquals(y, null);
public static bool operator !=(InterpreterConfiguration x, InterpreterConfiguration y)
Expand Down
Loading