Ejemplo n.º 1
0
def source_to_unicode(source, encoding=None):
    def detect_encoding():
        """
        For the implementation of encoding definitions in Python, look at:
        - http://www.python.org/dev/peps/pep-0263/
        - http://docs.python.org/2/reference/lexical_analysis.html#encoding-declarations
        """
        byte_mark = literal_eval(r"b'\xef\xbb\xbf'")
        if source.startswith(byte_mark):
            # UTF-8 byte-order mark
            return 'utf-8'

        first_two_lines = re.match(br'(?:[^\n]*\n){0,2}', source).group(0)
        possible_encoding = re.search(br"coding[=:]\s*([-\w.]+)",
                                      first_two_lines)
        if possible_encoding:
            return possible_encoding.group(1)
        else:
            # the default if nothing else has been set -> PEP 263
            return encoding if encoding is not None else 'utf-8'

    if isinstance(source, unicode):
        # only cast str/bytes
        return source

    encoding = detect_encoding()
    if not isinstance(encoding, unicode):
        encoding = unicode(encoding, 'utf-8', 'replace')
    # cast to unicode by default
    return unicode(source, encoding, 'replace')
Ejemplo n.º 2
0
    def description(self):
        """
        A description of the :class:`.Definition` object, which is heavily used
        in testing. e.g. for ``isinstance`` it returns ``def isinstance``.
        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var
        if isinstance(d, pr.Name):
            d = d.parent

        if isinstance(d, er.Array):
            d = 'class ' + d.type
        elif isinstance(d, (pr.Class, er.Class, er.Instance)):
            d = 'class ' + unicode(d.name)
        elif isinstance(d, (er.Function, pr.Function)):
            d = 'def ' + unicode(d.name)
        elif isinstance(d, pr.Module):
            # only show module name
            d = 'module %s' % self.module_name
        elif self.is_keyword:
            d = 'keyword %s' % d.name
        else:
            d = d.get_code().replace('\n', '')
        return d
Ejemplo n.º 3
0
def _check_isinstance_type(evaluator, stmt, search_name_part):
    try:
        expression_list = stmt.expression_list()
        # this might be removed if we analyze and, etc
        assert len(expression_list) == 1
        call = expression_list[0]
        assert isinstance(call, pr.Call) and str(call.name) == 'isinstance'
        assert bool(call.execution)

        # isinstance check
        isinst = call.execution.values
        assert len(isinst) == 2  # has two params
        obj, classes = [statement.expression_list() for statement in isinst]
        assert len(obj) == 1
        assert len(classes) == 1
        assert isinstance(obj[0], pr.Call)

        # names fit?
        assert unicode(obj[0].name) == unicode(search_name_part)
        assert isinstance(classes[0], pr.StatementElement)  # can be type or tuple
    except AssertionError:
        return []

    result = []
    for c in evaluator.eval_call(classes[0]):
        for typ in (c.get_index_types() if isinstance(c, iterable.Array) else [c]):
            result += evaluator.execute(typ)
    return result
Ejemplo n.º 4
0
    def name(self):
        """
        Name of variable/function/class/module.

        For example, for ``x = None`` it returns ``'x'``.

        :rtype: str or None
        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var

        if isinstance(d, pr.Name):
            return d.names[-1] if d.names else None
        elif isinstance(d, er.Array):
            return unicode(d.type)
        elif isinstance(d, (pr.Class, er.Class, er.Instance,
                            er.Function, pr.Function)):
            return unicode(d.name)
        elif isinstance(d, pr.Module):
            return self.module_name
        elif isinstance(d, pr.Import):
            try:
                return d.get_defined_names()[0].names[-1]
            except (AttributeError, IndexError):
                return None
        elif isinstance(d, pr.Statement):
            try:
                return d.assignment_details[0][1].values[0][0].name.names[-1]
            except IndexError:
                return None
        return None
 def in_iterable(name, iterable):
     """ checks if the name is in the variable 'iterable'. """
     for i in iterable:
         # Only the last name is important, because these names have a
         # maximal length of 2, with the first one being `self`.
         if unicode(i.names[-1]) == unicode(name.names[-1]):
             return True
     return False
Ejemplo n.º 6
0
 def test_multibyte_script(self):
     """ `jedi.Script` must accept multi-byte string source. """
     try:
         code = unicode("import datetime; datetime.d")
         comment = utf8("# multi-byte comment あいうえおä")
         s = (unicode('%s\n%s') % (code, comment)).encode('utf-8')
     except NameError:
         pass  # python 3 has no unicode method
     else:
         assert len(self.completions(s, (1, len(code))))
