From 8bca56b1fa4ab8b282ae6491de25525c90aa9efe Mon Sep 17 00:00:00 2001 From: MikhailArkhipov Date: Fri, 1 Mar 2019 09:51:05 -0800 Subject: [PATCH 1/3] Fix #668 (partial) --- .../Analyzer/Handlers/ConditionalHandler.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Handlers/ConditionalHandler.cs b/src/Analysis/Ast/Impl/Analyzer/Handlers/ConditionalHandler.cs index cb41801b9..b104acb94 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Handlers/ConditionalHandler.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Handlers/ConditionalHandler.cs @@ -66,24 +66,6 @@ public bool HandleIf(IfStatement node) { someRecognized = true; } } - - // Handle basic check such as - // if isinstance(value, type): - // return value - // by assigning type to the value unless clause is raising exception. - var ce = node.Tests.FirstOrDefault()?.Test as CallExpression; - if (ce?.Target is NameExpression ne && ne.Name == @"isinstance" && ce.Args.Count == 2) { - var nex = ce.Args[0].Expression as NameExpression; - var name = nex?.Name; - var typeName = (ce.Args[1].Expression as NameExpression)?.Name; - if (name != null && typeName != null) { - var typeId = typeName.GetTypeId(); - if (typeId != BuiltinTypeId.Unknown) { - var t = new PythonType(typeName, Module, string.Empty, LocationInfo.Empty, typeId); - Eval.DeclareVariable(name, t, VariableSource.Declaration, nex); - } - } - } return !someRecognized; } From 01be1749a27f74969332dc08b046e7bb66d003e5 Mon Sep 17 00:00:00 2001 From: MikhailArkhipov Date: Mon, 4 Mar 2019 13:35:12 -0800 Subject: [PATCH 2/3] Fix requests test --- src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs b/src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs index 510661e45..fedc05ad0 100644 --- a/src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs +++ b/src/Analysis/Ast/Impl/Extensions/PythonTypeExtensions.cs @@ -30,10 +30,9 @@ public static bool IsGeneric(this IPythonType value) public static void TransferDocumentationAndLocation(this IPythonType s, IPythonType d) { if (s != d && s is PythonType src && d is PythonType dst) { - dst.TrySetTypeId(src.TypeId); var documentation = src.Documentation; if (!string.IsNullOrEmpty(documentation)) { - dst.SetDocumentationProvider(_ => documentation); + dst.SetDocumentation(documentation); } dst.SetLocation(src.Location); } From 026bca23ccc37f7d0dfdcdbe33d8abd46de29b24 Mon Sep 17 00:00:00 2001 From: MikhailArkhipov Date: Mon, 4 Mar 2019 14:07:33 -0800 Subject: [PATCH 3/3] Read file with retries since cached file may still be being written. --- src/Analysis/Ast/Impl/Modules/ModuleCache.cs | 2 +- src/Analysis/Ast/Impl/Modules/PythonModule.cs | 2 +- src/Analysis/Ast/Impl/Modules/SpecializedModule.cs | 8 ++++---- src/Analysis/Ast/Impl/Modules/StubPythonModule.cs | 3 ++- src/Core/Impl/Extensions/IOExtensions.cs | 12 ++++++++++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Analysis/Ast/Impl/Modules/ModuleCache.cs b/src/Analysis/Ast/Impl/Modules/ModuleCache.cs index 50da4c92a..685eea09b 100644 --- a/src/Analysis/Ast/Impl/Modules/ModuleCache.cs +++ b/src/Analysis/Ast/Impl/Modules/ModuleCache.cs @@ -139,7 +139,7 @@ public string ReadCachedModule(string filePath) { if (assemblyTime > cacheTime) { cachedFileOlderThanAssembly = true; } else { - return _fs.ReadAllText(cachePath); + return _fs.ReadTextWithRetry(cachePath); } } } diff --git a/src/Analysis/Ast/Impl/Modules/PythonModule.cs b/src/Analysis/Ast/Impl/Modules/PythonModule.cs index c19d091a3..7be31275e 100644 --- a/src/Analysis/Ast/Impl/Modules/PythonModule.cs +++ b/src/Analysis/Ast/Impl/Modules/PythonModule.cs @@ -212,7 +212,7 @@ protected virtual string LoadContent() { if (ContentState < State.Loading) { ContentState = State.Loading; try { - var code = FileSystem.ReadAllText(FilePath); + var code = FileSystem.ReadTextWithRetry(FilePath); ContentState = State.Loaded; return code; } catch (IOException) { } catch (UnauthorizedAccessException) { } diff --git a/src/Analysis/Ast/Impl/Modules/SpecializedModule.cs b/src/Analysis/Ast/Impl/Modules/SpecializedModule.cs index d9d03fa1d..14ee21fb1 100644 --- a/src/Analysis/Ast/Impl/Modules/SpecializedModule.cs +++ b/src/Analysis/Ast/Impl/Modules/SpecializedModule.cs @@ -13,9 +13,9 @@ // See the Apache Version 2.0 License for specific language governing // permissions and limitations under the License. -using System; -using System.IO; +using Microsoft.Python.Analysis.Specializations.Typing; using Microsoft.Python.Core; +using Microsoft.Python.Core.IO; namespace Microsoft.Python.Analysis.Modules { /// @@ -27,7 +27,7 @@ namespace Microsoft.Python.Analysis.Modules { /// Specialization is helpful when it is easier to express module members /// behavior to the analyzer in code. Example of specialization is 'typing' /// module. Specialized module can use actual library module as a source - /// of documentation for its members. See . + /// of documentation for its members. See . /// public abstract class SpecializedModule : PythonModule { protected SpecializedModule(string name, string modulePath, IServiceContainer services) @@ -35,7 +35,7 @@ protected SpecializedModule(string name, string modulePath, IServiceContainer se protected override string LoadContent() { // Exceptions are handled in the base - return FileSystem.FileExists(FilePath) ? FileSystem.ReadAllText(FilePath) : string.Empty; + return FileSystem.FileExists(FilePath) ? FileSystem.ReadTextWithRetry(FilePath) : string.Empty; } } } diff --git a/src/Analysis/Ast/Impl/Modules/StubPythonModule.cs b/src/Analysis/Ast/Impl/Modules/StubPythonModule.cs index 501f2cdf4..83fa0ffbe 100644 --- a/src/Analysis/Ast/Impl/Modules/StubPythonModule.cs +++ b/src/Analysis/Ast/Impl/Modules/StubPythonModule.cs @@ -15,6 +15,7 @@ using System; using Microsoft.Python.Core; +using Microsoft.Python.Core.IO; namespace Microsoft.Python.Analysis.Modules { /// @@ -30,7 +31,7 @@ public StubPythonModule(string moduleName, string stubPath, bool isTypeshed, ISe protected override string LoadContent() { // Exceptions are handled in the base - return FileSystem.FileExists(FilePath) ? FileSystem.ReadAllText(FilePath) : string.Empty; + return FileSystem.FileExists(FilePath) ? FileSystem.ReadTextWithRetry(FilePath) : string.Empty; } protected override string[] GetScrapeArguments(IPythonInterpreter factory) => Array.Empty(); diff --git a/src/Core/Impl/Extensions/IOExtensions.cs b/src/Core/Impl/Extensions/IOExtensions.cs index cfabc6cc4..4342a6506 100644 --- a/src/Core/Impl/Extensions/IOExtensions.cs +++ b/src/Core/Impl/Extensions/IOExtensions.cs @@ -109,6 +109,18 @@ public static FileStream OpenWithRetry(this IFileSystem fs, string file, FileMod return null; } + public static string ReadTextWithRetry(this IFileSystem fs, string file) { + // Retry for up to one second + for (var retries = 100; retries > 0; --retries) { + try { + return fs.ReadAllText(file); + } catch (UnauthorizedAccessException) { + Thread.Sleep(10); + } + } + return null; + } + public static void WriteTextWithRetry(this IFileSystem fs, string filePath, string text) { try { using (var stream = fs.OpenWithRetry(filePath, FileMode.Create, FileAccess.Write, FileShare.Read)) {