Search code examples
pythonautocompletepython-imaging-librarycode-completionpython-jedi

Jedi completion does not work for Image object created using Image.open() method


I am using deoplete-jedi to provide auto-completions inside Neovim. I found out that auto-completion does not work if I create an Image object instance using Image.open() method when using Pillow. But for Image instance created using Image.new() method, the auto-completion works correctly.

After a lot of debuging, I finally find out the reason. Because the Jedi package can not provide completions for Image instance created by Image.open() method.

The below code shows the differences:

import jedi

source1 = '''
from PIL import Image
im = Image.new('test.jpg', (128, 128))
im.
'''

script1 = jedi.Script(source1, 4, len('im.'), 'example1.py')
print(script1.completions())

source2 = '''
from PIL import Image
im = Image.open('test.jpg')
im.
'''
script2 = jedi.Script(source2, 4, len('im.'), 'example2.py')
print(script2.completions())

Since the two methods both return an Image object, I do not know why the auto-completion behaves differently.

Version info

  • Python: Python 3.6.8
  • jedi: 0.13.3
  • Pillow: 5.2.0

Solution

  • The problem typically is that things like Image.open() do things like caching, where it's pretty much impossible to infer the right type.

    In this example (look at https://github.com/python-pillow/Pillow/blob/master/src/PIL/Image.py#L2690), Jedi tries to follow im -> _open_core(...) -> other im -> factory(...) -> factory seems like factory, accept = OPEN[i] -> but what is OPEN -> it's defined as an empty {}, and filled in register_open() or from the outside -> register_open is not called in the same file.

    And that's where Jedi stops searching for solutions. So you can see it's not always possible to infer types. Even I'm not sure what the returned type will be and I tried to look at it for 10 minutes. The solution is usually stubs/type annotations for this.