Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit 6bab760

Browse files
authored
Handle on-the-fly search path configuration changes, read search paths from config directly (microsoft#1492)
* Remove SearchPaths and TypeshedPath from Interpreter, move search path logic into module resolution * Move path processing into config change, with unfortunate extra reload * Cleanup usings * Eliminate nulls, since they aren't useful * Move initialization logic from initialize to initialized, and do an RPC call to get the user search paths instead of reloading, bring back searchPaths for full backwards compat * Cleanups * Null checks * Prevent errors on null settings or when the client doesn't implement workspace/configuration * Formatting * Replace IReadOnlyList with ImmutableArray where possible * Eliminate IReadOnlyList * Remove unused default/optional parameter
1 parent 55f999c commit 6bab760

File tree

12 files changed

+219
-108
lines changed

12 files changed

+219
-108
lines changed

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using Microsoft.Python.Analysis.Specializations.Typing;
2424
using Microsoft.Python.Analysis.Types;
2525
using Microsoft.Python.Core;
26+
using Microsoft.Python.Core.Collections;
2627
using Microsoft.Python.Core.Services;
2728
using Microsoft.Python.Parsing;
2829

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

46-
private async Task InitializeAsync(string root, IServiceManager sm, CancellationToken cancellationToken = default) {
47+
private async Task InitializeAsync(
48+
string root,
49+
IServiceManager sm,
50+
string typeshedPath,
51+
ImmutableArray<string> userConfiguredPaths,
52+
CancellationToken cancellationToken
53+
) {
4754
cancellationToken.ThrowIfCancellationRequested();
4855

4956
sm.AddService(this);
50-
_moduleResolution = new MainModuleResolution(root, sm);
51-
_stubResolution = new TypeshedResolution(Configuration.TypeshedPath, sm);
52-
57+
_moduleResolution = new MainModuleResolution(root, sm, userConfiguredPaths);
58+
_stubResolution = new TypeshedResolution(typeshedPath, sm);
59+
5360
await _stubResolution.ReloadAsync(cancellationToken);
5461
await _moduleResolution.ReloadAsync(cancellationToken);
5562
}
5663

57-
public static async Task<IPythonInterpreter> CreateAsync(InterpreterConfiguration configuration, string root, IServiceManager sm, CancellationToken cancellationToken = default) {
64+
public static async Task<IPythonInterpreter> CreateAsync(
65+
InterpreterConfiguration configuration,
66+
string root,
67+
IServiceManager sm,
68+
string typeshedPath = null,
69+
ImmutableArray<string> userConfiguredPaths = default,
70+
CancellationToken cancellationToken = default
71+
) {
5872
var pi = new PythonInterpreter(configuration);
59-
await pi.InitializeAsync(root, sm, cancellationToken);
73+
await pi.InitializeAsync(root, sm, typeshedPath, userConfiguredPaths, cancellationToken);
6074

6175
// Specialize typing
6276
TypingModule.Create(sm);

src/Analysis/Ast/Impl/Modules/Definitions/IModuleManagement.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
using System;
1717
using System.Collections.Generic;
18-
using System.Threading;
1918
using Microsoft.Python.Analysis.Caching;
2019
using Microsoft.Python.Analysis.Core.Interpreter;
2120
using Microsoft.Python.Analysis.Types;
@@ -25,7 +24,7 @@ namespace Microsoft.Python.Analysis.Modules {
2524
/// <summary>
2625
/// Represents module resolution and search subsystem.
2726
/// </summary>
28-
public interface IModuleManagement: IModuleResolution {
27+
public interface IModuleManagement : IModuleResolution {
2928
/// <summary>
3029
/// Builtins module name.
3130
/// </summary>
@@ -75,5 +74,7 @@ public interface IModuleManagement: IModuleResolution {
7574
/// Set of interpreter paths.
7675
/// </summary>
7776
ImmutableArray<string> InterpreterPaths { get; }
77+
78+
bool SetUserConfiguredPaths(ImmutableArray<string> paths);
7879
}
7980
}

src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ internal sealed class MainModuleResolution : ModuleResolutionBase, IModuleManage
4141
private readonly IUIService _ui;
4242
private IRunningDocumentTable _rdt;
4343

44-
private ImmutableArray<string> _userPaths = ImmutableArray<string>.Empty;
44+
private ImmutableArray<string> _userConfiguredPaths;
4545

46-
public MainModuleResolution(string root, IServiceContainer services)
46+
public MainModuleResolution(string root, IServiceContainer services, ImmutableArray<string> userConfiguredPaths)
4747
: base(root, services) {
48-
4948
_ui = services.GetService<IUIService>();
49+
_userConfiguredPaths = userConfiguredPaths;
5050
}
51-
51+
5252
public string BuiltinModuleName => BuiltinTypeId.Unknown.GetModuleName(Interpreter.LanguageVersion);
5353

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

174174
await ReloadSearchPaths(cancellationToken);
175175

176-
PathResolver = new PathResolver(Interpreter.LanguageVersion, Root, InterpreterPaths, _userPaths);
176+
PathResolver = new PathResolver(Interpreter.LanguageVersion, Root, InterpreterPaths, UserPaths);
177177

178178
var addedRoots = new HashSet<string> { Root };
179179
addedRoots.UnionWith(InterpreterPaths);
180-
addedRoots.UnionWith(_userPaths);
180+
addedRoots.UnionWith(UserPaths);
181181
ReloadModulePaths(addedRoots);
182182

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

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

203203
InterpreterPaths = interpreterPaths.Select(p => p.Path);
204-
_userPaths = userPaths.Select(p => p.Path);
204+
UserPaths = userPaths.Select(p => p.Path);
205205

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

212212
Log.Log(TraceEventType.Information, "User search paths:");
213-
foreach (var s in _userPaths) {
213+
foreach (var s in UserPaths) {
214214
Log.Log(TraceEventType.Information, $" {s}");
215215
}
216216
}
217217
}
218218

219+
public bool SetUserConfiguredPaths(ImmutableArray<string> paths) {
220+
if (paths.SequentiallyEquals(_userConfiguredPaths)) {
221+
return false;
222+
}
223+
224+
_userConfiguredPaths = paths;
225+
return true;
226+
}
227+
219228
public bool TryAddModulePath(in string path, in long fileSize, in bool allowNonRooted, out string fullModuleName)
220229
=> PathResolver.TryAddModulePath(path, fileSize, allowNonRooted, out fullModuleName);
221230

src/Analysis/Ast/Impl/Modules/Resolution/ModuleResolutionBase.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@
1717
using System.Collections.Generic;
1818
using System.IO;
1919
using System.Linq;
20-
using System.Threading;
2120
using Microsoft.Python.Analysis.Caching;
2221
using Microsoft.Python.Analysis.Core.DependencyResolution;
2322
using Microsoft.Python.Analysis.Core.Interpreter;
24-
using Microsoft.Python.Analysis.Documents;
2523
using Microsoft.Python.Analysis.Types;
2624
using Microsoft.Python.Core;
2725
using Microsoft.Python.Core.Collections;
@@ -55,6 +53,7 @@ protected ModuleResolutionBase(string root, IServiceContainer services) {
5553
}
5654

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

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

86-
foreach (var p in Configuration.SearchPaths) {
85+
foreach (var p in InterpreterPaths.Concat(UserPaths)) {
8786
if (PathEqualityComparer.Instance.StartsWith(filePath, p)) {
8887
if (p.Length > bestLibraryPath.Length) {
8988
bestLibraryPath = p;

src/Analysis/Ast/Test/AnalysisTestBase.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
// permissions and limitations under the License.
1515

1616
using System;
17-
using System.Collections.Generic;
1817
using System.Diagnostics;
1918
using System.IO;
2019
using System.Threading;
@@ -66,8 +65,9 @@ protected async Task<IServiceManager> CreateServicesAsync(string root, Interpret
6665
configuration.AssertInstalled();
6766
stubCacheFolderPath = stubCacheFolderPath ?? TestData.GetAstAnalysisCachePath(configuration.Version, true);
6867
Trace.TraceInformation("Cache Path: " + stubCacheFolderPath);
69-
configuration.SearchPaths = searchPaths ?? new[] { GetAnalysisTestDataFilesPath() };
70-
configuration.TypeshedPath = TestData.GetDefaultTypeshedPath();
68+
69+
searchPaths = searchPaths ?? new[] { GetAnalysisTestDataFilesPath() };
70+
var typeshedPath = TestData.GetDefaultTypeshedPath();
7171

7272
sm = sm ?? CreateServiceManager();
7373

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

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

9090
TestLogger.Log(TraceEventType.Information, "Create RunningDocumentTable");

src/Analysis/Core/Impl/Interpreter/InterpreterConfiguration.cs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,6 @@ private InterpreterConfiguration(IReadOnlyDictionary<string, object> properties)
6262
} catch (Exception ex) when (ex is ArgumentException || ex is FormatException) {
6363
Version = new Version();
6464
}
65-
if (properties.TryGetValue(nameof(SearchPaths), out object o)) {
66-
var sp = new List<string>();
67-
if (o is string s) {
68-
sp.AddRange(s.Split(';'));
69-
} else if (o is IEnumerable<string> ss) {
70-
sp.AddRange(ss);
71-
}
72-
SearchPaths = sp.ToArray();
73-
}
7465
}
7566

7667
public void WriteToDictionary(IDictionary<string, object> properties) {
@@ -83,7 +74,6 @@ public void WriteToDictionary(IDictionary<string, object> properties) {
8374
if (Version != null) {
8475
properties[nameof(Version)] = Version.ToString();
8576
}
86-
properties[nameof(SearchPaths)] = SearchPaths.ToArray();
8777
}
8878

8979
/// <summary>
@@ -163,16 +153,6 @@ public void SwitchToFullDescription() {
163153
/// </summary>
164154
public string SitePackagesPath { get; }
165155

166-
/// <summary>
167-
/// The fixed search paths of the interpreter.
168-
/// </summary>
169-
public IReadOnlyList<string> SearchPaths { get; set; } = Array.Empty<string>();
170-
171-
/// <summary>
172-
/// Typeshed root folder.
173-
/// </summary>
174-
public string TypeshedPath { get; set; }
175-
176156
public static bool operator ==(InterpreterConfiguration x, InterpreterConfiguration y)
177157
=> x?.Equals(y) ?? ReferenceEquals(y, null);
178158
public static bool operator !=(InterpreterConfiguration x, InterpreterConfiguration y)

0 commit comments

Comments
 (0)