public async Task ReloadAsync(CancellationToken cancellationToken = default) { ModuleCache = new ModuleCache(_interpreter, _services); _pathResolver = new PathResolver(_interpreter.LanguageVersion); var addedRoots = _pathResolver.SetRoot(_root); ReloadModulePaths(addedRoots); var interpreterPaths = await GetSearchPathsAsync(cancellationToken); addedRoots = _pathResolver.SetInterpreterSearchPaths(interpreterPaths); ReloadModulePaths(addedRoots); addedRoots = _pathResolver.SetUserSearchPaths(_interpreter.Configuration.SearchPaths); ReloadModulePaths(addedRoots); }
internal async Task LoadBuiltinTypesAsync(CancellationToken cancellationToken = default) { // Add names from search paths await ReloadAsync(cancellationToken); // Initialize built-in var moduleName = BuiltinTypeId.Unknown.GetModuleName(_interpreter.LanguageVersion); var modulePath = ModuleCache.GetCacheFilePath(_interpreter.Configuration.InterpreterPath ?? "python.exe"); var b = new BuiltinsPythonModule(moduleName, modulePath, _services); _modules[BuiltinModuleName] = BuiltinsModule = b; await b.LoadAndAnalyzeAsync(cancellationToken); // Add built-in module names var builtinModuleNamesMember = BuiltinsModule.GetAnyMember("__builtin_module_names__"); if (builtinModuleNamesMember.TryGetConstant <string>(out var s)) { var builtinModuleNames = s.Split(',').Select(n => n.Trim()); _pathResolver.SetBuiltins(builtinModuleNames); } }
private async Task <TryImportModuleResult> TryImportModuleAsync(string name, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(name)) { return(TryImportModuleResult.ModuleNotFound); } if (name == BuiltinModuleName) { return(new TryImportModuleResult(BuiltinsModule)); } Debug.Assert(!name.EndsWithOrdinal("."), $"{name} should not end with '.'"); // Return any existing module if (_modules.TryGetValue(name, out var module) && module != null) { if (module is SentinelModule) { // TODO: we can't just wait here or we hang. There are two cases: // a. Recursion on the same analysis chain (A -> B -> A) // b. Call from another chain (A -> B -> C and D -> B -> E). // TODO: Both should be resolved at the dependency chain level. _log?.Log(TraceEventType.Warning, $"Recursive import: {name}"); } return(new TryImportModuleResult(module)); } // Set up a sentinel so we can detect recursive imports var sentinelValue = new SentinelModule(name, _services); if (!_modules.TryAdd(name, sentinelValue)) { // Try to get the new module, in case we raced with a .Clear() if (_modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(new TryImportModuleResult(module)); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceEventType.Warning, $"Retry import: {name}"); return(TryImportModuleResult.NeedRetry); } // Do normal searches try { module = await ImportFromSearchPathsAsync(name, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { _log?.Log(TraceEventType.Error, $"Import timeout {name}"); return(TryImportModuleResult.Timeout); } module = module ?? await ModuleCache.ImportFromCacheAsync(name, cancellationToken); // Replace our sentinel if (!_modules.TryUpdate(name, module, sentinelValue)) { // Try to get the new module, in case we raced if (_modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(new TryImportModuleResult(module)); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceEventType.Warning, $"Retry import: {name}"); return(TryImportModuleResult.NeedRetry); } return(new TryImportModuleResult(module)); }