mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 23:34:45 +08:00
Move __getattr__ and __getattribute__ logic to instance
Now getattr warnings might be wrong
This commit is contained in:
@@ -121,30 +121,10 @@ class NameFinder(object):
|
|||||||
self._string_name, self._context, names, self._position)
|
self._string_name, self._context, names, self._position)
|
||||||
return list(names)
|
return list(names)
|
||||||
|
|
||||||
def _check_getattr(self, inst):
|
|
||||||
"""Checks for both __getattr__ and __getattribute__ methods"""
|
|
||||||
# str is important, because it shouldn't be `Name`!
|
|
||||||
name = compiled.create_simple_object(self._inference_state, self._string_name)
|
|
||||||
|
|
||||||
# This is a little bit special. `__getattribute__` is in Python
|
|
||||||
# executed before `__getattr__`. But: I know no use case, where
|
|
||||||
# this could be practical and where Jedi would return wrong types.
|
|
||||||
# If you ever find something, let me know!
|
|
||||||
# We are inversing this, because a hand-crafted `__getattribute__`
|
|
||||||
# could still call another hand-crafted `__getattr__`, but not the
|
|
||||||
# other way around.
|
|
||||||
names = (inst.get_function_slot_names(u'__getattr__') or
|
|
||||||
inst.get_function_slot_names(u'__getattribute__'))
|
|
||||||
return inst.execute_function_slots(names, name)
|
|
||||||
|
|
||||||
def _names_to_types(self, names):
|
def _names_to_types(self, names):
|
||||||
values = ValueSet.from_sets(name.infer() for name in names)
|
values = ValueSet.from_sets(name.infer() for name in names)
|
||||||
|
|
||||||
debug.dbg('finder._names_to_types: %s -> %s', names, values)
|
debug.dbg('finder._names_to_types: %s -> %s', names, values)
|
||||||
if not names and self._context.is_instance() and not self._context.is_compiled():
|
|
||||||
# handling __getattr__ / __getattribute__
|
|
||||||
return self._check_getattr(self._context)
|
|
||||||
|
|
||||||
# Add isinstance and other if/assert knowledge.
|
# Add isinstance and other if/assert knowledge.
|
||||||
if not values and isinstance(self._name, tree.Name) and \
|
if not values and isinstance(self._name, tree.Name) and \
|
||||||
not self._name_context.is_instance() and not self._context.is_compiled():
|
not self._name_context.is_instance() and not self._context.is_compiled():
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from abc import abstractproperty
|
from abc import abstractproperty
|
||||||
|
|
||||||
|
from parso.python.tree import Name
|
||||||
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
@@ -309,6 +311,29 @@ class TreeInstance(AbstractInstanceValue):
|
|||||||
for signature in init.get_signatures():
|
for signature in init.get_signatures():
|
||||||
yield signature.value
|
yield signature.value
|
||||||
|
|
||||||
|
def py__getattribute__(self, name_or_str, *args, **kwargs):
|
||||||
|
inferred = super(AbstractInstanceValue, self).py__getattribute__(
|
||||||
|
name_or_str, *args, **kwargs)
|
||||||
|
if inferred or self.is_stub():
|
||||||
|
return inferred
|
||||||
|
|
||||||
|
# Since nothing was inferred, now check the __getattr__ and
|
||||||
|
# __getattribute__ methods. Stubs don't need to be checked, because
|
||||||
|
# they don't contain any logic.
|
||||||
|
n = name_or_str.value if isinstance(name_or_str, Name) else name_or_str
|
||||||
|
name = compiled.create_simple_object(self.inference_state, n)
|
||||||
|
|
||||||
|
# This is a little bit special. `__getattribute__` is in Python
|
||||||
|
# executed before `__getattr__`. But: I know no use case, where
|
||||||
|
# this could be practical and where Jedi would return wrong types.
|
||||||
|
# If you ever find something, let me know!
|
||||||
|
# We are inversing this, because a hand-crafted `__getattribute__`
|
||||||
|
# could still call another hand-crafted `__getattr__`, but not the
|
||||||
|
# other way around.
|
||||||
|
names = (self.get_function_slot_names(u'__getattr__') or
|
||||||
|
self.get_function_slot_names(u'__getattribute__'))
|
||||||
|
return self.execute_function_slots(names, name)
|
||||||
|
|
||||||
|
|
||||||
class AnonymousInstance(TreeInstance):
|
class AnonymousInstance(TreeInstance):
|
||||||
def __init__(self, inference_state, parent_context, class_value):
|
def __init__(self, inference_state, parent_context, class_value):
|
||||||
|
|||||||
Reference in New Issue
Block a user