Skip to content

tab-completion sometimes access attributes #31643

@videlec

Description

@videlec

When jedi is activated, the IPython tab completion tries to access the __module__ attribute of the tab-completed object

sage: ip = get_ipython()
sage: ip.Completer.use_jedi = True
sage: cython("""
....: cdef class A(object):
....:     def __getattr__(self, key):
....:         print('getattr(key={})'.format(key))
....:         raise AttributeError
....: """)
sage: my_custom_name = A()
sage: ip.Completer.all_completions("my_custo")
getattr(key=__module__)
getattr(key=__module__)
['my_custom_name']

Note that this is very specific to extension classes and works fine with plain Python classes.

You can see here that it is specific to jedi

sage: ip.Completer.use_jedi = False
sage: ip.Completer.all_completions("my_cu")
['my_custom_name']

This access to the __module__ attribute has dramatic consequence with lazily imported objects that gets imported when accessing any attribute including __module__. In the following example, it even leads to a Sage crash on 9.2.rc3 because of badly designed lazy import

sage: ip.Completer.all_completions("s")
Traceback (most recent call last):
...
AttributeError: module 'sage.coding.linear_code' has no attribute 'self_orthogonal_binary_codes'

Here is the full trace of the calls that lead to the access of __module__ in the first example above

  File "/opt/sage/src/bin/sage-ipython", line 16, in <module>
    app.start()
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/terminal/ipapp.py", line 356, in start
    self.shell.mainloop()
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/terminal/interactiveshell.py", line 563, in mainloop
    self.interact()
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/terminal/interactiveshell.py", line 554, in interact
    self.run_cell(code, store_history=True)
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2866, in run_cell
    result = self._run_cell(
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2895, in _run_cell
    return runner(coro)
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/async_helpers.py", line 68, in _pseudo_sync_runner
    coro.send(None)
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3071, in run_cell_async
    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3263, in run_ast_nodes
    if (await self.run_code(code, result,  async_=asy)):
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-13-e16cd8a94897>", line 1, in <module>
    ip.Completer.all_completions("my_cu")
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/completer.py", line 1148, in all_completions
    return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/completer.py", line 1148, in <listcomp>
    return ['.'.join([prefix, c.text]) if prefix and self.use_jedi else c.text
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/completer.py", line 1818, in completions
    for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
  File "/opt/sage/local/lib/python3.9/site-packages/IPython/core/completer.py", line 1868, in _completions
    type_ = jm.type
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/api/classes.py", line 759, in type
    return super(Completion, self).type
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/api/classes.py", line 192, in type
    return self._name.api_type
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/names.py", line 612, in __getattr__
    return getattr(self._wrapped_name, name)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/value.py", line 354, in api_type
    api = self.infer()
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/cache.py", line 111, in wrapper
    result = method(self, *args, **kwargs)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/value.py", line 362, in infer
    return ValueSet([self.infer_compiled_value()])
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/value.py", line 365, in infer_compiled_value
    return create_from_name(self._inference_state, self._parent_value, self.string_name)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/value.py", line 591, in create_from_name
    access_paths = compiled_value.access_handle.getattr_paths(name, default=None)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/subprocess/__init__.py", line 400, in _workaround
    return self._cached_results(name, *args, **kwargs)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/cache.py", line 111, in wrapper
    result = method(self, *args, **kwargs)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/subprocess/__init__.py", line 404, in _cached_results
    return self._subprocess.get_compiled_method_return(self.id, name, *args, **kwargs)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/subprocess/functions.py", line 24, in get_compiled_method_return
    return getattr(handle.access, attribute)(*args, **kwargs)
  File "/opt/sage/local/lib/python3.9/site-packages/jedi/inference/compiled/access.py", line 391, in getattr_paths
    module = inspect.getmodule(return_obj)
  File "/usr/lib/python3.9/inspect.py", line 731, in getmodule
    if hasattr(object, '__module__'):

Upstream: Not yet reported upstream; Will do shortly.

CC: @kliem

Component: misc

Issue created by migration from https://trac.sagemath.org/ticket/31643

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions