Fixed unresolved attributes of namedtuple classes (PY-4349)

This commit is contained in:
Andrey Vlasovskikh
2012-09-12 20:46:24 +04:00
parent 01ab4059b9
commit 0f2dcaad3d
7 changed files with 1171 additions and 24 deletions
+35 -1
View File
@@ -24,7 +24,7 @@ but seemingly no one uses them in C extensions yet anyway.
# * re.search-bound, ~30% time, in likes of builtins and _gtk with complex docstrings.
# None of this can seemingly be easily helped. Maybe there's a simpler and faster parser library?
VERSION = "1.117" # Must be a number-dot-number string, updated with each change that affects generated skeletons
VERSION = "1.118" # Must be a number-dot-number string, updated with each change that affects generated skeletons
# Note: DON'T FORGET TO UPDATE!
import sys
@@ -2083,6 +2083,40 @@ class __generator(object):
"""
self.classes_buf.out(0, txt)
# Fake <type 'namedtuple'>
if version[0] >= 3 or (version[0] == 2 and version[1] >= 6):
namedtuple_text = """
class __namedtuple(tuple):
'''A mock base class for named tuples.'''
__slots__ = ()
_fields = ()
def __new__(cls, *args, **kwargs):
'Create a new instance of the named tuple.'
return tuple.__new__(cls, *args)
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new named tuple object from a sequence or iterable.'
return new(cls, iterable)
def __repr__(self):
return ''
def _asdict(self):
'Return a new dict which maps field types to their values.'
return {}
def _replace(self, **kwargs):
'Return a new named tuple object replacing specified fields with new values.'
return self
def __getnewargs__(self):
return tuple(self)
"""
self.classes_buf.out(0, namedtuple_text)
else:
self.classes_buf.out(0, "# no classes")
#
+1 -1
View File
@@ -6,7 +6,7 @@
(default) 1.92 # anything not explicitly marked
(built-in) 1.117 # skeletons of all built-in modules are built together
(built-in) 1.118 # skeletons of all built-in modules are built together
# Note: modules like itertools, etc are "(built-in)" and are ignored if given separately
_fileio 1.101
@@ -40,6 +40,7 @@ public class PyNames {
public static final String FAKE_OLD_BASE = "___Classobj";
public static final String FAKE_GENERATOR = "__generator";
public static final String FAKE_NAMEDTUPLE = "__namedtuple";
public static final String FUTURE_MODULE = "__future__";
public static final String UNICODE_LITERALS = "unicode_literals";
@@ -1,6 +1,5 @@
package com.jetbrains.python.codeInsight.stdlib;
import com.google.common.collect.ImmutableSet;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
@@ -30,9 +29,6 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
private final PsiElement myDeclaration;
private final List<String> myFields;
private static final ImmutableSet<String> ourClassMembers = ImmutableSet.of("_fields", "_make");
private static final ImmutableSet<String> ourInstanceMembers = ImmutableSet.of("_asdict", "_replace");
public PyNamedTupleType(PyClass tupleClass, PsiElement declaration, String name, List<String> fields, boolean isDefinition) {
super(tupleClass, isDefinition);
myDeclaration = declaration;
@@ -50,24 +46,12 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
if (classMembers != null && !classMembers.isEmpty()) {
return classMembers;
}
if (hasField(name)) {
if (myFields.contains(name)) {
return Collections.singletonList(new RatedResolveResult(1000, new PyElementImpl(myDeclaration.getNode())));
}
return Collections.emptyList();
}
private boolean hasField(String name) {
if (myFields.contains(name)) {
return true;
}
if (myDefinition) {
return ourClassMembers.contains(name);
}
else {
return ourInstanceMembers.contains(name);
}
}
@Override
public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) {
List<Object> result = new ArrayList<Object>();
@@ -75,9 +59,6 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
for (String field : myFields) {
result.add(LookupElementBuilder.create(field));
}
for (String s : myDefinition ? ourClassMembers : ourInstanceMembers) {
result.add(LookupElementBuilder.create(s));
}
return ArrayUtil.toObjectArray(result);
}
@@ -128,7 +109,7 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
}
}
if (fieldNames != null) {
PyClass tuple = PyBuiltinCache.getInstance(call).getClass(PyNames.TUPLE);
PyClass tuple = PyBuiltinCache.getInstance(call).getClass(PyNames.FAKE_NAMEDTUPLE);
if (tuple != null) {
return new PyNamedTupleType(tuple, call, name, fieldNames, true);
}
@@ -1,7 +1,7 @@
# encoding: utf-8
# module builtins
# from (built-in)
# by generator 1.117
# by generator 1.118
"""
Built-in functions, exceptions, and other objects.
@@ -5193,6 +5193,36 @@ class __generator(object):
'''Used to raise an exception inside the generator.'''
pass
class __namedtuple(tuple):
'''A mock base class for named tuples.'''
__slots__ = ()
_fields = ()
def __new__(cls, *args, **kwargs):
'Create a new instance of the named tuple.'
return tuple.__new__(cls, *args)
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new named tuple object from a sequence or iterable.'
return new(cls, iterable)
def __repr__(self):
return ''
def _asdict(self):
'Return a new dict which maps field types to their values.'
return {}
def _replace(self, **kwargs):
'Return a new named tuple object replacing specified fields with new values.'
return self
def __getnewargs__(self):
return tuple(self)
# variables with complex values
Ellipsis = None # (!) real value is ''
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
from collections import namedtuple
Point = namedtuple('Point', 'x y')
p = Point(1, 2)
# Fields and unpacking
x, y = p
x, y, z = p
print(p.x, p.y, p.<warning descr="Unresolved attribute reference 'z' for class 'Point'">z</warning>)
print(Point.x, Point.y, Point.<warning descr="Unresolved attribute reference 'z' for class 'Point'">z</warning>)
# Tuple attributes
print(p.count(1), p.__class__, p.__add__((1, 2)))
# Named tuple attribute
print(Point.__slots__, Point._fields)
print(p.__module__, p.__slots__)
print(p._asdict(), p._fields, p._replace(x=42))