# -*- coding: utf-8 -*-
"""
    ast
    ~~~

    The `ast` module helps Python applications to process trees of the Python
    abstract syntax grammar.  The abstract syntax itself might change with
    each Python release; this module helps to find out programmatically what
    the current grammar looks like and allows modifications of it.

    An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
    a flag to the `compile()` builtin function or by using the `parse()`
    function from this module.  The result will be a tree of objects whose
    classes all inherit from `ast.AST`.

    A modified abstract syntax tree can be compiled into a Python code object
    using the built-in `compile()` function.

    Additionally various helper functions are provided that make working with
    the trees simpler.  The main intention of the helper functions and this
    module in general is to provide an easy to use interface for libraries
    that work tightly with the python syntax ( template engines for example ).


    :copyright: Copyright 2008 by Armin Ronacher.
    :license: Python License.
"""
from _ast import *
from _ast import __version__


def parse( source, filename='<unknown>', mode='exec' ):
    """
    Parse the source into an AST node.
    Equivalent to compile( source, filename, mode, PyCF_ONLY_AST ).
    """
    return compile( source, filename, mode, PyCF_ONLY_AST )


def literal_eval( node_or_string ):
    """
    Safely evaluate an expression node or a string containing a Python
    expression.  The string or node provided may only consist of the following
    Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
    and None.
    """
    _safe_names = { 'None': None, 'True': True, 'False': False }
    if isinstance( node_or_string, basestring ):
        node_or_string = parse( node_or_string, mode='eval' )
    if isinstance( node_or_string, Expression ):
        node_or_string = node_or_string.body

    def _convert( node ):
        if isinstance( node, Str ):
            return node.s
        elif isinstance( node, Num ):
            return node.n
        elif isinstance( node, Tuple ):
            return tuple( map( _convert, node.elts ) )
        elif isinstance( node, List ):
            return list( map( _convert, node.elts ) )
        elif isinstance( node, Dict ):
            return dict( ( _convert( k ), _convert( v ) ) for k, v
                         in zip( node.keys, node.values ) )
        elif isinstance( node, Name ):
            if node.id in _safe_names:
                return _safe_names[ node.id ]
        elif isinstance( node, BinOp ) and \
             isinstance( node.op, ( Add, Sub ) ) and \
             isinstance( node.right, Num ) and \
             isinstance( node.right.n, complex ) and \
             isinstance( node.left, Num ) and \
             isinstance( node.left.n, ( int, long, float ) ):
            left = node.left.n
            right = node.right.n
            if isinstance( node.op, Add ):
                return left + right
            else:
                return left - right
        raise ValueError( 'malformed string' )
    return _convert( node_or_string )


def dump( node, annotate_fields=True, include_attributes=False ):
    """
    Return a formatted dump of the tree in *node*.  This is mainly useful for
    debugging purposes.  The returned string will show the names and the values
    for fields.  This makes the code impossible to evaluate, so if evaluation is
    wanted *annotate_fields* must be set to False.  Attributes such as line
    numbers and column offsets are not dumped by default.  If this is wanted,
    *include_attributes* can be set to True.
    """
    def _format( node ):
        if isinstance( node, AST ):
            fields = [ ( a, _format( b ) ) for a, b in iter_fields( node ) ]
            rv = '%s(%s' % ( node.__class__.__name__, ', '.join(
                ( '%s=%s' % field for field in fields )
                if annotate_fields else
                ( b for a, b in fields )
            ) )
            if include_attributes and node._attributes:
                rv += fields and ', ' or ' '
                rv += ', '.join( '%s=%s' % ( a, _format( getattr( node, a ) ) )
                                 for a in node._attributes )
            return rv + ')'
        elif isinstance( node, list ):
            return '[%s]' % ', '.join( _format( x ) for x in node )
        return repr( node )
    if not isinstance( node, AST ):
        raise TypeError( 'expected AST, got %r' % node.__class__.__name__ )
    return _format( node )


def copy_location( new_node, old_node ):
    """
    Copy source location ( `lineno` and `col_offset` attributes ) from
    *old_node* to *new_node* if possible, and return *new_node*.
    """
    for attr in 'lineno', 'col_offset':
        if attr in old_node._attributes and attr in new_node._attributes \
           and hasattr( old_node, attr ):
            setattr( new_node, attr, getattr( old_node, attr ) )
    return new_node


def fix_missing_locations( node ):
    """
    When you compile a node tree with compile(), the compiler expects lineno and
    col_offset attributes for every node that supports them.  This is rather
    tedious to fill in for generated nodes, so this helper adds these attributes
    recursively where not already set, by setting them to the values of the
    parent node.  It works recursively starting at *node*.
    """
    def _fix( node, lineno, col_offset ):
        if 'lineno' in node._attributes:
            if not hasattr( node, 'lineno' ):
                node.lineno = lineno
            else:
                lineno = node.lineno
        if 'col_offset' in node._attributes:
            if not hasattr( node, 'col_offset' ):
                node.col_offset = col_offset
            else:
                col_offset = node.col_offset
        for child in iter_child_nodes( node ):
            _fix( child, lineno, col_offset )
    _fix( node, 1, 0 )
    return node


