} // For de-serializer from JSON protected CallableModel(IPythonType callable, IServiceContainer services) { var functions = new List <FunctionModel>(); var classes = new List <ClassModel>(); foreach (var name in callable.GetMemberNames()) { var m = callable.GetMember(name); // Only take members from this class, skip members from bases. using (_processing.Push(m, out var reentered)) { if (reentered) { continue; } switch (m) { case IPythonFunctionType ft1 when ft1.IsLambda(): break; case IPythonFunctionType ft2: functions.Add(new FunctionModel(ft2, services)); break; case IPythonClassType cls: classes.Add(new ClassModel(cls, services)); break; } } } Id = callable.Name.GetStableHash(); Name = callable.Name; DeclaringModuleId = callable.DeclaringModule.GetUniqueId(services); QualifiedName = callable.QualifiedName; Documentation = callable.Documentation; Classes = classes.ToArray(); Functions = functions.ToArray(); IndexSpan = callable.Location.IndexSpan.ToModel(); Attributes = FunctionAttributes.Normal; if (callable.IsAbstract) { Attributes |= FunctionAttributes.Abstract; } if (callable is IPythonFunctionType ft) { if (ft.IsClassMethod) { Attributes |= FunctionAttributes.ClassMethod; } if (ft.IsStatic) { Attributes |= FunctionAttributes.Static; } } }
public static void AddMemberReference(this IPythonType type, string name, IExpressionEvaluator eval, Location location) { var m = type.GetMember(name); if (m is LocatedMember lm) { lm.AddReference(location); } else if (type is IPythonClassType cls) { using (eval.OpenScope(cls.DeclaringModule, cls.ClassDefinition)) { eval.LookupNameInScopes(name, out _, out var v, LookupOptions.Local); v?.AddReference(location); } } }
private static IEnumerable <IPythonFunction> GetTestCaseMembers(IPythonType cls, IModuleContext context) { var methodFunctions = cls.GetMemberNames(context).Select(n => cls.GetMember(context, n)) .OfType <IPythonFunction>() .ToArray(); var tests = methodFunctions.Where(v => v.Name.StartsWithOrdinal("test")); var runTest = methodFunctions.Where(v => v.Name.Equals("runTest")); if (tests.Any()) { return(tests); } else { return(runTest); } }
public static void AddMemberReference(this IPythonType type, string name, IExpressionEvaluator eval, Location location) { var m = type.GetMember(name); if (m is LocatedMember lm) { lm.AddReference(location); } else if (type is IPythonClassType cls) { using (eval.OpenScope(cls)) { eval.LookupNameInScopes(name, out _, out var v, LookupOptions.Local); v?.AddReference(location); } } else if (type is IPythonModule module && module.GlobalScope != null && module.GlobalScope.Variables.TryGetVariable(name, out var variable)) { variable.AddReference(location); } }
internal static IList <IPythonType> CalculateMro(IPythonType cls, HashSet <IPythonType> recursionProtection = null) { if (cls == null) { return(Array.Empty <IPythonType>()); } if (recursionProtection == null) { recursionProtection = new HashSet <IPythonType>(); } if (!recursionProtection.Add(cls)) { return(Array.Empty <IPythonType>()); } try { var mergeList = new List <List <IPythonType> > { new List <IPythonType>() }; var finalMro = new List <IPythonType> { cls }; var bases = (cls as AstPythonType)?.Bases ?? (cls.GetMember(null, "__bases__") as IPythonSequenceType)?.IndexTypes ?? Array.Empty <IPythonType>(); foreach (var b in bases) { var b_mro = new List <IPythonType>(); b_mro.AddRange(CalculateMro(b, recursionProtection)); mergeList.Add(b_mro); } while (mergeList.Any()) { // Next candidate is the first head that does not appear in // any other tails. var nextInMro = mergeList.FirstOrDefault(mro => { var m = mro.FirstOrDefault(); return(m != null && !mergeList.Any(m2 => m2.Skip(1).Contains(m))); })?.FirstOrDefault(); if (nextInMro == null) { // MRO is invalid, so return just this class return(new IPythonType[] { cls }); } finalMro.Add(nextInMro); // Remove all instances of that class from potentially being returned again foreach (var mro in mergeList) { mro.RemoveAll(ns => ns == nextInMro); } // Remove all lists that are now empty. mergeList.RemoveAll(mro => !mro.Any()); } return(finalMro); } finally { recursionProtection.Remove(cls); } }
/// <summary> /// Calculates MRO according to https://www.python.org/download/releases/2.3/mro/ /// </summary> internal static IReadOnlyList <IPythonType> CalculateMro(IPythonType type, HashSet <IPythonType> recursionProtection = null) { if (type == null) { return(Array.Empty <IPythonType>()); } recursionProtection = recursionProtection ?? new HashSet <IPythonType>(); if (!recursionProtection.Add(type)) { return(Array.Empty <IPythonType>()); } var bases = (type as IPythonClassType)?.Bases; if (bases == null) { var members = (type.GetMember("__bases__") as IPythonCollection)?.Contents ?? Array.Empty <IMember>(); bases = members.Select(m => m.GetPythonType()).ToArray(); } try { var mergeList = new List <List <IPythonType> > { new List <IPythonType>() }; var finalMro = new List <IPythonType> { type }; var mros = bases.Select(b => CalculateMro(b, recursionProtection).ToList()); mergeList.AddRange(mros); while (mergeList.Any()) { // Next candidate is the first head that does not appear in any other tails. var nextInMro = mergeList.FirstOrDefault(mro => { var m = mro.FirstOrDefault(); return(m != null && !mergeList.Any(m2 => m2.Skip(1).Contains(m))); })?.FirstOrDefault(); if (nextInMro == null) { // MRO is invalid, so return just this class return(new[] { type }); } finalMro.Add(nextInMro); // Remove all instances of that class from potentially being returned again foreach (var mro in mergeList) { mro.RemoveAll(ns => ns == nextInMro); } // Remove all lists that are now empty. mergeList.RemoveAll(mro => !mro.Any()); } return(finalMro); } finally { recursionProtection.Remove(type); } }
public IMember GetMember(IModuleContext context, string name) { return(_type.GetMember(context, name)); }
private void MergeClass(IVariable v, IPythonClassType sourceClass, IPythonType stubType, CancellationToken cancellationToken) { // Transfer documentation first so we get class documentation // that comes from the class definition win over one that may // come from __init__ during the member merge below. TransferDocumentationAndLocation(sourceClass, stubType); // Replace the class entirely since stub members may use generic types // and the class definition is important. We transfer missing members // from the original class to the stub. _eval.DeclareVariable(v.Name, v.Value, v.Source); // First pass: go through source class members and pick those // that are not present in the stub class. foreach (var name in sourceClass.GetMemberNames().ToArray()) { cancellationToken.ThrowIfCancellationRequested(); var sourceMember = sourceClass.GetMember(name); if (sourceMember.IsUnknown()) { continue; // Do not add unknowns to the stub. } var sourceMemberType = sourceMember?.GetPythonType(); if (sourceMemberType is IPythonClassMember cm && cm.DeclaringType != sourceClass) { continue; // Only take members from this class and not from bases. } if (!IsFromThisModuleOrSubmodules(sourceMemberType)) { continue; // Member does not come from module or its submodules. } var stubMember = stubType.GetMember(name); var stubMemberType = stubMember.GetPythonType(); // Get documentation from the current type, if any, since stubs // typically do not contain documentation while scraped code does. TransferDocumentationAndLocation(sourceMemberType, stubMemberType); // If stub says 'Any' but we have better type, use member from the original class. if (stubMember != null && !(stubType.DeclaringModule is TypingModule && stubType.Name == "Any")) { continue; // Stub already have the member, don't replace. } (stubType as PythonType)?.AddMember(name, stubMember, overwrite: true); } // Second pass: go through stub class members and if they don't have documentation // or location, check if source class has same member and fetch it from there. // The reason is that in the stub sometimes members are specified all in one // class while in source they may come from bases. Example: datetime. foreach (var name in stubType.GetMemberNames().ToArray()) { cancellationToken.ThrowIfCancellationRequested(); var stubMember = stubType.GetMember(name); if (stubMember.IsUnknown()) { continue; } var stubMemberType = stubMember.GetPythonType(); if (stubMemberType is IPythonClassMember cm && cm.DeclaringType != stubType) { continue; // Only take members from this class and not from bases. } var sourceMember = sourceClass.GetMember(name); if (sourceMember.IsUnknown()) { continue; } var sourceMemberType = sourceMember.GetPythonType(); if (sourceMemberType.Location.IsValid && !stubMemberType.Location.IsValid) { TransferDocumentationAndLocation(sourceMemberType, stubMemberType); } } }
public IMember GetMember(string name) => _type.GetMember(name);
public IMember GetMember(IModuleContext context, string name) => _sequenceType?.GetMember(context, name) ?? null;
public IMember GetMember(IModuleContext context, string name) => _type.GetMember(context, name);
public IMember GetMember(IModuleContext context, string name) => _lookupType?.GetMember(context, name) ?? null;