public async Task NestedClasses() { const string code = @" x = 'str' class A: def methodA(self): return True class B: x: int class C: def __init__(self): self.y = 1 def methodC(self): return False def methodB1(self): return self.C() def methodB2(self): return self.C().y c = B().methodB1() "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); var json = ToJson(model); Baseline.CompareToFile(BaselineFileName, json); }
public async Task PositionalOnly() { const string code = @" x = 'str' class C: x: int def __init__(self): self.y = 1 def method(self, x, /, y=True): return func() @property def prop(self) -> int: return x def func(): return 2.0 c = C() "; var analysis = await GetAnalysisAsync(code, PythonVersions.Required_Python38X); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }
public async Task Requests() { const string code = @" import requests x = requests.get('microsoft.com') "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var v = analysis.GlobalScope.Variables["requests"]; v.Should().NotBeNull(); if (v.Value.GetPythonType <IPythonModule>().ModuleType == ModuleType.Unresolved) { Assert.Inconclusive("'requests' package is not installed."); } var rq = analysis.Document.Interpreter.ModuleResolution.GetImportedModule("requests"); var model = ModuleModel.FromAnalysis(rq.Analysis, Services, AnalysisCachingLevel.Library); var u = model.UniqueId; u.Should().Contain("(").And.EndWith(")"); var open = u.IndexOf('('); // Verify this looks like a version. new Version(u.Substring(open + 1, u.IndexOf(')') - open - 1)); await CompareBaselineAndRestoreAsync(model, rq); }
public async Task SmokeTest() { const string code = @" x = 'str' class C: x: int def __init__(self): self.y = 1 def method(self): return func() @property def prop(self) -> int: return x def func(): return 2.0 c = C() "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); var json = ToJson(model); Baseline.CompareToFile(BaselineFileName, json); }
public async Task GenericClass() { const string code = @" from typing import Generic, TypeVar, Dict K = TypeVar('K') V = TypeVar('V') class A(Generic[K, V], Dict[K, V]): def key(self) -> K: return K def value(self): return V x = A(1, 'a') "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); //var json = ToJson(model); //Baseline.CompareToFile(BaselineFileName, json); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }
public async Task MemberLocations() { const string code = @" x = 'str' def sum(a, b): return a + b class B: x: int class C: def __init__(self): pass def methodC(self): pass @property def propertyB(self): return 1 def methodB2(self): return 2 "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); //var json = ToJson(model); //Baseline.CompareToFile(BaselineFileName, json); using (var dbModule = new PythonDbModule(model, analysis.Document.FilePath, Services)) { dbModule.Construct(model); var sum = dbModule.GetMember("sum") as IPythonFunctionType; sum.Should().NotBeNull(); sum.Definition.Span.Should().Be(4, 5, 4, 8); var b = dbModule.GetMember("B") as IPythonClassType; b.Should().NotBeNull(); b.Definition.Span.Should().Be(7, 7, 7, 8); var c = b.GetMember("C") as IPythonClassType; c.Should().NotBeNull(); c.Definition.Span.Should().Be(10, 11, 10, 12); var methodC = c.GetMember("methodC") as IPythonFunctionType; methodC.Should().NotBeNull(); methodC.Definition.Span.Should().Be(13, 13, 13, 20); var propertyB = b.GetMember("propertyB") as IPythonPropertyType; propertyB.Should().NotBeNull(); propertyB.Definition.Span.Should().Be(17, 9, 17, 18); var methodB2 = b.GetMember("methodB2") as IPythonFunctionType; methodB2.Should().NotBeNull(); methodB2.Definition.Span.Should().Be(20, 9, 20, 17); } }
internal async Task <ModuleModel> GetModelAsync(string code) { var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); model.FilePath = null; return(model); }
private void StoreModuleAnalysis(IDocumentAnalysis analysis, CancellationToken cancellationToken = default) { var cachingLevel = GetCachingLevel(); if (cachingLevel == AnalysisCachingLevel.None) { return; } var model = ModuleModel.FromAnalysis(analysis, _services, cachingLevel); if (model == null) { // Caching level setting does not permit this module to be persisted. return; } Exception ex = null; for (var retries = 50; retries > 0; --retries) { lock (_lock) { cancellationToken.ThrowIfCancellationRequested(); try { if (!_fs.DirectoryExists(_databaseFolder)) { _fs.CreateDirectory(_databaseFolder); } cancellationToken.ThrowIfCancellationRequested(); using (var db = new LiteDatabase(Path.Combine(_databaseFolder, $"{model.UniqueId}.db"))) { var modules = db.GetCollection <ModuleModel>("modules"); modules.Upsert(model); return; } } catch (Exception ex1) when(ex1 is IOException || ex1 is UnauthorizedAccessException) { ex = ex1; Thread.Sleep(10); } catch (Exception ex2) { ex = ex2; break; } } } if (ex != null) { _log?.Log(System.Diagnostics.TraceEventType.Warning, $"Unable to write analysis of {model.Name} to database. Exception {ex.Message}"); if (ex.IsCriticalException()) { throw ex; } } }
public async Task Builtins() { var analysis = await GetAnalysisAsync(string.Empty); var builtins = analysis.Document.Interpreter.ModuleResolution.BuiltinsModule; var model = ModuleModel.FromAnalysis(builtins.Analysis, Services, AnalysisCachingLevel.Library); var json = ToJson(model); Baseline.CompareToFile(BaselineFileName, json); var dbModule = new PythonDbModule(model, null, Services); dbModule.Should().HaveSameMembersAs(builtins); }
public async Task StoreModuleAnalysisAsync(IDocumentAnalysis analysis, bool immediate = false, CancellationToken cancellationToken = default) { var cachingLevel = GetCachingLevel(); if (cachingLevel == AnalysisCachingLevel.None) { return; } var model = await Task.Run(() => ModuleModel.FromAnalysis(analysis, _services, cachingLevel), cancellationToken); if (model != null && !cancellationToken.IsCancellationRequested) { await _cacheWriter.EnqueueModel(model, immediate, cancellationToken); } }
private async Task TestModule(string name) { var analysis = await GetAnalysisAsync($"import {name}", PythonVersions.Python37_x64); var m = analysis.Document.Interpreter.ModuleResolution.GetImportedModule(name); if (m == null || m.ModuleType == ModuleType.Unresolved) { Assert.Inconclusive($"Module {name} is not installed or otherwise could not be imported."); return; } var model = ModuleModel.FromAnalysis(m.Analysis, Services, AnalysisCachingLevel.Library); model.Should().NotBeNull($"Module {name} is either not installed or cannot be cached"); await CompareBaselineAndRestoreAsync(model, m); }
public async Task ClassesWithSuper() { const string code = @" class A: def methodA(self): return True class B(A): def methodB(self): return super() "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }
public async Task PrivateMembers() { const string code = @" class A: _x = 1 def _methodA(self): return True @classmethod def _methodB(self): return True "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); await CompareBaselineAndRestoreAsync(model, analysis.Document); }
public async Task ClassOwnDocumentation() { const string code = @" class A: '''class A doc''' class B(A): def __init__(self): '''__init__ doc''' return "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); var json = ToJson(model); // In JSON, class A should have 'class A doc' documentation while B should have none. Baseline.CompareToFile(BaselineFileName, json); }
public async Task VersionHandling(bool is3x) { const string code = @" if sys.version_info >= (3, 0): def func(a, b, c): ... else: def func(a): ... "; var analysis = await GetAnalysisAsync(code, is3x?PythonVersions.LatestAvailable3X : PythonVersions.LatestAvailable2X); analysis.Should().HaveFunction("func") .Which.Should().HaveSingleOverload() .Which.Should().HaveParameters(is3x ? new[] { "a", "b", "c" } : new[] { "a" }); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); var json = ToJson(model); Baseline.CompareToFile(GetBaselineFileNameWithSuffix(is3x ? "3" : "2"), json); }
public async Task ForwardDeclarations() { const string code = @" x = 'str' class A: def methodA1(self): return B() def methodA2(self): return func() class B: class C: def methodC(self): return func() def methodB1(self): def a(): return 1 return a def func(): return 1 a = B().methodB1() b = A().methodA1() "; var analysis = await GetAnalysisAsync(code); analysis.Should().HaveVariable("a").Which.Should().HaveType("a"); analysis.Should().HaveVariable("b").Which.Should().HaveType("B"); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); //var json = ToJson(model); //Baseline.CompareToFile(BaselineFileName, json); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }
public async Task Logging() { const string code = @" import logging logging.critical() "; var analysis = await GetAnalysisAsync(code); var logging = analysis.Document.Interpreter.ModuleResolution.GetImportedModule("logging"); var model = ModuleModel.FromAnalysis(logging.Analysis, Services, AnalysisCachingLevel.Library); await CompareRestoreAsync(model, logging); using (var m = CreateDbModule(model, logging.FilePath)) { var critical = m.GetMember("critical") as IPythonFunctionType; critical.Should().NotBeNull(); var span = critical.Definition.Span; span.Start.Line.Should().BeGreaterThan(1000); (span.End.Column - span.Start.Column).Should().Be("critical".Length); } }
public async Task NamedTupleWithSuper() { const string code = @" from typing import NamedTuple Point = NamedTuple('Point', ['x', 'y']) class ChildPoint(Point): def foo(self): pass p = ChildPoint() x = super(ChildPoint, p) "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }
public async Task GlobalSuper() { const string code = @" class Baze: def baze_foo(self): pass class Derived(Baze): def foo(self): pass d = Derived() x = super(Derived, d) "; var analysis = await GetAnalysisAsync(code); var model = ModuleModel.FromAnalysis(analysis, Services, AnalysisCachingLevel.Library); using (var dbModule = CreateDbModule(model, analysis.Document.FilePath)) { dbModule.Should().HaveSameMembersAs(analysis.Document); } }