Ejemplo n.º 1
0
def complete_jedi(context: CompletionContext):
    """Completes python code using Jedi and xonsh operators"""
    if context.python is None:
        return None

    xonsh_execer: XonshSession = builtins.__xonsh__  # type: ignore
    ctx = context.python.ctx or {}

    # if this is the first word and it's a known command, don't complete.
    # taken from xonsh/completers/python.py
    if context.command and context.command.arg_index != 0:
        first = context.command.args[0].value
        if first in xonsh_execer.commands_cache and first not in ctx:  # type: ignore
            return None

    filter_func = get_filter_function()
    jedi.settings.case_insensitive_completion = not xonsh_execer.env.get(
        "CASE_SENSITIVE_COMPLETIONS"
    )

    source = context.python.multiline_code
    index = context.python.cursor_index
    row = source.count("\n", 0, index) + 1
    column = (
        index - source.rfind("\n", 0, index) - 1
    )  # will be `index - (-1) - 1` if there's no newline

    extra_ctx = {"__xonsh__": xonsh_execer}
    try:
        extra_ctx["_"] = _
    except NameError:
        pass

    if JEDI_NEW_API:
        script = jedi.Interpreter(source, [ctx, extra_ctx])
    else:
        script = jedi.Interpreter(source, [ctx, extra_ctx], line=row, column=column)

    script_comp = set()
    try:
        if JEDI_NEW_API:
            script_comp = script.complete(row, column)
        else:
            script_comp = script.completions()
    except Exception:
        pass

    res = set(create_completion(comp) for comp in script_comp if should_complete(comp))

    if index > 0:
        last_char = source[index - 1]
        res.update(
            RichCompletion(t, prefix_len=1)
            for t in XONSH_SPECIAL_TOKENS
            if filter_func(t, last_char)
        )
    else:
        res.update(RichCompletion(t, prefix_len=0) for t in XONSH_SPECIAL_TOKENS)

    return res
Ejemplo n.º 2
0
def complete_jedi(prefix, line, start, end, ctx):
    """Completes python code using Jedi and xonsh operators"""

    # if this is the first word and it's a known command, don't complete.
    # taken from xonsh/completers/python.py
    if line.lstrip() != "":
        first = line.split(maxsplit=1)[0]
        if prefix == first and first in __xonsh__.commands_cache and first not in ctx:
            return set()

    filter_func = get_filter_function()
    jedi.settings.case_insensitive_completion = not __xonsh__.env.get(
        "CASE_SENSITIVE_COMPLETIONS")

    if PTK_COMPLETER:  # 'is not None' won't work with lazyobject
        document = PTK_COMPLETER.current_document
        source = document.text
        row = document.cursor_position_row + 1
        column = document.cursor_position_col
    else:
        source = line
        row = 1
        column = end

    extra_ctx = {"__xonsh__": __xonsh__}
    try:
        extra_ctx["_"] = _
    except NameError:
        pass

    if JEDI_NEW_API:
        script = jedi.Interpreter(source, [ctx, extra_ctx])
    else:
        script = jedi.Interpreter(source, [ctx, extra_ctx],
                                  line=row,
                                  column=column)

    script_comp = set()
    try:
        if JEDI_NEW_API:
            script_comp = script.complete(row, column)
        else:
            script_comp = script.completions()
    except Exception:
        pass

    # make sure _* names are completed only when
    # the user writes the first underscore
    complete_underscores = prefix.endswith("_")

    return set(
        itertools.chain(
            (create_completion(comp) for comp in script_comp
             if complete_underscores or not comp.name.startswith("_")
             or not comp.complete.startswith("_")),
            (t for t in XONSH_SPECIAL_TOKENS if filter_func(t, prefix)),
        ))
Ejemplo n.º 3
0
def test_keyword_argument():
    def f(some_keyword_argument):
        pass

    c, = jedi.Interpreter("f(some_keyw", [{'f': f}]).complete()
    assert c.name == 'some_keyword_argument='
    assert c.complete == 'ord_argument='

    # Make it impossible for jedi to find the source of the function.
    f.__name__ = 'xSOMETHING'
    c, = jedi.Interpreter("x(some_keyw", [{'x': f}]).complete()
    assert c.name == 'some_keyword_argument='