Ejemplo n.º 7
0
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: Add the the name (if import) to the result.
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, pr.Import) \
                        and d.start_pos == (0, 0):
                    i = imports.ImportPath(self._evaluator, d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        user_stmt = self._parser.user_stmt()
        if next(context) in ('class', 'def'):
            user_scope = self._parser.user_scope()
            definitions = set([user_scope.name])
            search_name = unicode(user_scope.name)
        elif isinstance(user_stmt, pr.Import):
            s, name_part = helpers.get_on_import_stmt(self._evaluator,
                                                   self._user_context, user_stmt)
            try:
                definitions = [s.follow(is_goto=True)[0]]
            except IndexError:
                definitions = []
            search_name = unicode(name_part)

            if add_import_name:
                import_name = user_stmt.get_defined_names()
                # imports have only one name
                if not user_stmt.star \
                        and name_part == import_name[0].names[-1]:
                    definitions.append(import_name[0])
        else:
            stmt = self._get_under_cursor_stmt(goto_path)
            defs, search_name = self._evaluator.goto(stmt)
            definitions = follow_inexistent_imports(defs)
            if isinstance(user_stmt, pr.Statement):
                c = user_stmt.expression_list()
                if c and not isinstance(c[0], (str, unicode)) \
                        and c[0].start_pos > self._pos \
                        and not re.search(r'\.\w+$', goto_path):
                    # The cursor must be after the start, otherwise the
                    # statement is just an assignee.
                    definitions = [user_stmt]
        return definitions, search_name
Ejemplo n.º 8
0
Archivo: api.py Proyecto: lvh/jedi
    def _goto(self, add_import_name=False):
        """
        Used for goto_assignments and usages.

        :param add_import_name: TODO add description
        """
        def follow_inexistent_imports(defs):
            """ Imports can be generated, e.g. following
            `multiprocessing.dummy` generates an import dummy in the
            multiprocessing module. The Import doesn't exist -> follow.
            """
            definitions = set(defs)
            for d in defs:
                if isinstance(d.parent, pr.Import) \
                                        and d.start_pos == (0, 0):
                    i = imports.ImportPath(d.parent).follow(is_goto=True)
                    definitions.remove(d)
                    definitions |= follow_inexistent_imports(i)
            return definitions

        goto_path = self._module.get_path_under_cursor()
        context = self._module.get_context()
        user_stmt = self._parser.user_stmt
        if next(context) in ('class', 'def'):
            user_scope = self._parser.user_scope
            definitions = set([user_scope.name])
            search_name = unicode(user_scope.name)
        elif isinstance(user_stmt, pr.Import):
            s, name_part = self._get_on_import_stmt()
            try:
                definitions = [s.follow(is_goto=True)[0]]
            except IndexError:
                definitions = []
            search_name = unicode(name_part)

            if add_import_name:
                import_name = user_stmt.get_defined_names()
                # imports have only one name
                if name_part == import_name[0].names[-1]:
                    definitions.append(import_name[0])
        else:
            stmt = self._get_under_cursor_stmt(goto_path)
            defs, search_name = evaluate.goto(stmt)
            definitions = follow_inexistent_imports(defs)
            if isinstance(user_stmt, pr.Statement):
                call = user_stmt.get_commands()[0]
                if not isinstance(call, (str, unicode)) and \
                   call.start_pos > self.pos:
                    # The cursor must be after the start, otherwise the
                    # statement is just an assignee.
                    definitions = [user_stmt]
        return definitions, search_name
Ejemplo n.º 9
0
    def has_explicit_absolute_import(self):
        """
        Checks if imports in this module are explicitly absolute, i.e. there
        is a ``__future__`` import.
        """
        for imp in self.imports:
            if imp.from_ns is None or imp.namespace is None:
                continue

            namespace, feature = imp.from_ns.names[0], imp.namespace.names[0]
            if unicode(namespace) == "__future__" and unicode(feature) == "absolute_import":
                return True

        return False
Ejemplo n.º 10
0
    def description(self):
        """
        A description of the :class:`.Definition` object, which is heavily used
        in testing. e.g. for ``isinstance`` it returns ``def isinstance``.

        Example:

        >>> from jedi import Script
        >>> source = '''
        ... def f():
        ...     pass
        ...
        ... class C:
        ...     pass
        ...
        ... variable = f or C'''
        >>> script = Script(source, column=3)  # line is maximum by default
        >>> defs = script.goto_definitions()
        >>> defs = sorted(defs, key=lambda d: d.line)
        >>> defs
        [<Definition def f>, <Definition class C>]
        >>> str(defs[0].description)  # strip literals in python2
        'def f'
        >>> str(defs[1].description)
        'class C'

        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var
        if isinstance(d, pr.Name):
            d = d.parent

        if isinstance(d, er.Array):
            d = "class " + d.type
        elif isinstance(d, (pr.Class, er.Class, er.Instance)):
            d = "class " + unicode(d.name)
        elif isinstance(d, (er.Function, pr.Function)):
            d = "def " + unicode(d.name)
        elif isinstance(d, pr.Module):
            # only show module name
            d = "module %s" % self.module_name
        elif self.is_keyword:
            d = "keyword %s" % d.name
        else:
            code = d.get_code().replace("\n", "")
            max_len = 20
            d = (code[:max_len] + "...") if len(code) > max_len + 3 else code
        return d
Ejemplo n.º 11
0
    def description(self):
        """
        A description of the :class:`.Definition` object, which is heavily used
        in testing. e.g. for ``isinstance`` it returns ``def isinstance``.

        Example:

        >>> from jedi import Script
        >>> source = '''
        ... def f():
        ...     pass
        ...
        ... class C:
        ...     pass
        ...
        ... variable = f or C'''
        >>> script = Script(source, column=3)  # line is maximum by default
        >>> defs = script.goto_definitions()
        >>> defs = sorted(defs, key=lambda d: d.line)
        >>> defs
        [<Definition def f>, <Definition class C>]
        >>> str(defs[0].description)  # strip literals in python2
        'def f'
        >>> str(defs[1].description)
        'class C'

        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var
        if isinstance(d, pr.Name):
            d = d.parent

        if isinstance(d, compiled.CompiledObject):
            d = d.type() + ' ' + d.name
        elif isinstance(d, iterable.Array):
            d = 'class ' + d.type
        elif isinstance(d, (pr.Class, er.Class, er.Instance)):
            d = 'class ' + unicode(d.name)
        elif isinstance(d, (er.Function, pr.Function)):
            d = 'def ' + unicode(d.name)
        elif isinstance(d, pr.Module):
            # only show module name
            d = 'module %s' % self.module_name
        elif self.is_keyword:
            d = 'keyword %s' % d.name
        else:
            d = d.get_code().replace('\n', '').replace('\r', '')
        return d
Ejemplo n.º 12
0
        def assemble(command_list, assignment=None):
            pieces = [c.get_code() if isinstance(c, Simple) else c.string if
isinstance(c, (tokenize.Token, Operator)) else unicode(c)
                      for c in command_list]
            if assignment is None:
                return ''.join(pieces)
            return '%s %s ' % (''.join(pieces), assignment)
Ejemplo n.º 13
0
 def raw_doc(self):
     """ Returns a cleaned version of the docstring token. """
     try:
         # Returns a literal cleaned version of the ``Token``.
         return unicode(cleandoc(literal_eval(self._doc_token.string)))
     except AttributeError:
         return u('')
Ejemplo n.º 14
0
    def get_call_signature(self, width=72, funcname=None):
        """
        Generate call signature of this function.

        :param width: Fold lines if a line is longer than this value.
        :type width: int
        :arg funcname: Override function name when given.
        :type funcname: str

        :rtype: str
        """
        l = unicode(funcname or self.name.names[-1]) + '('
        lines = []
        for (i, p) in enumerate(self.params):
            code = p.get_code(False)
            if i != len(self.params) - 1:
                code += ', '
            if len(l + code) > width:
                lines.append(l[:-1] if l[-1] == ' ' else l)
                l = code
            else:
                l += code
        if l:
            lines.append(l)
        lines[-1] += ')'
        return '\n'.join(lines)
Ejemplo n.º 15
0
    def description(self):
        """
        A textual description of the object.

        Example:

        >>> from jedi import Script
        >>> source = '''
        ... def f():
        ...     pass
        ...
        ... class C:
        ...     pass
        ...
        ... variable = f or C'''
        >>> script = Script(source, len(source.splitlines()), 3, 'example.py')
        >>> defs = script.definition()                      # doctest: +SKIP
        >>> defs = sorted(defs, key=lambda d: d.line)       # doctest: +SKIP
        >>> defs                                            # doctest: +SKIP
        [<Definition def f>, <Definition class C>]
        >>> defs[0].description                             # doctest: +SKIP
        'def f'
        >>> defs[1].description                             # doctest: +SKIP
        'class C'

        """
        return unicode(self._definition)
Ejemplo n.º 16
0
def _get_buildout_scripts(module_path):
    """
    if there is a 'buildout.cfg' file in one of the parent directories of the
    given module it will return a list of all files in the buildout bin
    directory that look like python files.

    :param module_path: absolute path to the module.
    :type module_path: str
    """
    project_root = _get_parent_dir_with_file(module_path, 'buildout.cfg')
    if not project_root:
        return []
    bin_path = os.path.join(project_root, 'bin')
    if not os.path.exists(bin_path):
        return []
    extra_module_paths = []
    for filename in os.listdir(bin_path):
        try:
            filepath = os.path.join(bin_path, filename)
            with open(filepath, 'r') as f:
                firstline = f.readline()
                if firstline.startswith('#!') and 'python' in firstline:
                    extra_module_paths.append(filepath)
        except IOError as e:
            # either permission error or race cond. because file got deleted
            # ignore
            debug.warning(unicode(e))
            continue
    return extra_module_paths
Ejemplo n.º 17
0
def collect_dir_tests(base_dir, test_files, check_thirdparty=False):
    for f_name in os.listdir(base_dir):
        files_to_execute = [a for a in test_files.items() if f_name.startswith(a[0])]
        lines_to_execute = reduce(lambda x, y: x + y[1], files_to_execute, [])
        if f_name.endswith(".py") and (not test_files or files_to_execute):
            skip = None
            if check_thirdparty:
                lib = f_name.replace('_.py', '')
                try:
                    # there is always an underline at the end.
                    # It looks like: completion/thirdparty/pylab_.py
                    __import__(lib)
                except ImportError:
                    skip = 'Thirdparty-Library %s not found.' % lib

            path = os.path.join(base_dir, f_name)

            if is_py3:
                source = open(path, encoding='utf-8').read()
            else:
                source = unicode(open(path).read(), 'UTF-8')

            for case in collect_file_tests(path, StringIO(source),
                                           lines_to_execute):
                case.source = source
                if skip:
                    case.set_skip(skip)
                yield case
Ejemplo n.º 18
0
    def full_name(self):
        """
        Dot-separated path of this object.

        It is in the form of ``<module>[.<submodule>[...]][.<object>]``.
        It is useful when you want to look up Python manual of the
        object at hand.

        Example:

        >>> from jedi import Script
        >>> source = '''
        ... import os
        ... os.path.join'''
        >>> script = Script(source, 3, len('os.path.join'), 'example.py')
        >>> print(script.goto_definitions()[0].full_name)
        os.path.join

        Notice that it correctly returns ``'os.path.join'`` instead of
        (for example) ``'posixpath.join'``.

        """
        path = [unicode(p) for p in self._path()]
        # TODO add further checks, the mapping should only occur on stdlib.
        if not path:
            return None  # for keywords the path is empty

        with common.ignored(KeyError):
            path[0] = self._mapping[path[0]]
        for key, repl in self._tuple_mapping.items():
            if tuple(path[:len(key)]) == key:
                path = [repl] + path[len(key):]

        return '.'.join(path if path[0] else path[1:])
Ejemplo n.º 19
0
    def _remove_statements(self, stmt):
        """
        This is the part where statements are being stripped.

        Due to lazy evaluation, statements like a = func; b = a; b() have to be
        evaluated.
        """
        evaluator = self._evaluator
        types = []
        # Remove the statement docstr stuff for now, that has to be
        # implemented with the evaluator class.
        #if stmt.docstr:
            #res_new.append(stmt)

        check_instance = None
        if isinstance(stmt, er.InstanceElement) and stmt.is_class_var:
            check_instance = stmt.instance
            stmt = stmt.var

        types += evaluator.eval_statement(stmt, seek_name=unicode(self.name_str))

        if check_instance is not None:
            # class renames
            types = [er.InstanceElement(evaluator, check_instance, a, True)
                     if isinstance(a, (er.Function, pr.Function))
                     else a for a in types]
        return types
Ejemplo n.º 20
0
def _load_faked_module(module):
    module_name = module.__name__
    if module_name == '__builtin__' and not is_py3:
        module_name = 'builtins'

    try:
        return modules[module_name]
    except KeyError:
        path = os.path.dirname(os.path.abspath(__file__))
        try:
            with open(os.path.join(path, 'fake', module_name) + '.pym') as f:
                source = f.read()
        except IOError:
            modules[module_name] = None
            return
        modules[module_name] = m = parse(unicode(source))

        if module_name == 'builtins' and not is_py3:
            # There are two implementations of `open` for either python 2/3.
            # -> Rename the python2 version (`look at fake/builtins.pym`).
            open_func = _search_scope(m, 'open')
            open_func.children[1].value = 'open_python3'
            open_func = _search_scope(m, 'open_python2')
            open_func.children[1].value = 'open'
        return m
Ejemplo n.º 21
0
    def raw_doc(self):
        """ Returns a cleaned version of the docstring token. """
        if isinstance(self, Module):
            node = self.children[0]
        elif isinstance(self, ClassOrFunc):
            node = self.children[self.children.index(':') + 1]
            if is_node(node, 'suite'):  # Normally a suite
                node = node.children[2]  # -> NEWLINE INDENT stmt
        else:  # ExprStmt
            simple_stmt = self.parent
            c = simple_stmt.parent.children
            index = c.index(simple_stmt)
            if not index:
                return ''
            node = c[index - 1]

        if is_node(node, 'simple_stmt'):
            node = node.children[0]

        if node.type == 'string':
            # TODO We have to check next leaves until there are no new
            # leaves anymore that might be part of the docstring. A
            # docstring can also look like this: ``'foo' 'bar'
            # Returns a literal cleaned version of the ``Token``.
            cleaned = cleandoc(literal_eval(node.value))
            # Since we want the docstr output to be always unicode, just
            # force it.
            if is_py3 or isinstance(cleaned, unicode):
                return cleaned
            else:
                return unicode(cleaned, 'UTF-8', 'replace')
        return ''
Ejemplo n.º 22
0
Archivo: usages.py Proyecto: Axure/jedi
def usages(evaluator, definition_names, mods):
    """
    :param definitions: list of Name
    """
    def compare_array(definitions):
        """ `definitions` are being compared by module/start_pos, because
        sometimes the id's of the objects change (e.g. executions).
        """
        result = []
        for d in definitions:
            module = d.get_parent_until()
            result.append((module, d.start_pos))
        return result

    search_name = unicode(list(definition_names)[0])
    compare_definitions = compare_array(definition_names)
    mods |= set([d.get_parent_until() for d in definition_names])
    definitions = []
    for m in imports.get_modules_containing_name(evaluator, mods, search_name):
        try:
            check_names = m.used_names[search_name]
        except KeyError:
            continue
        for name in check_names:

            result = evaluator.goto(name)
            if [c for c in compare_array(result) if c in compare_definitions]:
                definitions.append(classes.Definition(evaluator, name))
                # Previous definitions might be imports, so include them
                # (because goto might return that import name).
                compare_definitions += compare_array([name])
    return definitions
Ejemplo n.º 23
0
def _load_faked_module(evaluator, module_name):
    try:
        return fake_modules[module_name]
    except KeyError:
        pass

    check_module_name = module_name
    if module_name == '__builtin__' and evaluator.environment.version_info.major == 2:
        check_module_name = 'builtins'

    try:
        path = _path_dict[check_module_name]
    except KeyError:
        fake_modules[module_name] = None
        return

    with open(path) as f:
        source = f.read()

    fake_modules[module_name] = m = evaluator.latest_grammar.parse(unicode(source))

    if check_module_name != module_name:
        # There are two implementations of `open` for either python 2/3.
        # -> Rename the python2 version (`look at fake/builtins.pym`).
        open_func = _search_scope(m, 'open')
        open_func.children[1].value = 'open_python3'
        open_func = _search_scope(m, 'open_python2')
        open_func.children[1].value = 'open'
    return m
Ejemplo n.º 24
0
def _fix_forward_reference(context, node):
    evaled_nodes = context.eval_node(node)
    if len(evaled_nodes) != 1:
        debug.warning("Eval'ed typing index %s should lead to 1 object, "
                      " not %s" % (node, evaled_nodes))
        return node
    evaled_node = list(evaled_nodes)[0]
    if isinstance(evaled_node, compiled.CompiledObject) and \
            isinstance(evaled_node.obj, str):
        try:
            new_node = context.evaluator.grammar.parse(
                _compatibility.unicode(evaled_node.obj),
                start_symbol='eval_input',
                error_recovery=False
            )
        except ParserSyntaxError:
            debug.warning('Annotation not parsed: %s' % evaled_node.obj)
            return node
        else:
            module = node.get_root_node()
            parser_utils.move(new_node, module.end_pos[0])
            new_node.parent = context.tree_node
            return new_node
    else:
        return node
Ejemplo n.º 25
0
    def _does_scope_break_immediately(self, scope, name_list_scope):
        """
        In comparison to everthing else, if/while/etc doesn't break directly,
        because there are multiple different places in which a variable can be
        defined.
        """
        if isinstance(scope, pr.Flow) \
                or isinstance(scope, pr.KeywordStatement) and scope.name == 'global':

            # Check for `if foo is not None`, because Jedi is not interested in
            # None values, so this is the only branch we actually care about.
            # ATM it carries the same issue as the isinstance checks. It
            # doesn't work with instance variables (self.foo).
            if isinstance(scope, pr.Flow) and scope.command in ('if', 'while'):
                try:
                    expression_list = scope.inputs[0].expression_list()
                except IndexError:
                    pass
                else:
                    p = precedence.create_precedence(expression_list)
                    if (isinstance(p, precedence.Precedence)
                            and p.operator.string == 'is not'
                            and p.right.get_code() == 'None'
                            and p.left.get_code() == unicode(self.name_str)):
                        return True

            if isinstance(name_list_scope, er.Class):
                name_list_scope = name_list_scope.base
            return scope == name_list_scope
        else:
            return True
Ejemplo n.º 26
0
def _get_buildout_script_paths(search_path):
    """
    if there is a 'buildout.cfg' file in one of the parent directories of the
    given module it will return a list of all files in the buildout bin
    directory that look like python files.

    :param search_path: absolute path to the module.
    :type search_path: str
    """
    project_root = _get_parent_dir_with_file(search_path, 'buildout.cfg')
    if not project_root:
        return
    bin_path = os.path.join(project_root, 'bin')
    if not os.path.exists(bin_path):
        return

    for filename in os.listdir(bin_path):
        try:
            filepath = os.path.join(bin_path, filename)
            with open(filepath, 'r') as f:
                firstline = f.readline()
                if firstline.startswith('#!') and 'python' in firstline:
                    yield filepath
        except (UnicodeDecodeError, IOError) as e:
            # Probably a binary file; permission error or race cond. because
            # file got deleted. Ignore it.
            debug.warning(unicode(e))
            continue
Ejemplo n.º 27
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`api_classes.Usage` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`api_classes.Usage`
        """
        user_stmt = self._parser.user_stmt
        definitions, search_name = self._goto(add_import_name=True)
        if isinstance(user_stmt, pr.Statement) \
                    and self.pos < user_stmt.get_commands()[0].start_pos:
            # the search_name might be before `=`
            definitions = [v for v in user_stmt.set_vars
                                if unicode(v.names[-1]) == search_name]
        if not isinstance(user_stmt, pr.Import):
            # import case is looked at with add_import_name option
            definitions = dynamic.usages_add_import_modules(definitions,
                                                                search_name)

        module = set([d.get_parent_until() for d in definitions])
        module.add(self._parser.module)
        names = dynamic.usages(definitions, search_name, module)

        for d in set(definitions):
            if isinstance(d, pr.Module):
                names.append(api_classes.Usage(d, d))
            else:
                names.append(api_classes.Usage(d.names[-1], d))

        return self._sorted_defs(set(names))
def _load_faked_module(module):
    module_name = module.__name__
    if module_name == '__builtin__' and not is_py3:
        module_name = 'builtins'

    try:
        return modules[module_name]
    except KeyError:
        path = os.path.dirname(os.path.abspath(__file__))
        try:
            with open(os.path.join(path, 'fake', module_name) + '.pym') as f:
                source = f.read()
        except IOError:
            modules[module_name] = None
            return
        grammar = load_grammar(version='3.4')
        module = ParserWithRecovery(grammar, unicode(source), module_name).module
        modules[module_name] = module

        if module_name == 'builtins' and not is_py3:
            # There are two implementations of `open` for either python 2/3.
            # -> Rename the python2 version (`look at fake/builtins.pym`).
            open_func = search_scope(module, 'open')
            open_func.children[1] = FakeName('open_python3')
            open_func = search_scope(module, 'open_python2')
            open_func.children[1] = FakeName('open')
        return module
Ejemplo n.º 29
0
    def name(self):
        """
        Name of variable/function/class/module.

        For example, for ``x = None`` it returns ``'x'``.

        :rtype: str or None
        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var

        if isinstance(d, (compiled.CompiledObject, compiled.CompiledName)):
            name = d.name
        elif isinstance(d, pr.Name):
            name = d.names[-1]
        elif isinstance(d, iterable.Array):
            name = d.type
        elif isinstance(d, (pr.Class, er.Class, er.Instance,
                            er.Function, pr.Function)):
            name = d.name
        elif isinstance(d, pr.Module):
            name = self.module_name
        elif isinstance(d, pr.Import):
            try:
                name = d.get_defined_names()[0].names[-1]
            except (AttributeError, IndexError):
                return None
        elif isinstance(d, pr.Statement):
            try:
                expression_list = d.assignment_details[0][0]
                name = expression_list[0].name.names[-1]
            except IndexError:
                if isinstance(d, pr.Param):
                    try:
                        return unicode(d.expression_list()[0].name)
                    except (IndexError, AttributeError):
                        # IndexError for syntax error params
                        # AttributeError for *args/**kwargs
                        pass
                return None
        elif isinstance(d, iterable.Generator):
            return None
        elif isinstance(d, pr.NamePart):
            name = d
        return unicode(name)
Ejemplo n.º 30
0
    def _get_module(self):
        cache.invalidate_star_import_cache(self._path)
        parser = FastParser(self._grammar, self._source, self.path)
        save_parser(self.path, parser, pickling=False)

        module = self._evaluator.wrap(parser.module)
        imports.add_module(self._evaluator, unicode(module.name), module)
        return parser.module
Ejemplo n.º 31
0
    def description(self):
        """Provide a description of the completion object."""
        if self._definition is None:
            return ''
        t = self.type
        if t == 'statement' or t == 'import':
            desc = self._definition.get_code()
        else:
            desc = '.'.join(unicode(p) for p in self._path())

        line = '' if self.in_builtin_module else '@%s' % self.line
        return '%s: %s%s' % (t, desc, line)
Ejemplo n.º 32
0
    def follow(self, is_goto=False):
        if self._evaluator.recursion_detector.push_stmt(self._import):
            # check recursion
            return []

        try:
            module = self._evaluator.wrap(self._import.get_parent_until())
            import_path = self._import.path_for_name(self._name)
            from_import_name = None
            try:
                from_names = self._import.get_from_names()
            except AttributeError:
                # Is an import_name
                pass
            else:
                if len(from_names) + 1 == len(import_path):
                    # We have to fetch the from_names part first and then check
                    # if from_names exists in the modules.
                    from_import_name = import_path[-1]
                    import_path = from_names

            importer = Importer(self._evaluator, tuple(import_path), module,
                                self._import.level)

            types = importer.follow()

            #if self._import.is_nested() and not self.nested_resolve:
            #    scopes = [NestedImportModule(module, self._import)]

            if from_import_name is not None:
                types = list(
                    chain.from_iterable(
                        self._evaluator.find_types(
                            t, unicode(from_import_name), is_goto=is_goto)
                        for t in types))

                if not types:
                    path = import_path + [from_import_name]
                    importer = Importer(self._evaluator, tuple(path), module,
                                        self._import.level)
                    types = importer.follow()
                    # goto only accepts `Name`
                    if is_goto:
                        types = [s.name for s in types]
            else:
                # goto only accepts `Name`
                if is_goto:
                    types = [s.name for s in types]

            debug.dbg('after import: %s', types)
        finally:
            self._evaluator.recursion_detector.pop_stmt()
        return types
Ejemplo n.º 33
0
def _get_typing_replacement_module():
    """
    The idea is to return our jedi replacement for the PEP-0484 typing module
    as discussed at https://github.com/davidhalter/jedi/issues/663
    """
    global _typing_module
    if _typing_module is None:
        typing_path = \
            os.path.abspath(os.path.join(__file__, "../jedi_typing.py"))
        with open(typing_path) as f:
            code = _compatibility.unicode(f.read())
        _typing_module = parse(code)
    return _typing_module
Ejemplo n.º 34
0
 def _handle_for_loops(self, loop):
     # Take the first statement (for has always only
     # one, remember `in`). And follow it.
     if not loop.inputs:
         return []
     result = iterable.get_iterator_types(
         self._evaluator.eval_statement(loop.inputs[0]))
     if len(loop.set_vars) > 1:
         expression_list = loop.set_stmt.expression_list()
         # loops with loop.set_vars > 0 only have one command
         result = _assign_tuples(expression_list[0], result,
                                 unicode(self.name_str))
     return result
Ejemplo n.º 35
0
    def sys_path_with_modifications(self):
        # If you edit e.g. gunicorn, there will be imports like this:
        # `from gunicorn import something`. But gunicorn is not in the
        # sys.path. Therefore look if gunicorn is a parent directory, #56.
        in_path = []
        if self.import_path and self.file_path is not None:
            parts = self.file_path.split(os.path.sep)
            for i, p in enumerate(parts):
                if p == unicode(self.import_path[0]):
                    new = os.path.sep.join(parts[:i])
                    in_path.append(new)

        return in_path + sys_path_with_modifications(self._evaluator, self.module)
Ejemplo n.º 36
0
        def get_posibilities(evaluator, module, func_name):
            try:
                possible_stmts = module.used_names[func_name]
            except KeyError:
                return []

            for stmt in possible_stmts:
                if isinstance(stmt, pr.Import):
                    continue
                calls = helpers.scan_statement_for_calls(stmt, func_name)
                for c in calls:
                    # no execution means that params cannot be set
                    call_path = list(c.generate_call_path())
                    pos = c.start_pos
                    scope = stmt.parent

                    # this whole stuff is just to not execute certain parts
                    # (speed improvement), basically we could just call
                    # ``eval_call_path`` on the call_path and it would
                    # also work.
                    def listRightIndex(lst, value):
                        return len(lst) - lst[-1::-1].index(value) - 1

                    # Need to take right index, because there could be a
                    # func usage before.
                    call_path_simple = [unicode(d) if isinstance(d, pr.NamePart)
                                        else d for d in call_path]
                    i = listRightIndex(call_path_simple, func_name)
                    first, last = call_path[:i], call_path[i + 1:]
                    if not last and not call_path_simple.index(func_name) != i:
                        continue
                    scopes = [scope]
                    if first:
                        scopes = evaluator.eval_call_path(iter(first), scope, pos)
                        pos = None
                    from jedi.evaluate import representation as er
                    for scope in scopes:
                        s = evaluator.find_types(scope, func_name, position=pos,
                                                 search_global=not first,
                                                 resolve_decorator=False)

                        c = [getattr(escope, 'base_func', None) or escope.base
                             for escope in s
                             if escope.isinstance(er.Function, er.Class)]
                        if compare in c:
                            # only if we have the correct function we execute
                            # it, otherwise just ignore it.
                            evaluator.follow_path(iter(last), s, scope)

            return listener.param_possibilities
Ejemplo n.º 37
0
def infer_import(context, tree_name, is_goto=False):
    module_context = context.get_root_context()
    import_node = tree_name.get_parent_until(tree.Import)
    import_path = import_node.path_for_name(tree_name)
    from_import_name = None
    evaluator = context.evaluator
    try:
        from_names = import_node.get_from_names()
    except AttributeError:
        # Is an import_name
        pass
    else:
        if len(from_names) + 1 == len(import_path):
            # We have to fetch the from_names part first and then check
            # if from_names exists in the modules.
            from_import_name = import_path[-1]
            import_path = from_names

    importer = Importer(evaluator, tuple(import_path),
                        module_context, import_node.level)

    types = importer.follow()

    #if import_node.is_nested() and not self.nested_resolve:
    #    scopes = [NestedImportModule(module, import_node)]

    if from_import_name is not None:
        types = unite(
            t.py__getattribute__(
                unicode(from_import_name),
                name_context=context,
                is_goto=is_goto
            ) for t in types
        )

        if not types:
            path = import_path + [from_import_name]
            importer = Importer(evaluator, tuple(path),
                                module_context, import_node.level)
            types = importer.follow()
            # goto only accepts `Name`
            if is_goto:
                types = set(s.name for s in types)
    else:
        # goto only accepts `Name`
        if is_goto:
            types = set(s.name for s in types)

    debug.dbg('after import: %s', types)
    return types
Ejemplo n.º 38
0
def _get_typing_replacement_module(grammar):
    """
    The idea is to return our jedi replacement for the PEP-0484 typing module
    as discussed at https://github.com/davidhalter/jedi/issues/663
    """
    global _typing_module, _typing_module_code_lines
    if _typing_module is None:
        typing_path = \
            os.path.abspath(os.path.join(__file__, "../jedi_typing.py"))
        with open(typing_path) as f:
            code = unicode(f.read())
        _typing_module = grammar.parse(code)
        _typing_module_code_lines = split_lines(code, keepends=True)
    return _typing_module, _typing_module_code_lines
Ejemplo n.º 39
0
 def _get_nested_import_name(self):
     """
     Generates an Import statement, that can be used to fake nested imports.
     """
     i = self._nested_import
     # This is not an existing Import statement. Therefore, set position to
     # 0 (0 is not a valid line number).
     zero = (0, 0)
     names = [unicode(name) for name in i.namespace_names[1:]]
     name = helpers.FakeName(names, self._nested_import)
     new = tree.Import(i._sub_module, zero, zero, name)
     new.parent = self._module
     debug.dbg('Generated a nested import: %s', new)
     return helpers.FakeName(str(i.namespace_names[1]), new)
Ejemplo n.º 40
0
 def _follow_statements_imports(self):
     # imports completion is very complicated and needs to be treated
     # separately in Completion.
     if self._definition.isinstance(
             pr.Import) and self._definition.alias is None:
         i = imports.ImportWrapper(self._evaluator, self._definition, True)
         import_path = i.import_path + (unicode(self._name), )
         try:
             return imports.get_importer(self._evaluator, import_path,
                                         i._importer.module).follow(
                                             self._evaluator)
         except imports.ModuleNotFound:
             pass
     return super(Completion, self)._follow_statements_imports()
Ejemplo n.º 41
0
    def call_signatures(self):
        """
        Return the function object of the call you're currently in.

        E.g. if the cursor is here::

            abs(# <-- cursor is here

        This would return the ``abs`` function. On the other hand::

            abs()# <-- cursor is here

        This would return ``None``.

        :rtype: list of :class:`classes.CallSignature`
        """
        user_stmt = self._parser.user_stmt_with_whitespace()
        call, index = search_call_signatures(user_stmt, self._pos)
        if call is None:
            return []

        stmt_el = call
        while isinstance(stmt_el.parent, pr.StatementElement):
            # Go to parent literal/variable until not possible anymore. This
            # makes it possible to return the whole expression.
            stmt_el = stmt_el.parent
        # We can reset the execution since it's a new object
        # (fast_parent_copy).
        execution_arr, call.execution = call.execution, None

        with common.scale_speed_settings(settings.scale_call_signatures):
            _callable = lambda: self._evaluator.eval_call(stmt_el)
            origins = cache.cache_call_signatures(_callable, self.source,
                                                  self._pos, user_stmt)
        debug.speed('func_call followed')

        key_name = None
        try:
            detail = execution_arr[index].assignment_details[0]
        except IndexError:
            pass
        else:
            try:
                key_name = unicode(detail[0][0].name)
            except (IndexError, AttributeError):
                pass
        return [
            classes.CallSignature(self._evaluator, o, call, index, key_name)
            for o in origins if o.is_callable()
        ]
Ejemplo n.º 42
0
    def get_call_signature(self, width=72, func_name=None):
        """
        Generate call signature of this function.

        :param width: Fold lines if a line is longer than this value.
        :type width: int
        :arg func_name: Override function name when given.
        :type func_name: str

        :rtype: str
        """
        func_name = func_name or self.name
        code = unicode(func_name) + self._get_paramlist_code()
        return '\n'.join(textwrap.wrap(code, width))
Ejemplo n.º 43
0
    def test_unicode_script(self):
        """ normally no unicode objects are being used. (<=2.7) """
        s = unicode("import datetime; datetime.timedelta")
        completions = self.complete(s)
        assert len(completions)
        assert type(completions[0].description) is unicode

        s = utf8("author='öä'; author")
        completions = self.complete(s)
        assert type(completions[0].description) is unicode

        s = utf8("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author")
        s = s.encode('latin-1')
        completions = self.complete(s)
        assert type(completions[0].description) is unicode
Ejemplo n.º 44
0
 def get_code(self):
     if self.type == Call.NAME:
         s = self.name.get_code()
     else:
         if not is_py3k and isinstance(self.name, str)\
                     and "'" not in self.name:
             # This is a very rough spot, because of repr not supporting
             # unicode signs, see `test_unicode_script`.
             s = "'%s'" % unicode(self.name, 'UTF-8')
         else:
             s = '' if self.name is None else repr(self.name)
     if self.execution is not None:
         s += self.execution.get_code()
     if self.next is not None:
         s += '.' + self.next.get_code()
     return s
Ejemplo n.º 45
0
 def _get_nested_import(self, parent):
     """
     See documentation of `self._is_nested_import`.
     Generates an Import statement, that can be used to fake nested imports.
     """
     i = self.import_stmt
     # This is not an existing Import statement. Therefore, set position to
     # 0 (0 is not a valid line number).
     zero = (0, 0)
     names = [(unicode(name_part), name_part.start_pos)
              for name_part in i.namespace.names[1:]]
     n = pr.Name(i._sub_module, names, zero, zero, self.import_stmt)
     new = pr.Import(i._sub_module, zero, zero, n)
     new.parent = parent
     debug.dbg('Generated a nested import: %s', new)
     return new
Ejemplo n.º 46
0
    def description(self):
        """
        Provide a description of the completion object.

        .. todo:: return value is just __repr__ of some objects, improve!
        """
        parent = self._name.parent
        if parent is None:
            return ''
        t = self.type
        if t == 'Statement' or t == 'Import':
            desc = self._definition.get_code(False)
        else:
            desc = '.'.join(unicode(p) for p in self.path)

        line = '' if self.in_builtin_module else '@%s' % self.line
        return '%s: %s%s' % (t, desc, line)
Ejemplo n.º 47
0
def _paths_from_call_expression(module_path, call):
    """ extract the path from either "sys.path.append" or "sys.path.insert" """
    if call.execution is None:
        return
    n = call.name
    if not isinstance(n, pr.Name) or len(n.names) != 3:
        return
    names = [unicode(x) for x in n.names]
    if names[:2] != ['sys', 'path']:
        return
    cmd = names[2]
    exe = call.execution
    if cmd == 'insert' and len(exe) == 2:
        path = _paths_from_insert(module_path, exe)
    elif cmd == 'append' and len(exe) == 1:
        path = _execute_code(module_path, exe.get_code())
    return path and [path] or []
Ejemplo n.º 48
0
    def filter_name(self, scope_generator):
        """
        Filters all variables of a scope (which are defined in the
        `scope_generator`), until the name fits.
        """
        result = []
        for nscope, name_list in scope_generator:
            break_scopes = []
            if not isinstance(nscope, compiled.CompiledObject):
                # Here is the position stuff happening (sorting of variables).
                # Compiled objects don't need that, because there's only one
                # reference.
                name_list = sorted(name_list,
                                   key=lambda n: n.start_pos,
                                   reverse=True)
            for name in name_list:
                if unicode(self.name_str) != name.get_code():
                    continue

                parpar = name.parent.parent
                if name.parent.parent in break_scopes:
                    continue

                if not self._name_is_array_assignment(name):
                    result.append(name)  # `arr[1] =` is not the definition
                # for comparison we need the raw class
                # this means that a definition was found and is not e.g.
                # in if/else.
                if result and self._name_is_break_scope(name):
                    #print result, name.parent, parpar, s
                    if isinstance(parpar, pr.Flow) \
                            or isinstance(parpar, pr.KeywordStatement) \
                            and parpar.name == 'global':
                        s = nscope.base if isinstance(nscope,
                                                      er.Class) else nscope
                        if parpar == s:
                            break
                    else:
                        break
                    break_scopes.append(parpar)
            if result:
                break

        debug.dbg('finder.filter_name "%s" in (%s-%s): %s@%s', self.name_str,
                  self.scope, nscope, u(result), self.position)
        return result
Ejemplo n.º 49
0
    def usages(self, additional_module_paths=()):
        """
        Return :class:`classes.Usage` objects, which contain all
        names that point to the definition of the name under the cursor. This
        is very useful for refactoring (renaming), or to show all usages of a
        variable.

        .. todo:: Implement additional_module_paths

        :rtype: list of :class:`classes.Usage`
        """
        temp, settings.dynamic_flow_information = \
            settings.dynamic_flow_information, False
        user_stmt = self._parser.user_stmt()
        definitions, search_name = self._goto(add_import_name=True)
        if isinstance(user_stmt, pr.Statement):
            c = user_stmt.expression_list()[0]
            if not isinstance(c, unicode) and self._pos < c.start_pos:
                # the search_name might be before `=`
                definitions = [
                    v for v in user_stmt.get_set_vars()
                    if unicode(v.names[-1]) == search_name
                ]
        if not isinstance(user_stmt, pr.Import):
            # import case is looked at with add_import_name option
            definitions = usages.usages_add_import_modules(
                self._evaluator, definitions, search_name)

        module = set([d.get_parent_until() for d in definitions])
        module.add(self._parser.module())
        names = usages.usages(self._evaluator, definitions, search_name,
                              module)

        for d in set(definitions):
            if isinstance(d, pr.Module):
                names.append(usages.Usage(self._evaluator, d, d))
            elif isinstance(d, er.Instance):
                # Instances can be ignored, because they have been created by
                # ``__getattr__``.
                pass
            else:
                names.append(usages.Usage(self._evaluator, d.names[-1], d))

        settings.dynamic_flow_information = temp
        return helpers.sorted_definitions(set(names))
Ejemplo n.º 50
0
def collections_namedtuple(evaluator, obj, arguments):
    """
    Implementation of the namedtuple function.

    This has to be done by processing the namedtuple class template and
    evaluating the result.

    .. note:: |jedi| only supports namedtuples on Python >2.6.

    """
    # Namedtuples are not supported on Python 2.6
    if not hasattr(collections, '_class_template'):
        return set()

    # Process arguments
    # TODO here we only use one of the types, we should use all.
    name = list(_follow_param(evaluator, arguments, 0))[0].obj
    _fields = list(_follow_param(evaluator, arguments, 1))[0]
    if isinstance(_fields, compiled.CompiledObject):
        fields = _fields.obj.replace(',', ' ').split()
    elif isinstance(_fields, iterable.AbstractSequence):
        fields = [
            v.obj for lazy_context in _fields.py__iter__()
            for v in lazy_context.infer() if hasattr(v, 'obj')
        ]
    else:
        return set()

    # Build source
    source = collections._class_template.format(
        typename=name,
        field_names=fields,
        num_fields=len(fields),
        arg_list=', '.join(fields),
        repr_fmt=', '.join(
            collections._repr_template.format(name=name) for name in fields),
        field_defs='\n'.join(
            collections._field_template.format(index=index, name=name)
            for index, name in enumerate(fields)))

    # Parse source
    generated_class = ParserWithRecovery(evaluator.grammar,
                                         unicode(source)).module.subscopes[0]
    return set(
        [er.ClassContext(evaluator, generated_class, evaluator.BUILTINS)])
Ejemplo n.º 51
0
    def check_calls(calls, add_name):
        """
        Calls are processed here. The part before the call is searched and
        compared with the original Array.
        """
        result = []
        for c in calls:
            call_path = list(c.generate_call_path())
            call_path_simple = [
                unicode(n) if isinstance(n, pr.NamePart) else n
                for n in call_path
            ]
            separate_index = call_path_simple.index(add_name)
            if add_name == call_path_simple[-1] or separate_index == 0:
                # this means that there is no execution -> [].append
                # or the keyword is at the start -> append()
                continue
            backtrack_path = iter(call_path[:separate_index])

            position = c.start_pos
            scope = c.get_parent_until(pr.IsScope)

            found = evaluator.eval_call_path(backtrack_path, scope, position)
            if not compare_array in found:
                continue

            params = call_path[separate_index + 1]
            if not params.values:
                continue  # no params: just ignore it
            if add_name in ['append', 'add']:
                for param in params:
                    result += evaluator.eval_statement(param)
            elif add_name in ['insert']:
                try:
                    second_param = params[1]
                except IndexError:
                    continue
                else:
                    result += evaluator.eval_statement(second_param)
            elif add_name in ['extend', 'update']:
                for param in params:
                    iterators = evaluator.eval_statement(param)
                result += get_iterator_types(iterators)
        return result
Ejemplo n.º 52
0
    def _eval_param(self, param):
        evaluator = self._evaluator
        res_new = []
        func = param.parent

        cls = func.parent.get_parent_until((pr.Class, pr.Function))

        from jedi.evaluate.param import ExecutedParam
        if isinstance(cls, pr.Class) and param.position_nr == 0 \
                and not isinstance(param, ExecutedParam):
            # This is where we add self - if it has never been
            # instantiated.
            if isinstance(self.scope, er.InstanceElement):
                res_new.append(self.scope.instance)
            else:
                for inst in evaluator.execute(er.Class(evaluator, cls)):
                    inst.is_generated = True
                    res_new.append(inst)
            return res_new

        # Instances are typically faked, if the instance is not called from
        # outside. Here we check it for __init__ functions and return.
        if isinstance(func, er.InstanceElement) \
                and func.instance.is_generated and str(func.name) == '__init__':
            param = func.var.params[param.position_nr]

        # Add docstring knowledge.
        doc_params = docstrings.follow_param(evaluator, param)
        if doc_params:
            return doc_params

        if not param.is_generated:
            # Param owns no information itself.
            res_new += dynamic.search_params(evaluator, param)
            if not res_new:
                if param.stars:
                    t = 'tuple' if param.stars == 1 else 'dict'
                    typ = evaluator.find_types(compiled.builtin, t)[0]
                    res_new = evaluator.execute(typ)
            if not param.assignment_details:
                # this means that there are no default params,
                # so just ignore it.
                return res_new
        return res_new + evaluator.eval_statement(param, seek_name=unicode(self.name_str))
Ejemplo n.º 53
0
def _paths_from_assignment(statement):
    """
    extracts the assigned strings from an assignment that looks as follows::

    >>> sys.path[0:0] = ['module/path', 'another/module/path']
    """

    names = statement.get_defined_names()
    if len(names) != 1:
        return []
    if [unicode(x) for x in names[0].names] != ['sys', 'path']:
        return []
    expressions = statement.expression_list()
    if len(expressions) != 1 or not isinstance(expressions[0], pr.Array):
        return
    stmts = (s for s in expressions[0].values if isinstance(s, pr.Statement))
    expression_lists = (s.expression_list() for s in stmts)
    return [e.value for exprs in expression_lists for e in exprs
            if isinstance(e, pr.Literal) and e.value]
Ejemplo n.º 54
0
def collections_namedtuple(evaluator, obj, params):
    """
    Implementation of the namedtuple function.

    This has to be done by processing the namedtuple class template and
    evaluating the result.

    .. note:: |jedi| only supports namedtuples on Python >2.6.

    """
    # Namedtuples are not supported on Python 2.6
    if not hasattr(collections, '_class_template'):
        return []

    # Process arguments
    name = _follow_param(evaluator, params, 0)[0].obj
    _fields = _follow_param(evaluator, params, 1)[0]
    if isinstance(_fields, compiled.CompiledObject):
        fields = _fields.obj.replace(',', ' ').split()
    elif isinstance(_fields, iterable.Array):
        try:
            fields = [v.obj for v in _fields.values()]
        except AttributeError:
            return []
    else:
        return []

    # Build source
    source = collections._class_template.format(
        typename=name,
        field_names=fields,
        num_fields=len(fields),
        arg_list=', '.join(fields),
        repr_fmt=', '.join(
            collections._repr_template.format(name=name) for name in fields),
        field_defs='\n'.join(
            collections._field_template.format(index=index, name=name)
            for index, name in enumerate(fields)))

    # Parse source
    generated_class = Parser(evaluator.grammar,
                             unicode(source)).module.subscopes[0]
    return [er.Class(evaluator, generated_class)]
Ejemplo n.º 55
0
    def get_self_attributes(self):
        def add_self_dot_name(name):
            """
            Need to copy and rewrite the name, because names are now
            ``instance_usage.variable`` instead of ``self.variable``.
            """
            n = copy.copy(name)
            n.names = n.names[1:]
            n._get_code = unicode(n.names[-1])
            names.append(InstanceElement(self._evaluator, self, n))

        names = []
        # This loop adds the names of the self object, copies them and removes
        # the self.
        for sub in self.base.subscopes:
            if isinstance(sub, pr.Class):
                continue
            # Get the self name, if there's one.
            self_name = self._get_func_self_name(sub)
            if not self_name:
                continue

            if sub.name.get_code() == '__init__':
                # ``__init__`` is special because the params need are injected
                # this way. Therefore an execution is necessary.
                if not sub.decorators:
                    # __init__ decorators should generally just be ignored,
                    # because to follow them and their self variables is too
                    # complicated.
                    sub = self._get_method_execution(sub)
            for n in sub.get_defined_names():
                # Only names with the selfname are being added.
                # It is also important, that they have a len() of 2,
                # because otherwise, they are just something else
                if unicode(n.names[0]) == self_name and len(n.names) == 2:
                    add_self_dot_name(n)

        if not isinstance(self.base, compiled.CompiledObject):
            for s in self.base.get_super_classes():
                for inst in self._evaluator.execute(s):
                    names += inst.get_self_attributes()
        return names
Ejemplo n.º 56
0
def find_assignments(lhs, results, seek_name):
    """
    Check if `seek_name` is in the left hand side `lhs` of assignment.

    `lhs` can simply be a variable (`pr.Call`) or a tuple/list (`pr.Array`)
    representing the following cases::

        a = 1        # lhs is pr.Call
        (a, b) = 2   # lhs is pr.Array

    :type lhs: pr.Call
    :type results: list
    :type seek_name: str
    """
    if isinstance(lhs, pr.Array):
        return _assign_tuples(lhs, results, seek_name)
    elif unicode(lhs.name.names[-1]) == seek_name:
        return results
    else:
        return []
Ejemplo n.º 57
0
    def name(self):
        """
        Name of variable/function/class/module.

        For example, for ``x = None`` it returns ``'x'``.

        :rtype: str or None
        """
        d = self._definition
        if isinstance(d, er.InstanceElement):
            d = d.var

        if isinstance(d, (compiled.CompiledObject, compiled.CompiledName)):
            name = d.name
        elif isinstance(d, pr.Name):
            name = d.names[-1]
        elif isinstance(d, iterable.Array):
            name = d.type
        elif isinstance(d, (pr.Class, er.Class, er.Instance,
                            er.Function, pr.Function)):
            name = d.name
        elif isinstance(d, pr.Module):
            name = self.module_name
        elif isinstance(d, pr.Import):
            try:
                name = d.get_defined_names()[0].names[-1]
            except (AttributeError, IndexError):
                return None
        elif isinstance(d, pr.Param):
            name = d.get_name()
        elif isinstance(d, pr.Statement):
            try:
                expression_list = d.assignment_details[0][0]
                name = expression_list[0].name.names[-1]
            except IndexError:
                return None
        elif isinstance(d, iterable.Generator):
            return None
        elif isinstance(d, pr.NamePart):
            name = d
        return unicode(name)
Ejemplo n.º 58
0
        def return_value(search_path):
            init_path = self.py__file__()
            if os.path.basename(init_path) == '__init__.py':

                with open(init_path, 'rb') as f:
                    content = common.source_to_unicode(f.read())
                    # these are strings that need to be used for namespace packages,
                    # the first one is ``pkgutil``, the second ``pkg_resources``.
                    options = ('declare_namespace(__name__)',
                               'extend_path(__path__')
                    if options[0] in content or options[1] in content:
                        # It is a namespace, now try to find the rest of the
                        # modules on sys_path or whatever the search_path is.
                        paths = set()
                        for s in search_path:
                            other = os.path.join(s, unicode(self.name))
                            if os.path.isdir(other):
                                paths.add(other)
                        return list(paths)
            # Default to this.
            return [path]
Ejemplo n.º 59
0
def collect_file_tests(lines, lines_to_execute):
    makecase = lambda t: IntegrationTestCase(t, correct, line_nr, column,
                                             start, line)
    start = None
    correct = None
    test_type = None
    for line_nr, line in enumerate(lines):
        line_nr += 1  # py2.5 doesn't know about the additional enumerate param
        if not is_py3k:
            line = unicode(line, 'UTF-8')
        if correct:
            r = re.match('^(\d+)\s*(.*)$', correct)
            if r:
                column = int(r.group(1))
                correct = r.group(2)
                start += r.regs[2][0]  # second group, start index
            else:
                column = len(line) - 1  # -1 for the \n
            if test_type == '!':
                yield makecase(TEST_ASSIGNMENTS)
            elif test_type == '<':
                yield makecase(TEST_USAGES)
            elif correct.startswith('['):
                yield makecase(TEST_COMPLETIONS)
            else:
                yield makecase(TEST_DEFINITIONS)
            correct = None
        else:
            try:
                r = re.search(r'(?:^|(?<=\s))#([?!<])\s*([^\n]+)', line)
                # test_type is ? for completion and ! for goto_assignments
                test_type = r.group(1)
                correct = r.group(2)
                start = r.start()
            except AttributeError:
                correct = None
            else:
                # skip the test, if this is not specified test
                if lines_to_execute and line_nr not in lines_to_execute:
                    correct = None
Ejemplo n.º 60
0
 def _path(self):
     """The path to a module/class/function definition."""
     path = []
     par = self._definition
     while par is not None:
         if isinstance(par, tree.Import):
             path += imports.ImportWrapper(self._evaluator, self._name).import_path
             break
         try:
             name = par.name
         except AttributeError:
             pass
         else:
             if isinstance(par, er.ModuleWrapper):
                 # TODO just make the path dotted from the beginning, we id:240 gh:241
                 # shouldn't really split here.
                 path[0:0] = par.py__name__().split('.')
                 break
             else:
                 path.insert(0, unicode(name))
         par = par.parent
     return path