Esempio n. 1
0
    def parse_and_get_code(self, code=None, path=None, encoding='utf-8',
                           use_latest_grammar=False, file_io=None, **kwargs):
        if self.allow_different_encoding:
            if code is None:
                if file_io is None:
                    file_io = FileIO(path)
                code = file_io.read()
            code = python_bytes_to_unicode(code, encoding=encoding, errors='replace')

        grammar = self.latest_grammar if use_latest_grammar else self.grammar
        return grammar.parse(code=code, path=path, file_io=file_io, **kwargs), code
Esempio n. 2
0
def _load_from_typeshed(inference_state, python_value_set, parent_module_value,
                        import_names):
    import_name = import_names[-1]
    map_ = None
    if len(import_names) == 1:
        map_ = _cache_stub_file_map(inference_state.grammar.version_info)
        import_name = _IMPORT_MAP.get(import_name, import_name)
    elif isinstance(parent_module_value, ModuleValue):
        if not parent_module_value.is_package():
            # Only if it's a package (= a folder) something can be
            # imported.
            return None
        paths = parent_module_value.py__path__()
        # Once the initial package has been loaded, the sub packages will
        # always be loaded, regardless if they are there or not. This makes
        # sense, IMO, because stubs take preference, even if the original
        # library doesn't provide a module (it could be dynamic). ~dave
        map_ = _merge_create_stub_map(
            [PathInfo(p, is_third_party=False) for p in paths])

    if map_ is not None:
        path_info = map_.get(import_name)
        if path_info is not None and (not path_info.is_third_party
                                      or python_value_set):
            return _try_to_load_stub_from_file(
                inference_state,
                python_value_set,
                file_io=FileIO(path_info.path),
                import_names=import_names,
            )
Esempio n. 3
0
    def parse_and_get_code(self, code=None, path=None,
                           use_latest_grammar=False, file_io=None, **kwargs):
        if path is not None:
            path = str(path)
        if code is None:
            if file_io is None:
                file_io = FileIO(path)
            code = file_io.read()
        # We cannot just use parso, because it doesn't use errors='replace'.
        code = parso.python_bytes_to_unicode(code, encoding='utf-8', errors='replace')

        if len(code) > settings._cropped_file_size:
            code = code[:settings._cropped_file_size]

        grammar = self.latest_grammar if use_latest_grammar else self.grammar
        return grammar.parse(code=code, path=path, file_io=file_io, **kwargs), code
Esempio n. 4
0
    def get_file_ios_to_check():
        for folder_io, base_names in folders_with_names_to_be_checked:
            for file_io in check_directory(folder_io):
                yield file_io, base_names

        for p in settings.additional_dynamic_modules:
            p = os.path.abspath(p)
            if p not in used_mod_paths:
                yield FileIO(p), None
Esempio n. 5
0
def test_get_modules_containing_name(evaluator, path, goal, is_package):
    module = imports._load_python_module(
        evaluator,
        FileIO(path),
        import_names=('ok', 'lala', 'x'),
        is_package=is_package,
    )
    assert module
    input_module, found_module = imports.get_modules_containing_name(
        evaluator, [module], 'string_that_only_exists_here')
    assert input_module is module
    assert found_module.string_names == goal
Esempio n. 6
0
def test_get_modules_containing_name(inference_state, path, goal, is_package):
    module = imports._load_python_module(
        inference_state,
        FileIO(path),
        import_names=('ok', 'lala', 'x'),
        is_package=is_package,
    )
    assert module
    module_context = module.as_context()
    input_module, found_module = imports.get_module_contexts_containing_name(
        inference_state, [module_context], 'string_that_only_exists_here')
    assert input_module is module_context
    assert found_module.string_names == goal
Esempio n. 7
0
def _get_paths_from_buildout_script(inference_state, buildout_script_path):
    file_io = FileIO(str(buildout_script_path))
    try:
        module_node = inference_state.parse(
            file_io=file_io, cache=True, cache_path=settings.cache_directory)
    except IOError:
        debug.warning('Error trying to read buildout_script: %s',
                      buildout_script_path)
        return

    from jedi.inference.value import ModuleValue
    module_context = ModuleValue(
        inference_state,
        module_node,
        file_io=file_io,
        string_names=None,
        code_lines=get_cached_code_lines(inference_state.grammar,
                                         str(buildout_script_path)),
    ).as_context()
    yield from check_sys_path_modifications(module_context)
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
    file_io = FileIO(buildout_script_path)
    try:
        module_node = evaluator.parse(file_io=file_io,
                                      cache=True,
                                      cache_path=settings.cache_directory)
    except IOError:
        debug.warning('Error trying to read buildout_script: %s',
                      buildout_script_path)
        return

    from jedi.evaluate.context import ModuleContext
    module = ModuleContext(
        evaluator,
        module_node,
        file_io,
        string_names=None,
        code_lines=get_cached_code_lines(evaluator.grammar,
                                         buildout_script_path),
    )
    for path in check_sys_path_modifications(module):
        yield path
