public async Task Mro() { using (var s = await CreateServicesAsync(null, null, null)) { var interpreter = s.GetService <IPythonInterpreter>(); var o = interpreter.GetBuiltinType(BuiltinTypeId.Object); var m = new SentinelModule("test", s); var location = new Location(m); var O = new PythonClassType("O", location); var A = new PythonClassType("A", location); var B = new PythonClassType("B", location); var C = new PythonClassType("C", location); var D = new PythonClassType("D", location); var E = new PythonClassType("E", location); var F = new PythonClassType("F", location); O.SetBases(new[] { o }); F.SetBases(new[] { O }); E.SetBases(new[] { O }); D.SetBases(new[] { O }); C.SetBases(new[] { D, F }); B.SetBases(new[] { D, E }); A.SetBases(new[] { B, C }); var mroA = PythonClassType.CalculateMro(A).Select(p => p.Name); mroA.Should().Equal("A", "B", "C", "D", "E", "F", "O", "object"); var mroB = PythonClassType.CalculateMro(B).Select(p => p.Name); mroB.Should().Equal("B", "D", "E", "O", "object"); var mroC = PythonClassType.CalculateMro(C).Select(p => p.Name); mroC.Should().Equal("C", "D", "F", "O", "object"); } }
private IPythonModule GetModule() { var mod = Volatile.Read(ref _module); if (mod != null) { return(mod); } foreach (var n in _importNames) { mod = _interpreter.ImportModule(n); if (mod != null) { Debug.Assert(!(mod is AstNestedPythonModule), "ImportModule should not return nested module"); break; } } if (mod == null) { mod = new SentinelModule(_importNames.FirstOrDefault() ?? "<unknown>", false); } return(Interlocked.CompareExchange(ref _module, mod, null) ?? mod); }
private IPythonModule GetModule() { var module = Volatile.Read(ref _module); if (module != null) { return(module); } module = _interpreter.ImportModule(Name); if (module != null) { Debug.Assert(!(module is AstNestedPythonModule), "ImportModule should not return nested module"); } if (module == null) { module = new SentinelModule(Name, false); } return(Interlocked.CompareExchange(ref _module, module, null) ?? module); }
public void AddUnimportableModule(string moduleName) { _modules[moduleName] = new SentinelModule(moduleName, false); }
public async Task <TryImportModuleResult> TryImportModuleAsync(string name, PathResolverSnapshot pathResolver, IReadOnlyList <string> typeStubPaths, bool mergeTypeStubPackages, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(name)) { return(TryImportModuleResult.ModuleNotFound); } Debug.Assert(!name.EndsWithOrdinal("."), $"{name} should not end with '.'"); // Handle builtins explicitly if (name == BuiltinModuleName) { Debug.Fail($"Interpreters must handle import {name} explicitly"); return(TryImportModuleResult.NotSupported); } // Return any existing module if (_modules.TryGetValue(name, out var module) && module != null) { if (module is SentinelModule sentinelModule) { // If we are importing this module on another thread, allow // time for it to complete. This does not block if we are // importing on the current thread or the module is not // really being imported. try { module = await sentinelModule.WaitForImportAsync(cancellationToken); } catch (OperationCanceledException) { _log?.Log(TraceLevel.Warning, "ImportTimeout", name); return(TryImportModuleResult.Timeout); } if (module is SentinelModule) { _log?.Log(TraceLevel.Warning, "RecursiveImport", name); } } return(new TryImportModuleResult(module)); } // Set up a sentinel so we can detect recursive imports var sentinelValue = new SentinelModule(name, true); 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(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } // Do normal searches if (!string.IsNullOrEmpty(_configuration?.InterpreterPath)) { try { module = ImportFromSearchPaths(name, pathResolver); } catch (OperationCanceledException) { _log?.Log(TraceLevel.Error, "ImportTimeout", name, "ImportFromSearchPaths"); return(TryImportModuleResult.Timeout); } } if (module == null) { module = _astModuleCache.ImportFromCache(name, _interpreter); } // Also search for type stub packages if enabled and we are not a blacklisted module if (module != null && typeStubPaths != null && module.Name != "typing") { var tsModule = ImportFromTypeStubs(module.Name, typeStubPaths, pathResolver); if (tsModule != null) { module = mergeTypeStubPackages ? AstPythonMultipleMembers.CombineAs <IPythonModule>(module, tsModule) : tsModule; } } // Replace our sentinel, or if we raced, get the current // value and abandon the one we just created. 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(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } sentinelValue.Complete(module); return(new TryImportModuleResult(module)); }
private IPythonModule ImportModuleOrRetry(string name, out bool retry) { retry = false; if (string.IsNullOrEmpty(name)) { return(null); } Debug.Assert(!name.EndsWith("."), $"{name} should not end with '.'"); // Handle builtins explicitly if (name == BuiltinModuleName) { if (_builtinModule == null) { _modules[BuiltinModuleName] = _builtinModule = new AstBuiltinsPythonModule(_factory.LanguageVersion); _builtinModuleNames = null; _builtinModule.Imported(this); var bmn = ((AstBuiltinsPythonModule)_builtinModule).GetAnyMember("__builtin_module_names") as AstPythonStringLiteral; _builtinModuleNames = bmn?.Value?.Split(',') ?? Array.Empty <string>(); } return(_builtinModule); } IPythonModule mod; // Return any existing module if (_modules.TryGetValue(name, out mod) && mod != null) { if (mod is SentinelModule smod) { // If we are importing this module on another thread, allow // time for it to complete. This does not block if we are // importing on the current thread or the module is not // really being imported. var newMod = smod.WaitForImport(5000); if (newMod is SentinelModule) { _log?.Log(TraceLevel.Warning, "RecursiveImport", name); mod = newMod; } else if (newMod == null) { _log?.Log(TraceLevel.Warning, "ImportTimeout", name); } else { mod = newMod; } } return(mod); } // Set up a sentinel so we can detect recursive imports var sentinalValue = new SentinelModule(name, true); if (!_modules.TryAdd(name, sentinalValue)) { // Try to get the new module, in case we raced with a .Clear() if (_modules.TryGetValue(name, out mod) && !(mod is SentinelModule)) { return(mod); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); retry = true; return(null); } // Do normal searches mod = ImportFromBuiltins(name) ?? ImportFromSearchPaths(name); // Replace our sentinel, or if we raced, get the current // value and abandon the one we just created. if (!_modules.TryUpdate(name, mod, sentinalValue)) { // Try to get the new module, in case we raced if (_modules.TryGetValue(name, out mod) && !(mod is SentinelModule)) { return(mod); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); retry = true; return(null); } sentinalValue.Complete(mod); sentinalValue.Dispose(); return(mod); }
public TryImportModuleResult TryImportModule( string name, out IPythonModule module, TryImportModuleContext context ) { module = null; if (string.IsNullOrEmpty(name)) { return(TryImportModuleResult.ModuleNotFound); } Debug.Assert(!name.EndsWithOrdinal("."), $"{name} should not end with '.'"); // Handle builtins explicitly if (name == BuiltinModuleName) { Debug.Fail($"Interpreters must handle import {name} explicitly"); return(TryImportModuleResult.NotSupported); } var modules = context?.ModuleCache; int importTimeout = context?.Timeout ?? 5000; SentinelModule sentinalValue = null; if (modules != null) { // Return any existing module if (modules.TryGetValue(name, out module) && module != null) { if (module is SentinelModule smod) { // If we are importing this module on another thread, allow // time for it to complete. This does not block if we are // importing on the current thread or the module is not // really being imported. var newMod = smod.WaitForImport(importTimeout); if (newMod is SentinelModule) { _log?.Log(TraceLevel.Warning, "RecursiveImport", name); module = newMod; } else if (newMod == null) { _log?.Log(TraceLevel.Warning, "ImportTimeout", name); module = null; return(TryImportModuleResult.Timeout); } else { module = newMod; } } return(TryImportModuleResult.Success); } // Set up a sentinel so we can detect recursive imports sentinalValue = new SentinelModule(name, true); if (!modules.TryAdd(name, sentinalValue)) { // Try to get the new module, in case we raced with a .Clear() if (modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(module == null ? TryImportModuleResult.ModuleNotFound : TryImportModuleResult.Success); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } } // Do normal searches if (!string.IsNullOrEmpty(Configuration?.InterpreterPath)) { var importTask = ImportFromSearchPathsAsync(name, context); if (importTask.Wait(importTimeout)) { module = importTask.Result; } else { _log?.Log(TraceLevel.Error, "ImportTimeout", name, "ImportFromSearchPaths"); module = null; } module = module ?? ImportFromBuiltins(name, context.BuiltinModule as AstBuiltinsPythonModule); } if (module == null) { module = ImportFromCache(name); } if (modules != null) { // Replace our sentinel, or if we raced, get the current // value and abandon the one we just created. if (!modules.TryUpdate(name, module, sentinalValue)) { // Try to get the new module, in case we raced if (modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(module == null ? TryImportModuleResult.ModuleNotFound : TryImportModuleResult.Success); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } sentinalValue.Complete(module); sentinalValue.Dispose(); } return(TryImportModuleResult.Success); }
public TryImportModuleResult TryImportModule( string name, out IPythonModule module, TryImportModuleContext context ) { module = null; if (string.IsNullOrEmpty(name)) { return(TryImportModuleResult.ModuleNotFound); } Debug.Assert(!name.EndsWithOrdinal("."), $"{name} should not end with '.'"); // Handle builtins explicitly if (name == BuiltinModuleName) { Debug.Fail($"Interpreters must handle import {name} explicitly"); return(TryImportModuleResult.NotSupported); } var modules = context?.ModuleCache; int importTimeout = context?.Timeout ?? 5000; SentinelModule sentinalValue = null; if (modules != null) { // Return any existing module if (modules.TryGetValue(name, out module) && module != null) { if (module is SentinelModule smod) { // If we are importing this module on another thread, allow // time for it to complete. This does not block if we are // importing on the current thread or the module is not // really being imported. var newMod = smod.WaitForImport(importTimeout); if (newMod is SentinelModule) { _log?.Log(TraceLevel.Warning, "RecursiveImport", name); module = newMod; } else if (newMod == null) { _log?.Log(TraceLevel.Warning, "ImportTimeout", name); module = null; return(TryImportModuleResult.Timeout); } else { module = newMod; } } return(TryImportModuleResult.Success); } // Set up a sentinel so we can detect recursive imports sentinalValue = new SentinelModule(name, true); if (!modules.TryAdd(name, sentinalValue)) { // Try to get the new module, in case we raced with a .Clear() if (modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(module == null ? TryImportModuleResult.ModuleNotFound : TryImportModuleResult.Success); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } } // Do normal searches if (!string.IsNullOrEmpty(Configuration?.InterpreterPath)) { var importTask = ImportFromSearchPathsAsync(name, context); if (importTask.Wait(importTimeout)) { module = importTask.Result; } else { _log?.Log(TraceLevel.Error, "ImportTimeout", name, "ImportFromSearchPaths"); module = null; } module = module ?? ImportFromBuiltins(name, context.BuiltinModule as AstBuiltinsPythonModule); } if (module == null) { module = ImportFromCache(name); } if (modules != null) { // Replace our sentinel, or if we raced, get the current // value and abandon the one we just created. if (!modules.TryUpdate(name, module, sentinalValue)) { // Try to get the new module, in case we raced if (modules.TryGetValue(name, out module) && !(module is SentinelModule)) { return(module == null ? TryImportModuleResult.ModuleNotFound : TryImportModuleResult.Success); } // If we reach here, the race is too complicated to recover // from. Signal the caller to try importing again. _log?.Log(TraceLevel.Warning, "RetryImport", name); return(TryImportModuleResult.NeedRetry); } sentinalValue.Complete(module); sentinalValue.Dispose(); } // Also search for type stub packages if enabled and we are not a blacklisted module if (module != null && module.Name != "typing") { // Note that this currently only looks in the typeshed package, as type stub // packages are not yet standardised so we don't know where to look. // The details will be in PEP 561. if (context.TypeStubPaths?.Any() == true) { var mtsp = FindModuleInSearchPath(context.TypeStubPaths, null, module.Name); if (mtsp.HasValue) { var mp = mtsp.Value; if (mp.IsCompiled) { Debug.Fail("Unsupported native module in typeshed"); } else { _log?.Log(TraceLevel.Verbose, "ImportTypeShed", mp.FullName, FastRelativePath(mp.SourceFile)); var tsModule = PythonModuleLoader.FromFile(context.Interpreter, mp.SourceFile, LanguageVersion, mp.FullName); if (tsModule != null) { if (context.MergeTypeStubPackages) { module = AstPythonMultipleModules.Combine(module, tsModule); } else { module = tsModule; } } } } } } return(module == null ? TryImportModuleResult.ModuleNotFound : TryImportModuleResult.Success); }