davidhalter / jedi

Awesome autocompletion, static analysis and refactoring library for python
http://jedi.readthedocs.io
Other
5.82k stars 507 forks source link

Compiled methods are completed as 'builtins' #2031

Open zerocewl opened 3 weeks ago

zerocewl commented 3 weeks ago

First things first: Thx for creating and maintaining jedi!

I have an issue with completing compiled files, created with cython but only with methods / functions inside classes. If i try to complete these methods they are shown as builtins and not as function, in fact all infos like docstring are missing too.

To reproduce the issue i used a simple python class (the static function is only to show, that this one works):

class MyClass:

   def my_function(self):
      print('hello from function2')

   @staticmethod
   def my_function_static():
      print('hello from static function')

Following the simple hello world example from Cython i created the so file / compiled with

python setup.py build_ext --inplace

After this i tried to create the completion with the minimal changed jedi example:

import jedi
source='''
import helloworld
helloworld.MyClass().my_func'''
script = jedi.Script(source, path='example.py')
completions = script.complete(3, len('helloworld.MyClass().my_func'))

But the completion from the first entry returns module_nameas builtins.

I also create a small pytest to assert the completion, but only with the already created compiled file:

def test_jedi_class_completion():
    source='''
import helloworld
helloworld.MyClass().my_func'''
    script = jedi.Script(source, path='example.py')
    completions = script.complete(3, len('helloworld.MyClass().my_func'))
    assert completions[0].module_name == 'helloworld'
    assert completions[0].type == 'function'
    assert completions[0].description == 'def my_function'

I tried to debug inference/compiled and only found a very rough workaround by setting the is_get_descriptor in access.py#L335 to False. So maybe the return value from

attr, is_get_descriptor = getattr_static(self._obj, name) is not as expected for this case?

Here is a screenshot from the pytest, showing the wrong content for the completion.

image

Note: Static functions inside classes works as expected.

I used python 3.11.10 on arm mac (the issue is on windows reproducible too).

❯ pip list
Package    Version
---------- -------
Cython     3.0.11
jedi       0.19.1
parso      0.8.4
pip        24.2
setuptools 74.1.2
davidhalter commented 3 weeks ago

The problem is probably that the attribute on helloworld.MyClass.my_func' might just be an alias to abs or whatever builtin function. I'm not sure we have the information on the object (on classes we do). We could probably change the default there. But this is all highly complicated, because for a lot of these things we are talking about heuristics.

zerocewl commented 3 weeks ago

hm that sounds not very promising =)

There is no easy solution where we can adapt the criterion if the node is a class function? For other functions the completion is working fine...

I only found during debugging in getattr_static that at some point a __get__ is checked and found for the function, but i don't know why this should be the check.

zerocewl commented 3 weeks ago

Another nasty workaround could be the change of /jedi/inference/compiled/access.py#L354 by adding a check like type(attr).__name__ != "cython_function_or_method":

if is_get_descriptor and type(attr) not in ALLOWED_DESCRIPTOR_ACCESS and type(attr).__name__ != "cython_function_or_method":