Esempio n. 9
0
def _load_from_typeshed(inference_state, python_value_set, parent_module_value, import_names):
    import_name = import_names[-1]
    map_ = None
    if len(import_names) == 1:
        map_ = _cache_stub_file_map(inference_state.grammar.version_info)
        import_name = _IMPORT_MAP.get(import_name, import_name)
    elif isinstance(parent_module_value, ModuleValue):
        if not parent_module_value.is_package():
            # Only if it's a package (= a folder) something can be
            # imported.
            return None
        path = parent_module_value.py__path__()
        map_ = _merge_create_stub_map(path)

    if map_ is not None:
        path = map_.get(import_name)
        if path is not None:
            return _try_to_load_stub_from_file(
                inference_state,
                python_value_set,
                file_io=FileIO(path),
                import_names=import_names,
            )
Esempio n. 10
0
def _load_from_typeshed(evaluator, actual_context_set, parent_module_context,
                        import_names):
    import_name = import_names[-1]
    map_ = None
    if len(import_names) == 1:
        map_ = _cache_stub_file_map(evaluator.grammar.version_info)
    elif isinstance(parent_module_context, StubModuleContext):
        if not parent_module_context.is_package:
            # Only if it's a package (= a folder) something can be
            # imported.
            return None
        path = parent_module_context.py__path__()
        map_ = _merge_create_stub_map(path)

    if map_ is not None:
        path = map_.get(import_name)
        if path is not None:
            return _try_to_load_stub_from_file(
                evaluator,
                actual_context_set,
                file_io=FileIO(path),
                import_names=import_names,
            )
Esempio n. 11
0
def _try_to_load_stub(inference_state, import_names, python_value_set,
                      parent_module_value, sys_path):
    """
    Trying to load a stub for a set of import_names.

    This is modelled to work like "PEP 561 -- Distributing and Packaging Type
    Information", see https://www.python.org/dev/peps/pep-0561.
    """
    if parent_module_value is None and len(import_names) > 1:
        try:
            parent_module_value = try_to_load_stub_cached(
                inference_state,
                import_names[:-1],
                NO_VALUES,
                parent_module_value=None,
                sys_path=sys_path)
        except KeyError:
            pass

    # 1. Try to load foo-stubs folders on path for import name foo.
    if len(import_names) == 1:
        # foo-stubs
        for p in sys_path:
            p = cast_path(p)
            init = os.path.join(
                p, *import_names) + '-stubs' + os.path.sep + '__init__.pyi'
            m = _try_to_load_stub_from_file(
                inference_state,
                python_value_set,
                file_io=FileIO(init),
                import_names=import_names,
            )
            if m is not None:
                return m
        if import_names[0] == 'django' and python_value_set:
            return _try_to_load_stub_from_file(
                inference_state,
                python_value_set,
                file_io=FileIO(DJANGO_INIT_PATH),
                import_names=import_names,
            )

    # 2. Try to load pyi files next to py files.
    for c in python_value_set:
        try:
            method = c.py__file__
        except AttributeError:
            pass
        else:
            file_path = method()
            file_paths = []
            if c.is_namespace():
                file_paths = [
                    os.path.join(p, '__init__.pyi') for p in c.py__path__()
                ]
            elif file_path is not None and file_path.endswith('.py'):
                file_paths = [file_path + 'i']

            for file_path in file_paths:
                m = _try_to_load_stub_from_file(
                    inference_state,
                    python_value_set,
                    # The file path should end with .pyi
                    file_io=FileIO(file_path),
                    import_names=import_names,
                )
                if m is not None:
                    return m

    # 3. Try to load typeshed
    m = _load_from_typeshed(inference_state, python_value_set,
                            parent_module_value, import_names)
    if m is not None:
        return m

    # 4. Try to load pyi file somewhere if python_value_set was not defined.
    if not python_value_set:
        if parent_module_value is not None:
            check_path = parent_module_value.py__path__() or []
            # In case import_names
            names_for_path = (import_names[-1], )
        else:
            check_path = sys_path
            names_for_path = import_names

        for p in check_path:
            m = _try_to_load_stub_from_file(
                inference_state,
                python_value_set,
                file_io=FileIO(os.path.join(p, *names_for_path) + '.pyi'),
                import_names=import_names,
            )
            if m is not None:
                return m

    # If no stub is found, that's fine, the calling function has to deal with
    # it.
    return None
