diff --git a/jedi/evaluate/analysis.py b/jedi/evaluate/analysis.py index 9ad52387..fa35ed61 100644 --- a/jedi/evaluate/analysis.py +++ b/jedi/evaluate/analysis.py @@ -82,8 +82,20 @@ def add(evaluator, name, jedi_obj, message=None, typ=Error, payload=None): evaluator.analysis.append(instance) +def add_attribute_error(evaluator, jedi_obj, message, scope): + typ = Error + payload = scope, jedi_obj # jedi_obj is a name_part. + add(evaluator, 'attribute-error', jedi_obj, message, typ, payload) + + def _check_for_exception_catch(evaluator, jedi_obj, exception, payload=None): - """Returns True if the exception was catched.""" + """ + Checks if a jedi object (e.g. `Statement`) sits inside a try/catch and + doesn't count as an error (if equal to `exception`). + Also checks `hasattr` for AttributeErrors and uses the `payload` to compare + it. + Returns True if the exception was catched. + """ def check_match(cls): try: return isinstance(cls, CompiledObject) and issubclass(exception, cls.obj) diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 100046f3..e5bda942 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -57,8 +57,10 @@ class NameFinder(object): else: message = ('AttributeError: %s has no attribute %s.' % (self._last_filter_name_scope, self.name_str)) - analysis.add(self._evaluator, err_type, self.name_str, message, - payload=(self.scope, self.name_str)) + payload = self.name_str + analysis.add_attribute_error(self._evaluator, + self.name_str, message, + self.scope) debug.dbg('finder._names_to_types: %s -> %s', names, types) return self._resolve_descriptors(types) diff --git a/test/conftest.py b/test/conftest.py index 9c5b2372..6b834146 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -9,6 +9,7 @@ from . import helpers from . import run from . import refactor import jedi +from jedi.evaluate.analysis import Warning def pytest_addoption(parser): @@ -105,7 +106,9 @@ class StaticAnalysisCase(object): def run(self, compare_cb): analysis = jedi.Script(self._source, path=self._path)._analysis() - analysis = [(r.line, r.column, r.name) for r in analysis] + typ_str = lambda inst: 'warning ' if isinstance(inst, Warning) else '' + analysis = [(r.line, r.column, typ_str(r) + r.name) + for r in analysis] compare_cb(self, analysis, self.collect_comparison()) def __repr__(self):