Ejemplo n.º 4
0
def test_completion_param_annotations():
    # Need to define this function not directly in Python. Otherwise Jedi is to
    # clever and uses the Python code instead of the signature object.
    code = 'def foo(a: 1, b: str, c: int = 1.0) -> bytes: pass'
    exec_(code, locals())
    script = jedi.Interpreter('foo', [locals()])
    c, = script.completions()
    a, b, c = c.params
    assert a.infer() == []
    assert [d.name for d in b.infer()] == ['str']
    assert {d.name for d in c.infer()} == {'int', 'float'}

    d, = jedi.Interpreter('foo()', [locals()]).goto_definitions()
    assert d.name == 'bytes'
Ejemplo n.º 5
0
def test_keyword_argument():
    def f(some_keyword_argument):
        pass

    c, = jedi.Interpreter("f(some_keyw", [{'f': f}]).completions()
    assert c.name == 'some_keyword_argument'
    assert c.complete == 'ord_argument='

    # This needs inspect.signature to work.
    if is_py3:
        # Make it impossible for jedi to find the source of the function.
        f.__name__ = 'xSOMETHING'
        c, = jedi.Interpreter("x(some_keyw", [{'x': f}]).completions()
        assert c.name == 'some_keyword_argument'
Ejemplo n.º 6
0
    def get_completions(self, info):
        """Gets Python completions based on the current cursor position
        within the %%init_spark cell.

        Based on
        https://github.com/Calysto/metakernel/blob/master/metakernel/magics/python_magic.py

        Parameters
        ----------
        info : dict
            Information about the current caret position
        """
        if jedi is None:
            return []

        text = info['code']
        position = (info['line_num'], info['column'])
        interpreter = jedi.Interpreter(text, [self.env])

        lines = common.splitlines(text)
        name = get_on_completion_name(interpreter._get_module_node(), lines,
                                      position)

        before = text[:len(text) - len(name)]
        completions = interpreter.completions()
        completions = [before + c.name_with_symbols for c in completions]
        return [c[info['start']:] for c in completions]
Ejemplo n.º 7
0
 def shell_complete(self, identities, msg):
     code = msg['content']['code']
     cursor_pos = msg['content']['cursor_pos']
     linenr, colnr = cursor_pos_to_lc(code, cursor_pos)
     script = jedi.Interpreter(code, [self.user_ns, self.user_global_ns],
                               line=linenr,
                               column=colnr)
     completions = script.completions()
     matches = [c.name_with_symbols for c in completions]
     rests = [
         len(c.name_with_symbols) - len(c.complete) for c in completions
     ]
     replace_start = cursor_pos - rests[0] if len(rests) > 0 else cursor_pos
     content = {
         'matches': matches,
         'cursor_start': replace_start,
         'cursor_end': cursor_pos,
         'status': 'ok'
     }
     metadata = {}
     self.send(self.shell_stream,
               'complete_reply',
               content,
               metadata=metadata,
               parent_header=msg['header'],
               identities=identities)
Ejemplo n.º 8
0
 def _jedi_complete(*args, **kws):
     import jedi
     import json
     i = jedi.Interpreter(*args, **kws)
     cs = i.completions()
     d = [dict(name=c.name, complete=c.complete, docstring=c.docstring()) for c in cs]
     print(json.dumps(d))
Ejemplo n.º 9
0
    def get_reticulate_completions(document, complete_event):
        word = document.get_word_before_cursor()
        prefix_length = settings.completion_prefix_length
        if len(word
               ) < prefix_length and not complete_event.completion_requested:
            return []

        glo = rcopy(rcall(("reticulate", "py_run_string"), "globals()"))
        loc = rcopy(rcall(("reticulate", "py_run_string"), "locals()"))
        try:
            script = jedi.Interpreter(document.text,
                                      column=document.cursor_position_col,
                                      line=document.cursor_position_row + 1,
                                      path="input-text",
                                      namespaces=[glo, loc])
            return [
                Completion(
                    text_type(c.name_with_symbols),
                    len(text_type(c.complete)) -
                    len(text_type(c.name_with_symbols)))
                for c in script.completions()
            ]

        except Exception:
            return []
