From 3388a9659bd6843ee051bea8efb33d226d497385 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 3 Feb 2020 22:27:22 +0100 Subject: [PATCH 1/3] Catch an error with illegal class instances, fixes #1491 --- jedi/inference/compiled/access.py | 4 +++- test/test_api/test_interpreter.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/jedi/inference/compiled/access.py b/jedi/inference/compiled/access.py index f47ae7737..f76a645fb 100644 --- a/jedi/inference/compiled/access.py +++ b/jedi/inference/compiled/access.py @@ -570,4 +570,6 @@ def _is_class_instance(obj): except AttributeError: return False else: - return cls != type and not issubclass(cls, NOT_CLASS_TYPES) + # The isinstance check for cls is just there so issubclass doesn't + # raise an exception. + return cls != type and isinstance(cls, type) and not issubclass(cls, NOT_CLASS_TYPES) diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index 160639eb3..1ec0b7410 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -530,6 +530,16 @@ def syslogs_to_df(): assert c.line == syslogs_to_df.__wrapped__.__code__.co_firstlineno + 1 +@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL") +def test_illegal_class_instance(): + class X: + __class__ = 1 + X.__name__ = 'asdf' + d, = jedi.Interpreter('foo', [{'foo': X()}]).infer() + v, = d._name.infer() + assert not v.is_instance() + + @pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL") @pytest.mark.parametrize('module_name', ['sys', 'time', 'unittest.mock']) def test_core_module_completes(module_name): From 40fced2450c285e1eeb4f71da3f229f15e571b87 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 4 Feb 2020 19:34:42 +0100 Subject: [PATCH 2/3] Actually use follow_builtin_imports and improve the goto docstring, fixes #1492 --- jedi/api/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 44751109a..426f56ec1 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -271,12 +271,12 @@ def goto(self, line=None, column=None, **kwargs): """ Return the first definition found, while optionally following imports. Multiple objects may be returned, because Python itself is a - dynamic language, which means depending on an option you can have two - different versions of a function. + dynamic language, which means you can have two different versions of a + function. :param follow_imports: The goto call will follow imports. - :param follow_builtin_imports: If follow_imports is True will decide if - it follow builtin imports. + :param follow_builtin_imports: If follow_imports is True will try to + look up names in builtins (i.e. compiled or extension modules). :param only_stubs: Only return stubs for this goto call. :param prefer_stubs: Prefer stubs to Python objects for this goto call. :rtype: list of :class:`classes.Definition` @@ -310,7 +310,7 @@ def _goto(self, line, column, follow_imports=False, follow_builtin_imports=False names = list(name.goto()) if follow_imports: - names = helpers.filter_follow_imports(names) + names = helpers.filter_follow_imports(names, follow_builtin_imports) names = convert_names( names, only_stubs=only_stubs, From 7a55484b79bed3650a98a31a03a623f3fcd0680f Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 4 Feb 2020 23:56:01 +0100 Subject: [PATCH 3/3] Fix a test issue --- jedi/inference/gradual/annotation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index bda6c20b3..1de87962e 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -285,7 +285,7 @@ def infer_return_for_callable(arguments, param_values, result_values): all_type_vars.update(type_var_dict) return ValueSet.from_sets( - v.define_generics(type_var_dict) + v.define_generics(all_type_vars) if isinstance(v, (DefineGenericBase, TypeVar)) else ValueSet({v}) for v in result_values ).execute_annotation()