Exemplo n.º 1
0
def extract(fileobj, keywords, comment_tags, options, cls=HTMLTemplate):
    """
    Babel extraction function
    """
    with patch_load():
        source = fileobj.read()
        if isinstance(source, bytes):
            source = source.decode('UTF-8')

        template = cls(source)

        for _, node, _ in im.walk_tree(template.intermediate):
            for astnode in get_ast_nodes(node):
                calls = (n for n, _ in astwalk(astnode)
                         if isinstance(n, ast.Call))
                for c in calls:
                    if isinstance(c.func, ast.Name) and c.func.id in keywords:
                        strargs = tuple(x.s for x in takewhile(
                            lambda x: isinstance(x, ast.Str), iter(c.args)))
                        if len(strargs) == 1:
                            strargs = strargs[0]
                        if strargs:
                            yield node.pos.line, c.func.id, strargs, []

            if isinstance(node, im.TranslationNode):
                comments = [node.comment] if node.comment else []
                func_name = '_'
                yield (node.pos.line, func_name, node.get_msgstr(), comments)
def _get_out_of_scope_names(fn):
    """
    Return the set of names that are not accessible within node ``fn``.

    This is good enough for the ast generated by piglet, but would not work
    more generally as it does not support global and non_local
    """
    in_scope = set()
    out_of_scope = set()

    for n, ancestors in astwalk(fn):
        # A function parameter or py2 variable assignment
        if isinstance(n, Name) and isinstance(n.ctx, (Param, Store)):
            in_scope.add((ancestors, n.id))

        # A py3 function argument
        elif arg is not None and isinstance(n, arg):
            in_scope.add((ancestors, n.arg))

        # A name defined through an import
        elif isinstance(n, alias):
            in_scope.add((ancestors, n.asname or n.name))

        # A reference to a (possibly non-local) variable
        elif isinstance(n, Name) and isinstance(n.ctx, Load):
            if not any((ancestors[:ix], n.id) in in_scope
                       for ix in range(len(ancestors) + 1)):
                out_of_scope.add((n, ancestors))
    return out_of_scope
    def collect_output(self, parent):
        """
        Context manager that collects any yield expressions added to ``parent``
        and turns them into calls to ``__piglet_acc_list.append``.

        The name of the accumulator object is returned by the function
        """
        acc = self.unique_id('acc')
        append = self.unique_id('append')
        pos = len(parent.body)

        parent.body.append(Assign(targets=[StoreName(acc)],
                                  value=List(elts=[], ctx=Load())))
        parent.body.append(Assign(targets=[StoreName(append)],
                                  value=Attribute(value=LoadName(acc),
                                                  attr='append',
                                                  ctx=Load())))
        yield acc
        for n in parent.body[pos:]:
            for node, ancestors in astwalk(n):
                if isinstance(node, Expr) and isinstance(node.value, Yield):
                    node.value = Call(func=LoadName(append),
                                      args=[node.value.value],
                                      starargs=None,
                                      kwargs=None,
                                      keywords=[])
def _ensure_all_functions_yield(module):
    """
    All generated functions should contain at least one yield statement.
    This walks the ast to insert a "yield ''" in functions that
    don't otherwise produce output (eg in the case of '<py:def
    function="a"></py:def>')
    """
    functions = {}
    if YieldFrom is not None:
        yield_classes = (Yield, YieldFrom)
    else:
        yield_classes = (Yield,)
    for node, ancestors in astwalk(module):
        if isinstance(node, FunctionDef):
            functions.setdefault(node, False)
        elif isinstance(node, yield_classes):
            f = next(a for a in reversed(ancestors)
                     if isinstance(a, FunctionDef))
            functions[f] = True

    for f in functions:
        if not functions[f]:
            f.body.append(Expr(Yield(Str(s=''))))

    return module
 def get_ancestors(self, node):
     """
     Return the sequence of ancestor nodes for ``node``.
     :param astnode: the astnode to consider
     :yields: sequence of ancestor AST nodes, in the order
             ``[node, parent, grandparent, great-grandparent, ...]``
     """
     for n, ancestors in astwalk(self.module):
         if n is node:
             return chain([node], reversed(ancestors))
     return []
def _get_function_defs(astnode):
    return ((n, a) for n, a in astwalk(astnode) if isinstance(n, FunctionDef))