Currently I am writing all my Python code using Neovim and a couple of plugins to provide auto-completion, linting, etc.
For code auto-completion, I use deoplete
as my completion engine and deoplete-jedi
as the completion source for Python. They work great most of the time. However,
occasionally I can not get any auto-completion for some object instances. For
example, auto-completion for object instances returned by the Image.open()
method in the package Pillow does
not work. I decide to take a look.
At first, I think it is an issue with deoplete or deoplete-jedi. However, I
find that auto-completion for Image instances returned by other methods, e.g.,
Image.new()
,
works as expected. If this is an issue with deoplete or deoplete-jedi, then
auto-completion should not work anymore. Maybe it is due to the static type
checker Jedi that deoplete-jedi relies
on?
To find out the real reason, I use the following script to check if Jedi can
provide completion for Image instances returned by Image.open()
and
Image.new()
method1:
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())
As expected, the first print()
shows a list of completion results, while the
second print()
shows an empty list.
So this is actually an issue with Jedi. I filed an
issue on the Jedi GitHub
repo. After a while, I got a reply from the maintainer of this project. The
root cause is that Jedi can not infer the type returned by Image.open()
method since it is too dynamic to infer. The author suggested that I may use
type
hints
to help Jedi infer the types of the return objects. I tried two ways based on
the type hinting
documentation
of Jedi.
The first way is to use function annotations. I find the source file of
Image.open()
on my system and change the its definition from
def open(fp, mode="r") :
to
def open(fp, mode="r") -> Image:
Now the auto-completion works for instance returned by Image.open()
method.
While this method works, it is cumbersome to use since it requires changing the
source files of various packages.
The second way is to use type hints in inline comments. But the auto-completion does not work anymore. My test script is:
import jedi
source = '''
from PIL import Image
im = Image.open('test.png') # type: Image
im.
'''
script = jedi.Script(source, 4, len('im.'), 'example.py')
print(script.completions())
The print function shows an empty list.
So for now, you may stick to function annotations if you really want type hints to work for Jedi.