Ejemplo n.º 10
0
def get_jedi_script_from_document(document, locals, globals):
    try:
        return jedi.Interpreter(document.text,
                                column=document.cursor_position_col,
                                line=document.cursor_position_row + 1,
                                path='input-text',
                                namespaces=[locals, globals])

    except jedi.common.MultiLevelStopIteration:
        # This happens when the document is just a backslash.
        return None
    except ValueError:
        # Invalid cursor position.
        # ValueError('`column` parameter is not in a valid range.')
        return None
    except AttributeError:
        # Workaround for #65: https://github.com/jonathanslenders/python-prompt-toolkit/issues/65
        # See also: https://github.com/davidhalter/jedi/issues/508
        return None
    except IndexError:
        # Workaround Jedi issue #514: for https://github.com/davidhalter/jedi/issues/514
        return None
    except KeyError:
        # Workaroud for a crash when the input is "u'", the start of a unicode string.
        return None
Ejemplo n.º 11
0
def get_completions(code: str,
                    cursor: Optional[int] = None,
                    namespaces: Optional[List] = None) -> List[str]:
    """
    Get code autocompletion candidates

    Note that this function requires to have the jedi module loaded.

    Parameters
    ----------
    code
       the Python code to complete.
    cursor
       optional position in the code at which to autocomplete
    namespaces
       a list of namespaces

    Returns
    -------
    a list of autocompleted modules
    """
    import jedi
    import __main__

    if namespaces is None:
        namespaces = [__main__.__dict__]

    if cursor is None:
        cursor = len(code)
    code = code[:cursor]
    interp = jedi.Interpreter(code, namespaces)
    completions = interp.completions()

    return [x.name for x in completions]
Ejemplo n.º 12
0
def test_dir_magic_method():
    class CompleteAttrs(object):
        def __getattr__(self, name):
            if name == 'foo':
                return 1
            if name == 'bar':
                return 2
            raise AttributeError(name)

        def __dir__(self):
            if is_py3:
                names = object.__dir__(self)
            else:
                names = dir(object())
            return ['foo', 'bar'] + names

    itp = jedi.Interpreter("ca.", [{'ca': CompleteAttrs()}])
    completions = itp.completions()
    names = [c.name for c in completions]
    assert ('__dir__' in names) == is_py3
    assert '__class__' in names
    assert 'foo' in names
    assert 'bar' in names

    foo = [c for c in completions if c.name == 'foo'][0]
    assert foo._goto_definitions() == []
Ejemplo n.º 13
0
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()
Ejemplo n.º 14
0
    def update_calltips(self):
        if not check_module("jedi", "0.17"):
            return
        import jedi

        line, column = self.getCursorPosition()

        # Simulate QGIS python default imports
        init_lines = [
            "from qgis.core import *",
            "from qgis.gui import *",
            "from qgis.utils import iface",
            "from PyQt5.QtCore import *",
            "from PyQt5.QtWidgets import *",
            "from PyQt5.QtGui import *",
            "iface: QgisInterface = iface",
        ]
        init_text = "\n".join(init_lines) + "\n"
        script = jedi.Interpreter(code=init_text + self.text(),
                                  namespaces=(globals(), locals()))
        try:
            res = script.get_signatures(line + 1 + len(init_lines), column)
        except TypeError:
            res = None
        if not res:
            self.callTips.hide()
            return

        bracket_line, bracket_column = res[0].bracket_start
        pos = self.positionFromLineIndex(bracket_line - 1 - len(init_lines),
                                         bracket_column)
        x = self.SendScintilla(QsciScintilla.SCI_POINTXFROMPOSITION, 0, pos)
        y = self.SendScintilla(QsciScintilla.SCI_POINTYFROMPOSITION, 0, pos)

        self.callTips.show_signatures(res, QPoint(x, y))
