def _eval_atom(self, atom): """ Basically to process ``atom`` nodes. The parser sometimes doesn't generate the node (because it has just one child). In that case an atom might be a name or a literal as well. """ if isinstance(atom, pr.Name): # This is the first global lookup. stmt = atom.get_definition() scope = stmt.get_parent_until(pr.IsScope, include_current=True) if isinstance(stmt, pr.CompFor): stmt = stmt.get_parent_until((pr.ClassOrFunc, pr.ExprStmt)) if stmt.type != 'expr_stmt': # We only need to adjust the start_pos for statements, because # there the name cannot be used. stmt = atom return self.find_types(scope, atom, stmt.start_pos, search_global=True) elif isinstance(atom, pr.Literal): return [compiled.create(self, atom.eval())] else: c = atom.children # Parentheses without commas are not tuples. if c[0] == '(' and not len(c) == 2 \ and not(pr.is_node(c[1], 'testlist_comp') and len(c[1].children) > 1): return self.eval_element(c[1]) try: comp_for = c[1].children[1] except (IndexError, AttributeError): pass else: if isinstance(comp_for, pr.CompFor): return [iterable.Comprehension.from_atom(self, atom)] return [iterable.Array(self, atom)]
def _eval_atom(self, atom): """ Basically to process ``atom`` nodes. The parser sometimes doesn't generate the node (because it has just one child). In that case an atom might be a name or a literal as well. """ if isinstance(atom, tree.Name): # This is the first global lookup. stmt = atom.get_definition() scope = stmt.get_parent_until(tree.IsScope, include_current=True) if isinstance(scope, (tree.Function, er.FunctionExecution)): # Adjust scope: If the name is not in the suite, it's a param # default or annotation and will be resolved as part of the # parent scope. colon = scope.children.index(':') if atom.start_pos < scope.children[colon + 1].start_pos: scope = scope.get_parent_scope() if isinstance(stmt, tree.CompFor): stmt = stmt.get_parent_until((tree.ClassOrFunc, tree.ExprStmt)) if stmt.type != 'expr_stmt': # We only need to adjust the start_pos for statements, because # there the name cannot be used. stmt = atom return self.find_types(scope, atom, stmt.start_pos, search_global=True) elif isinstance(atom, tree.Literal): return set([compiled.create(self, atom.eval())]) else: c = atom.children if c[0].type == 'string': # Will be one string. types = self._eval_atom(c[0]) for string in c[1:]: right = self._eval_atom(string) types = precedence.calculate(self, types, '+', right) return types # Parentheses without commas are not tuples. elif c[0] == '(' and not len(c) == 2 \ and not(tree.is_node(c[1], 'testlist_comp') and len(c[1].children) > 1): return self.eval_element(c[1]) try: comp_for = c[1].children[1] except (IndexError, AttributeError): pass else: if comp_for == ':': # Dict comprehensions have a colon at the 3rd index. try: comp_for = c[1].children[3] except IndexError: pass if comp_for.type == 'comp_for': return set([iterable.Comprehension.from_atom(self, atom)]) return set([iterable.Array(self, atom)])
def builtins_reversed(evaluator, obj, params): objects = tuple(_follow_param(evaluator, params, 0)) if objects: # unpack the iterator values objects = tuple(iterable.get_iterator_types(objects)) if 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 = (iterable.Array(evaluator, FakeArray(stmts, objects[0].parent)),) return [er.Instance(evaluator, obj, objects)]
def eval_call_path(self, path, scope, position): """ Follows a path generated by `pr.StatementElement.generate_call_path()`. """ current = next(path) if isinstance(current, pr.Array): types = [iterable.Array(self, current)] else: if isinstance(current, pr.NamePart): # This is the first global lookup. types = self.find_types(scope, current, position=position, search_global=True) else: # for pr.Literal types = [compiled.create(self, current.value)] types = imports.follow_imports(self, types) return self.follow_path(path, types, scope)