mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-29 08:26:53 +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)
|
||||
|
||||
|
||||
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):
|
||||
message = ('AttributeError: %s has no attribute %s.' % (scope, name_part))
|
||||
from jedi.evaluate.representation import Instance
|
||||
@@ -95,6 +109,7 @@ def add_attribute_error(evaluator, scope, name_part):
|
||||
try:
|
||||
scope.get_subscope_by_name('__getattribute__')
|
||||
except KeyError:
|
||||
if not _check_for_setattr(scope):
|
||||
typ = Error
|
||||
else:
|
||||
typ = Error
|
||||
|
||||
@@ -115,7 +115,6 @@ class NameFinder(object):
|
||||
if result:
|
||||
break
|
||||
|
||||
self._last_filter_name_scope = name_list_scope
|
||||
scope_txt = (self.scope if 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,
|
||||
|
||||
@@ -3,6 +3,10 @@ Jedi issues warnings for possible errors if ``__getattr__``,
|
||||
``__getattribute__`` or ``setattr`` are used.
|
||||
"""
|
||||
|
||||
# -----------------
|
||||
# __getattr*__
|
||||
# -----------------
|
||||
|
||||
|
||||
class Cls():
|
||||
def __getattr__(self, name):
|
||||
@@ -22,3 +26,21 @@ Inherited().upper
|
||||
|
||||
#! 12 warning attribute-error
|
||||
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