B
    S\1                 @   s&   d dl Z d dlmZ G dd dZdS )    N)	lru_cachec               @   sZ   e Zd ZdZdZdd Zeeddd Zdd	 Zd
d Z	dddZ
dddZdd ZdS )TransformVisitorzA visitor for handling transforms.

    The standard approach of using it is to call
    :meth:`~visit` with an *astroid* module and the class
    will take care of the rest, walking the tree and running the
    transforms for each encountered node.
    i'  c             C   s   t t| _d S )N)collectionsdefaultdictlist
transforms)self r	   1lib/python3.7/site-packages/astroid/transforms.py__init__   s    zTransformVisitor.__init__)maxsizec             C   sd   |j }|| jkr|S | j| }x@|D ]8\}}|dks<||r$||}|dk	rP|}|j |kr$P q$W |S )zdCall matching transforms for the given node if any and return the
        transformed node.
        N)	__class__r   )r   nodeclsr   Ztransform_func	predicateZretr	   r	   r
   
_transform   s    


zTransformVisitor._transformc             C   sL   t |drBx6|jD ],}t||}| |}||krt||| qW | |S )N_astroid_fields)hasattrr   getattr_visit_genericsetattrr   )r   r   namevalueZvisitedr	   r	   r
   _visit2   s    


zTransformVisitor._visitc                sX   t |tr fdd|D S t |tr<t fdd|D S |rJt |trN|S  |S )Nc                s   g | ]}  |qS r	   )r   ).0child)r   r	   r
   
<listcomp>=   s    z3TransformVisitor._visit_generic.<locals>.<listcomp>c             3   s   | ]}  |V  qd S )N)r   )r   r   )r   r	   r
   	<genexpr>?   s    z2TransformVisitor._visit_generic.<locals>.<genexpr>)
isinstancer   tuplestrr   )r   r   r	   )r   r
   r   ;   s    

zTransformVisitor._visit_genericNc             C   s   | j | ||f dS )a7  Register `transform(node)` function to be applied on the given
        astroid's `node_class` if `predicate` is None or returns true
        when called with the node as argument.

        The transform function may return a value which is then used to
        substitute the original node in the tree.
        N)r   append)r   
node_class	transformr   r	   r	   r
   register_transformE   s    z#TransformVisitor.register_transformc             C   s   | j | ||f dS )zUnregister the given transform.N)r   remove)r   r"   r#   r   r	   r	   r
   unregister_transformO   s    z%TransformVisitor.unregister_transformc                s     fdd|j D |_  |S )zWalk the given astroid *tree* and transform each encountered node

        Only the nodes which have transforms registered will actually
        be replaced or changed.
        c                s   g | ]}  |qS r	   )r   )r   r   )r   r	   r
   r   Y   s    z*TransformVisitor.visit.<locals>.<listcomp>)Zbodyr   )r   moduler	   )r   r
   visitS   s    zTransformVisitor.visit)N)N)__name__
__module____qualname____doc__ZTRANSFORM_MAX_CACHE_SIZEr   r   r   r   r   r$   r&   r(   r	   r	   r	   r
   r      s   	



r   )r   	functoolsr   r   r	   r	   r	   r
   <module>	   s   