Ejemplo n.º 15
0
def test_dir_magic_method(allow_unsafe_getattr):
    class CompleteAttrs(object):
        def __getattr__(self, name):
            if name == 'foo':
                return 1
            if name == 'bar':
                return 2
            raise AttributeError(name)

        def __dir__(self):
            return ['foo', 'bar'] + object.__dir__(self)

    itp = jedi.Interpreter("ca.", [{'ca': CompleteAttrs()}])
    completions = itp.complete()
    names = [c.name for c in completions]
    assert ('__dir__' in names) is True
    assert '__class__' in names
    assert 'foo' in names
    assert 'bar' in names

    foo = [c for c in completions if c.name == 'foo'][0]
    if allow_unsafe_getattr:
        inst, = foo.infer()
        assert inst.name == 'int'
        assert inst.type == 'instance'
    else:
        assert foo.infer() == []
Ejemplo n.º 16
0
def get_jedi_script_from_document(document, locals, globals):
    import jedi  # We keep this import in-line, to improve start-up time.
    # Importing Jedi is 'slow'.

    try:
        return jedi.Interpreter(document.text,
                                column=document.cursor_position_col,
                                line=document.cursor_position_row + 1,
                                path='input-text',
                                namespaces=[locals, globals])
    except ValueError:
        # Invalid cursor position.
        # ValueError('`column` parameter is not in a valid range.')
        return None
    except AttributeError:
        # Workaround for #65: https://github.com/jonathanslenders/python-prompt-toolkit/issues/65
        # See also: https://github.com/davidhalter/jedi/issues/508
        return None
    except IndexError:
        # Workaround Jedi issue #514: for https://github.com/davidhalter/jedi/issues/514
        return None
    except KeyError:
        # Workaroud for a crash when the input is "u'", the start of a unicode string.
        return None
    except Exception:
        # Workaround for: https://github.com/jonathanslenders/ptpython/issues/91
        return None
Ejemplo n.º 17
0
def test_sys_path_docstring():  # Was an issue in #1298
    import jedi
    s = jedi.Interpreter("from sys import path\npath",
                         line=2,
                         column=4,
                         namespaces=[locals()])
    s.completions()[0].docstring()
Ejemplo n.º 18
0
def test_param_completion():
    def foo(bar):
        pass

    lambd = lambda xyz: 3

    _assert_interpreter_complete('foo(bar', locals(), ['bar'])
    assert bool(jedi.Interpreter('lambd(xyz', [locals()]).completions()) == is_py3
Ejemplo n.º 19
0
def test_mixed_module_cache():
    """Caused by #1479"""
    interpreter = jedi.Interpreter('jedi', [{'jedi': jedi}])
    d, = interpreter.infer()
    assert d.name == 'jedi'
    inference_state = interpreter._inference_state
    jedi_module, = inference_state.module_cache.get(('jedi', ))
    assert isinstance(jedi_module, ModuleValue)
Ejemplo n.º 20
0
def test_more_complex_instances():
    class Something:
        def foo(self, other):
            return self

    class Base:
        def wow(self):
            return Something()

    script = jedi.Interpreter('Base().wow().foo', [locals()])
    c, = script.complete()
    assert c.name == 'foo'

    x = Base()
    script = jedi.Interpreter('x.wow().foo', [locals()])
    c, = script.complete()
    assert c.name == 'foo'
Ejemplo n.º 21
0
def get_interpreter_completions(source: str, namespaces: List[Dict]):
    import jedi

    interpreter = jedi.Interpreter(source, namespaces)
    if hasattr(interpreter, "completions"):
        # up to jedi 0.17
        return _tweak_completions(interpreter.completions())
    else:
        return _tweak_completions(interpreter.complete())
Ejemplo n.º 22
0
def test_completion_params():
    foo = lambda a, b=3: None

    script = jedi.Interpreter('foo', [locals()])
    c, = script.completions()
    assert [p.name for p in c.params] == ['a', 'b']
    assert c.params[0]._goto_definitions() == []
    t, = c.params[1]._goto_definitions()
    assert t.name == 'int'
