def _paths_from_assignment(evaluator, statement): """ Extracts the assigned strings from an assignment that looks as follows:: >>> sys.path[0:0] = ['module/path', 'another/module/path'] This function is in general pretty tolerant (and therefore 'buggy'). However, it's not a big issue usually to add more paths to Jedi's sys_path, because it will only affect Jedi in very random situations and by adding more paths than necessary, it usually benefits the general user. """ for exp_list, operator in statement.assignment_details: if len(exp_list) != 1 or not isinstance(exp_list[0], pr.Call): continue if exp_list[0].names() != ['sys', 'path']: continue # TODO at this point we ignore all ways what could be assigned to # sys.path or an execution of it. Here we could do way more # complicated checks. from jedi.evaluate.iterable import get_iterator_types from jedi.evaluate.precedence import is_string for val in get_iterator_types(evaluator.eval_statement(statement)): if is_string(val): yield val.obj
def _handle_for_loops(self, loop): # Take the first statement (for has always only one`in`). 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
def builtins_reversed(evaluator, sequences, obj): # Unpack the iterator values objects = tuple(iterable.get_iterator_types(sequences)) rev = [iterable.AlreadyEvaluated([o]) for o in reversed(objects)] # Repack iterator values and then run it the normal way. This is # necessary, because `reversed` is a function and autocompletion # would fail in certain cases like `reversed(x).__iter__` if we # just returned the result directly. rev = iterable.AlreadyEvaluated( [iterable.FakeSequence(evaluator, rev, 'list')]) return [er.Instance(evaluator, obj, param.Arguments(evaluator, [rev]))]
def builtins_reversed(evaluator, sequences, obj): # Unpack the iterator values objects = tuple(iterable.get_iterator_types(sequences)) rev = [iterable.AlreadyEvaluated([o]) for o in reversed(objects)] # Repack iterator values and then run it the normal way. This is # necessary, because `reversed` is a function and autocompletion # would fail in certain cases like `reversed(x).__iter__` if we # just returned the result directly. rev = iterable.AlreadyEvaluated( [iterable.FakeSequence(evaluator, rev, 'list')] ) return [er.Instance(evaluator, obj, param.Arguments(evaluator, [rev]))]
def _name_to_types(evaluator, name, scope): types = [] typ = name.get_definition() if typ.isinstance(pr.ForStmt): for_types = evaluator.eval_element(typ.children[3]) for_types = iterable.get_iterator_types(for_types) types += check_tuple_assignments(for_types, name) elif typ.isinstance(pr.CompFor): for_types = evaluator.eval_element(typ.children[3]) for_types = iterable.get_iterator_types(for_types) types += check_tuple_assignments(for_types, name) elif isinstance(typ, pr.Param): types += _eval_param(evaluator, typ, scope) elif typ.isinstance(pr.ExprStmt): types += _remove_statements(evaluator, typ, name) elif typ.isinstance(pr.WithStmt): types += evaluator.eval_element(typ.node_from_name(name)) elif isinstance(typ, pr.Import): types += imports.ImportWrapper(evaluator, name).follow() elif isinstance(typ, pr.GlobalStmt): # TODO theoretically we shouldn't be using search_global here, it # doesn't make sense, because it's a local search (for that name)! # However, globals are not that important and resolving them doesn't # guarantee correctness in any way, because we don't check for when # something is executed. types += evaluator.find_types(typ.get_parent_scope(), str(name), search_global=True) elif isinstance(typ, pr.TryStmt): # TODO an exception can also be a tuple. Check for those. # TODO check for types that are not classes and add it to # the static analysis report. exceptions = evaluator.eval_element(name.prev_sibling().prev_sibling()) types = list( chain.from_iterable(evaluator.execute(t) for t in exceptions)) else: if typ.isinstance(er.Function): typ = typ.get_decorated_func() types.append(typ) return types
def _name_to_types(evaluator, name, scope): types = [] typ = name.get_definition() if typ.isinstance(pr.ForStmt): for_types = evaluator.eval_element(typ.children[3]) for_types = iterable.get_iterator_types(for_types) types += check_tuple_assignments(for_types, name) elif typ.isinstance(pr.CompFor): for_types = evaluator.eval_element(typ.children[3]) for_types = iterable.get_iterator_types(for_types) types += check_tuple_assignments(for_types, name) elif isinstance(typ, pr.Param): types += _eval_param(evaluator, typ, scope) elif typ.isinstance(pr.ExprStmt): types += _remove_statements(evaluator, typ, name) elif typ.isinstance(pr.WithStmt): types += evaluator.eval_element(typ.node_from_name(name)) elif isinstance(typ, pr.Import): types += imports.ImportWrapper(evaluator, name).follow() elif isinstance(typ, pr.GlobalStmt): # TODO theoretically we shouldn't be using search_global here, it # doesn't make sense, because it's a local search (for that name)! # However, globals are not that important and resolving them doesn't # guarantee correctness in any way, because we don't check for when # something is executed. types += evaluator.find_types(typ.get_parent_scope(), str(name), search_global=True) elif isinstance(typ, pr.TryStmt): # TODO an exception can also be a tuple. Check for those. # TODO check for types that are not classes and add it to # the static analysis report. exceptions = evaluator.eval_element(name.prev_sibling().prev_sibling()) types = list(chain.from_iterable( evaluator.execute(t) for t in exceptions)) else: if typ.isinstance(er.Function): typ = typ.get_decorated_func() types.append(typ) return types
def builtins_reversed(evaluator, obj, params): objects = _follow_param(evaluator, params, 0) if objects: # unpack the iterator values objects = iterable.get_iterator_types(objects) rev = reversed(objects) # Repack iterator values and then run it the normal way. This is necessary, # because `reversed` is a function and autocompletion would fail in certain # cases like `reversed(x).__iter__` if we just returned the result # directly. stmts = [FakeStatement([r]) for r in rev] objects = (FakeArray(stmts, objects[0].parent), ) return [er.Instance(evaluator, obj, objects)]
def builtins_reversed(evaluator, obj, params): objects = _follow_param(evaluator, params, 0) if objects: # unpack the iterator values objects = iterable.get_iterator_types(objects) rev = reversed(objects) # Repack iterator values and then run it the normal way. This is necessary, # because `reversed` is a function and autocompletion would fail in certain # cases like `reversed(x).__iter__` if we just returned the result # directly. stmts = [FakeStatement([r]) for r in rev] objects = (FakeArray(stmts, objects[0].parent),) return [er.Instance(evaluator, obj, objects)]
def _paths_from_assignment(evaluator, expr_stmt): """ Extracts the assigned strings from an assignment that looks as follows:: >>> sys.path[0:0] = ['module/path', 'another/module/path'] This function is in general pretty tolerant (and therefore 'buggy'). However, it's not a big issue usually to add more paths to Jedi's sys_path, because it will only affect Jedi in very random situations and by adding more paths than necessary, it usually benefits the general user. """ for assignee, operator in zip(expr_stmt.children[::2], expr_stmt.children[1::2]): try: assert operator in ['=', '+='] assert tree.is_node(assignee, 'power') and len(assignee.children) > 1 c = assignee.children assert c[0].type == 'name' and c[0].value == 'sys' trailer = c[1] assert trailer.children[0] == '.' and trailer.children[ 1].value == 'path' # TODO Essentially we're not checking details on sys.path # manipulation. Both assigment of the sys.path and changing/adding # parts of the sys.path are the same: They get added to the current # sys.path. """ execution = c[2] assert execution.children[0] == '[' subscript = execution.children[1] assert subscript.type == 'subscript' assert ':' in subscript.children """ except AssertionError: continue from jedi.evaluate.iterable import get_iterator_types from jedi.evaluate.precedence import is_string for val in get_iterator_types(evaluator.eval_statement(expr_stmt)): if is_string(val): yield val.obj
def builtins_isinstance(evaluator, objects, types): bool_results = set([]) for o in objects: try: mro_func = o.py__class__(evaluator).py__mro__ except AttributeError: # This is temporary. Everything should have a class attribute in # Python?! Maybe we'll leave it here, because some numpy objects or # whatever might not. return [compiled.true_obj, compiled.false_obj] mro = mro_func(evaluator) for cls_or_tup in types: if cls_or_tup.is_class(): bool_results.add(cls_or_tup in mro) else: # Check for tuples. classes = iterable.get_iterator_types([cls_or_tup]) bool_results.add(any(cls in mro for cls in classes)) return [compiled.keyword_from_value(x) for x in bool_results]
def _paths_from_assignment(evaluator, expr_stmt): """ Extracts the assigned strings from an assignment that looks as follows:: >>> sys.path[0:0] = ['module/path', 'another/module/path'] This function is in general pretty tolerant (and therefore 'buggy'). However, it's not a big issue usually to add more paths to Jedi's sys_path, because it will only affect Jedi in very random situations and by adding more paths than necessary, it usually benefits the general user. """ for assignee, operator in zip(expr_stmt.children[::2], expr_stmt.children[1::2]): try: assert operator in ['=', '+='] assert pr.is_node(assignee, 'power') and len(assignee.children) > 1 c = assignee.children assert c[0].type == 'name' and c[0].value == 'sys' trailer = c[1] assert trailer.children[0] == '.' and trailer.children[1].value == 'path' # TODO Essentially we're not checking details on sys.path # manipulation. Both assigment of the sys.path and changing/adding # parts of the sys.path are the same: They get added to the current # sys.path. """ execution = c[2] assert execution.children[0] == '[' subscript = execution.children[1] assert subscript.type == 'subscript' assert ':' in subscript.children """ except AssertionError: continue from jedi.evaluate.iterable import get_iterator_types from jedi.evaluate.precedence import is_string for val in get_iterator_types(evaluator.eval_statement(expr_stmt)): if is_string(val): yield val.obj