mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fixed unresolved attributes of namedtuple classes (PY-4349)
This commit is contained in:
@@ -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")
|
||||
#
|
||||
|
||||
@@ -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))
|
||||
Reference in New Issue
Block a user