def increment_lineno( node, n=1 ):
    """
    Increment the line number of each node in the tree starting at *node* by *n*.
    This is useful to "move code" to a different location in a file.
    """
    for child in walk( node ):
        if 'lineno' in child._attributes:
            child.lineno = getattr( child, 'lineno', 0 ) + n
    return node


def iter_fields( node ):
    """
    Yield a tuple of ``( fieldname, value )`` for each field in ``node._fields``
    that is present on *node*.
    """
    for field in node._fields:
        try:
            yield field, getattr( node, field )
        except AttributeError:
            pass


def iter_child_nodes( node ):
    """
    Yield all direct child nodes of *node*, that is, all fields that are nodes
    and all items of fields that are lists of nodes.
    """
    for name, field in iter_fields( node ):
        if isinstance( field, AST ):
            yield field
        elif isinstance( field, list ):
            for item in field:
                if isinstance( item, AST ):
                    yield item


def get_docstring( node, clean=True ):
    """
    Return the docstring for the given node or None if no docstring can
    be found.  If the node provided does not have docstrings a TypeError
    will be raised.
    """
    if not isinstance( node, ( FunctionDef, ClassDef, Module ) ):
        raise TypeError( "%r can't have docstrings" % node.__class__.__name__ )
    if node.body and isinstance( node.body[ 0 ], Expr ) and \
       isinstance( node.body[ 0 ].value, Str ):
        if clean:
            import inspect
            return inspect.cleandoc( node.body[ 0 ].value.s )
        return node.body[ 0 ].value.s


def walk( node ):
    """
    Recursively yield all descendant nodes in the tree starting at *node*
    ( including *node* itself ), in no specified order.  This is useful if you
    only want to modify nodes in place and don't care about the context.
    """
    from collections import deque
    todo = deque( [ node ] )
    while todo:
        node = todo.popleft()
        todo.extend( iter_child_nodes( node ) )
        yield node


class NodeVisitor( object ):

    """
    A node visitor base class that walks the abstract syntax tree and calls a
    visitor function for every node found.  This function may return a value
    which is forwarded by the `visit` method.

    This class is meant to be subclassed, with the subclass adding visitor
    methods.

    Per default the visitor functions for the nodes are ``'visit_'`` +
    class name of the node.  So a `TryFinally` node visit function would
    be `visit_TryFinally`.  This behavior can be changed by overriding
    the `visit` method.  If no visitor function exists for a node
    ( return value `None` ) the `generic_visit` visitor is used instead.

    Don't use the `NodeVisitor` if you want to apply changes to nodes during
    traversing.  For this a special visitor exists ( `NodeTransformer` ) that
    allows modifications.
    """
    def visit( self, node ):
        "Visit a node."
        method = 'visit_' + node.__class__.__name__
        visitor = getattr( self, method, self.generic_visit )
        return visitor( node )

    def generic_visit( self, node ):
        "Called if no explicit visitor function exists for a node."
        for field, value in iter_fields( node ):
            if isinstance( value, list ):
                for item in value:
                    if isinstance( item, AST ):
                        self.visit( item )
            elif isinstance( value, AST ):
                self.visit( value )


class NodeTransformer( NodeVisitor ):

    """
    A :class:`NodeVisitor` subclass that walks the abstract syntax tree and
    allows modification of nodes.

    The `NodeTransformer` will walk the AST and use the return value of the
    visitor methods to replace or remove the old node.  If the return value of
    the visitor method is ``None``, the node will be removed from its location,
    otherwise it is replaced with the return value.  The return value may be the
    original node in which case no replacement takes place.

    Here is an example transformer that rewrites all occurrences of name lookups
    ( ``foo`` ) to ``data[ 'foo' ]``::

       class RewriteName( NodeTransformer ):

           def visit_Name( self, node ):
               return copy_location( Subscript(
                   value=Name( id='data', ctx=Load() ),
                   slice=Index( value=Str( s=node.id ) ),
                   ctx=node.ctx
               ), node )

    Keep in mind that if the node you're operating on has child nodes you must
    either transform the child nodes yourself or call the :meth:`generic_visit`
    method for the node first.

    For nodes that were part of a collection of statements ( that applies to all
    statement nodes ), the visitor may also return a list of nodes rather than
    just a single node.

    Usually you use the transformer like this::

       node = YourTransformer().visit( node )
    """
    def generic_visit( self, node ):
        for field, old_value in iter_fields( node ):
            old_value = getattr( node, field, None )
            if isinstance( old_value, list ):
                new_values = []
                for value in old_value:
                    if isinstance( value, AST ):
                        value = self.visit( value )
                        if value is None:
                            continue
                        elif not isinstance( value, AST ):
                            new_values.extend( value )
                            continue
                    new_values.append( value )
                old_value[ : ] = new_values
            elif isinstance( old_value, AST ):
                new_node = self.visit( old_value )
                if new_node is None:
                    delattr( node, field )
                else:
                    setattr( node, field, new_node )
        return node
