mirror of
https://github.com/davidhalter/jedi.git
synced 2026-08-17 19:27:59 +08:00
Also issue warnings if setattr is used in a class instead of an error
This commit is contained in:
@@ -82,6 +82,20 @@ def add(evaluator, name, jedi_obj, message=None, typ=Error, payload=None):
|
|||||||
evaluator.analysis.append(instance)
|
evaluator.analysis.append(instance)
|
||||||
|
|
||||||
|
|
||||||
|
def _check_for_setattr(instance):
|
||||||
|
"""
|
||||||
|
Check if there's any setattr method inside an instance. If so, return True.
|
||||||
|
"""
|
||||||
|
module = instance.get_parent_until()
|
||||||
|
try:
|
||||||
|
stmts = module.used_names['setattr']
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return any(instance.start_pos < stmt.start_pos < instance.end_pos
|
||||||
|
for stmt in stmts)
|
||||||
|
|
||||||
|
|
||||||
def add_attribute_error(evaluator, scope, name_part):
|
def add_attribute_error(evaluator, scope, name_part):
|
||||||
message = ('AttributeError: %s has no attribute %s.' % (scope, name_part))
|
message = ('AttributeError: %s has no attribute %s.' % (scope, name_part))
|
||||||
from jedi.evaluate.representation import Instance
|
from jedi.evaluate.representation import Instance
|
||||||
@@ -95,7 +109,8 @@ def add_attribute_error(evaluator, scope, name_part):
|
|||||||
try:
|
try:
|
||||||
scope.get_subscope_by_name('__getattribute__')
|
scope.get_subscope_by_name('__getattribute__')
|
||||||
except KeyError:
|
except KeyError:
|
||||||
typ = Error
|
if not _check_for_setattr(scope):
|
||||||
|
typ = Error
|
||||||
else:
|
else:
|
||||||
typ = Error
|
typ = Error
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ class NameFinder(object):
|
|||||||
if result:
|
if result:
|
||||||
break
|
break
|
||||||
|
|
||||||
self._last_filter_name_scope = name_list_scope
|
|
||||||
scope_txt = (self.scope if self.scope == name_list_scope
|
scope_txt = (self.scope if self.scope == name_list_scope
|
||||||
else '%s-%s' % (self.scope, name_list_scope))
|
else '%s-%s' % (self.scope, name_list_scope))
|
||||||
debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str,
|
debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str,
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ Jedi issues warnings for possible errors if ``__getattr__``,
|
|||||||
``__getattribute__`` or ``setattr`` are used.
|
``__getattribute__`` or ``setattr`` are used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# __getattr*__
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
|
||||||
class Cls():
|
class Cls():
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@@ -22,3 +26,21 @@ Inherited().upper
|
|||||||
|
|
||||||
#! 12 warning attribute-error
|
#! 12 warning attribute-error
|
||||||
Inherited().undefined
|
Inherited().undefined
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# setattr
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
|
||||||
|
class SetattrCls():
|
||||||
|
def __init__(self, dct):
|
||||||
|
# Jedi doesn't even try to understand such code
|
||||||
|
for k, v in dct:
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
self.defined = 3
|
||||||
|
|
||||||
|
c = SetattrCls({'a': 'b'})
|
||||||
|
c.defined
|
||||||
|
#! 2 warning attribute-error
|
||||||
|
c.undefined
|
||||||
|
|||||||
Reference in New Issue
Block a user