Esempio n. 12
0
def _find_syntax_node_name(inference_state, python_object):
    original_object = python_object
    try:
        python_object = _get_object_to_check(python_object)
        path = inspect.getsourcefile(python_object)
    except TypeError:
        # The type might not be known (e.g. class_with_dict.__weakref__)
        return None
    if path is None or not os.path.exists(path):
        # The path might not exist or be e.g. <stdin>.
        return None

    file_io = FileIO(path)
    module_node = _load_module(inference_state, path)

    if inspect.ismodule(python_object):
        # We don't need to check names for modules, because there's not really
        # a way to write a module in a module in Python (and also __name__ can
        # be something like ``email.utils``).
        code_lines = get_cached_code_lines(inference_state.grammar, path)
        return module_node, module_node, file_io, code_lines

    try:
        name_str = python_object.__name__
    except AttributeError:
        # Stuff like python_function.__code__.
        return None

    if name_str == '<lambda>':
        return None  # It's too hard to find lambdas.

    # Doesn't always work (e.g. os.stat_result)
    names = module_node.get_used_names().get(name_str, [])
    # Only functions and classes are relevant. If a name e.g. points to an
    # import, it's probably a builtin (like collections.deque) and needs to be
    # ignored.
    names = [
        n for n in names
        if n.parent.type in ('funcdef', 'classdef') and n.parent.name == n
    ]
    if not names:
        return None

    try:
        code = python_object.__code__
        # By using the line number of a code object we make the lookup in a
        # file pretty easy. There's still a possibility of people defining
        # stuff like ``a = 3; foo(a); a = 4`` on the same line, but if people
        # do so we just don't care.
        line_nr = code.co_firstlineno
    except AttributeError:
        pass
    else:
        line_names = [name for name in names if name.start_pos[0] == line_nr]
        # There's a chance that the object is not available anymore, because
        # the code has changed in the background.
        if line_names:
            names = line_names

    code_lines = get_cached_code_lines(inference_state.grammar, path)
    # It's really hard to actually get the right definition, here as a last
    # resort we just return the last one. This chance might lead to odd
    # completions at some points but will lead to mostly correct type
    # inference, because people tend to define a public name in a module only
    # once.
    tree_node = names[-1].parent
    if tree_node.type == 'funcdef' and get_api_type(
            original_object) == 'instance':
        # If an instance is given and we're landing on a function (e.g.
        # partial in 3.5), something is completely wrong and we should not
        # return that.
        return None
    return module_node, tree_node, file_io, code_lines
Esempio n. 13
0
def _find_syntax_node_name(evaluator, access_handle):
    # TODO accessing this is bad, but it probably doesn't matter that much,
    # because we're working with interpreteters only here.
    python_object = access_handle.access._obj
    try:
        python_object = _get_object_to_check(python_object)
        path = inspect.getsourcefile(python_object)
    except TypeError:
        # The type might not be known (e.g. class_with_dict.__weakref__)
        return None
    if path is None or not os.path.exists(path):
        # The path might not exist or be e.g. <stdin>.
        return None

    file_io = FileIO(path)
    module_node = _load_module(evaluator, path)

    if inspect.ismodule(python_object):
        # We don't need to check names for modules, because there's not really
        # a way to write a module in a module in Python (and also __name__ can
        # be something like ``email.utils``).
        code_lines = get_cached_code_lines(evaluator.grammar, path)
        return module_node, module_node, file_io, code_lines

    try:
        name_str = python_object.__name__
    except AttributeError:
        # Stuff like python_function.__code__.
        return None

    if name_str == '<lambda>':
        return None  # It's too hard to find lambdas.

    # Doesn't always work (e.g. os.stat_result)
    names = module_node.get_used_names().get(name_str, [])
    names = [n for n in names if n.is_definition()]
    if not names:
        return None

    try:
        code = python_object.__code__
        # By using the line number of a code object we make the lookup in a
        # file pretty easy. There's still a possibility of people defining
        # stuff like ``a = 3; foo(a); a = 4`` on the same line, but if people
        # do so we just don't care.
        line_nr = code.co_firstlineno
    except AttributeError:
        pass
    else:
        line_names = [name for name in names if name.start_pos[0] == line_nr]
        # There's a chance that the object is not available anymore, because
        # the code has changed in the background.
        if line_names:
            names = line_names

    code_lines = get_cached_code_lines(evaluator.grammar, path)
    # It's really hard to actually get the right definition, here as a last
    # resort we just return the last one. This chance might lead to odd
    # completions at some points but will lead to mostly correct type
    # inference, because people tend to define a public name in a module only
    # once.
    return module_node, names[-1].parent, file_io, code_lines