Ejemplo n.º 23
0
def test_name_not_inferred_properly():
    """
    In IPython notebook it is typical that some parts of the code that is
    provided was already executed. In that case if something is not properly
    inferred, it should still infer from the variables it already knows.
    """
    x = 1
    d, = jedi.Interpreter('x = UNDEFINED; x', [locals()]).infer()
    assert d.name == 'int'
Ejemplo n.º 24
0
def test_property_content():
    class Foo3(object):
        @property
        def bar(self):
            return 1

    foo = Foo3()
    def_, = jedi.Interpreter('foo.bar', [locals()]).infer()
    assert def_.name == 'int'
Ejemplo n.º 25
0
def test_param_completion():
    def foo(bar):
        pass

    lambd = lambda xyz: 3

    _assert_interpreter_complete('foo(bar', locals(), ['bar'])
    # TODO we're not yet using the Python3.5 inspect.signature, yet.
    assert not jedi.Interpreter('lambd(xyz', [locals()]).completions()
Ejemplo n.º 26
0
def test_param_annotation_completion(class_is_findable):
    class Foo:
        bar = 3

    if not class_is_findable:
        Foo.__name__ = 'asdf'

    code = 'def CallFoo(x: Foo):\n x.ba'
    def_, = jedi.Interpreter(code, [locals()]).complete()
    assert def_.name == 'bar'
Ejemplo n.º 27
0
def test__wrapped__():
    from functools import lru_cache

    @lru_cache(maxsize=128)
    def syslogs_to_df():
        pass

    c, = jedi.Interpreter('syslogs_to_df', [locals()]).complete()
    # Apparently the function starts on the line where the decorator starts.
    assert c.line == syslogs_to_df.__wrapped__.__code__.co_firstlineno + 1
Ejemplo n.º 28
0
def test_completion_params():
    foo = lambda a, b=3: None

    script = jedi.Interpreter('foo', [locals()])
    c, = script.complete()
    sig, = c.get_signatures()
    assert [p.name for p in sig.params] == ['a', 'b']
    assert sig.params[0].infer() == []
    t, = sig.params[1].infer()
    assert t.name == 'int'
Ejemplo n.º 29
0
def jedi_completions(text, offset):
    '''
    autocomplete() must be called first.
    Not used yet. Returns the same completions jedi would.
    Examples
    --------
    from riptable.rt_misc import jedi_completions
    st = Struct({'a': 5})
    jedi_completions('st', 2)
    '''
    def position_to_cursor(text: str, offset: int):
        before = text[:offset]
        blines = before.split('\n')
        line = before.count('\n')
        col = len(blines[-1])
        return line, col

    def cursor_to_position(text: str, line: int, column: int) -> int:
        lines = text.split('\n')
        return sum(len(l) + 1 for l in lines[:line]) + column

    try:
        ipc = Hooker._ipcompleter
        cursor_line, cursor_column = position_to_cursor(text, offset)

        namespaces = [ipc.namespace]
        if ipc.global_namespace is not None:
            namespaces.append(ipc.global_namespace)

        completion_filter = lambda x: x
        offset = cursor_to_position(text, cursor_line, cursor_column)
        # filter output if we are completing for object members
        if offset:
            pre = text[offset - 1]


#            if pre == '.':
#                if self.omit__names == 2:
#                    completion_filter = lambda c:not c.name.startswith('_')
#                elif self.omit__names == 1:
#                    completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
#                elif self.omit__names == 0:
#                    completion_filter = lambda x:x
#                else:
#                    raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))

        import jedi
        interpreter = jedi.Interpreter(text[:offset],
                                       namespaces,
                                       column=cursor_column,
                                       line=cursor_line + 1)
        return interpreter.completions()

    except Exception:
        return []
Ejemplo n.º 30
0
def test_simple_completions(code, completions):
    x = [str]
    y = {1}
    z = {1: str, 2: list}
    import collections
    deq = collections.deque([1])
    counter = collections.Counter(['asdf'])
    string = ''

    defs = jedi.Interpreter(code, [locals()]).complete()
    assert [d.name for d in defs] == completions