B
    7r\                 @   st   d Z ddlmZ ddlmZ ddlmZ dZdZdZ	dZ
G d	d
 d
eZedd ZefddZG dd deZdS )a  
Recursions are the recipe of |jedi| to conquer Python code. However, someone
must stop recursions going mad. Some settings are here to make |jedi| stop at
the right time. You can read more about them :ref:`here <settings-recursion>`.

Next to :mod:`jedi.evaluate.cache` this module also makes |jedi| not
thread-safe. Why?  ``execution_recursion_decorator`` uses class variables to
count the function calls.

.. _settings-recursion:

Settings
~~~~~~~~~~

Recursion settings are important if you don't want extremly
recursive python code to go absolutely crazy.

The default values are based on experiments while completing the |jedi| library
itself (inception!). But I don't think there's any other Python library that
uses recursion in a similarly extreme way. Completion should also be fast and
therefore the quality might not always be maximal.

.. autodata:: recursion_limit
.. autodata:: total_function_execution_limit
.. autodata:: per_function_execution_limit
.. autodata:: per_function_recursion_limit
    )contextmanager)debug)NO_CONTEXTS            c               @   s   e Zd Zdd ZdS )RecursionDetectorc             C   s
   g | _ d S )N)pushed_nodes)self r   6lib/python3.7/site-packages/jedi/evaluate/recursion.py__init__6   s    zRecursionDetector.__init__N)__name__
__module____qualname__r   r   r   r   r   r	   5   s   r	   c             c   sR   | j j}||kr.td|t|dd dV  n z|| dV  W d|  X dS )z
    A decorator to detect recursions in statements. In a recursion a statement
    at the same place, in the same module may not be executed two times.
    zcatched stmt recursion: %s @%sZ	start_posNFT)Zrecursion_detectorr
   r   Zwarninggetattrappendpop)	evaluatorZnoder
   r   r   r   execution_allowed:   s    

r   c                s    fdd}|S )Nc                s    fdd}|S )Nc                s<   | j j}|| }z|r }n| f|}W d |  X |S )N)r   Zexecution_recursion_detectorpush_executionpop_execution)r   kwargsZdetectorZallowedresult)defaultfuncr   r   wrapperP   s    

zAexecution_recursion_decorator.<locals>.decorator.<locals>.wrapperr   )r   r   )r   )r   r   	decoratorO   s    z0execution_recursion_decorator.<locals>.decoratorr   )r   r   r   )r   r   execution_recursion_decoratorN   s    r   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	ExecutionRecursionDetectorz+
    Catches recursions of executions.
    c             C   s"   || _ d| _g | _i | _d| _d S )Nr   )
_evaluator_recursion_level_parent_execution_funcs_funcdef_execution_counts_execution_count)r   r   r   r   r   r   c   s
    z#ExecutionRecursionDetector.__init__c             C   s   | j   |  jd8  _d S )N   )r#   r   r"   )r   r   r   r   r   k   s    
z(ExecutionRecursionDetector.pop_executionc             C   s   |j }|  jd7  _| j| | }|| jjkr8dS | jtkrFdS | jt	krTdS |  jd7  _| j
|dtkrxdS | j
|  d7  < | j|tkrdS dS )Nr&   FTr   )Z	tree_noder"   r#   r   Zget_root_contextr!   Zbuiltins_modulerecursion_limitr%   total_function_execution_limitr$   
setdefaultper_function_execution_limitcountper_function_recursion_limit)r   Z	executionZfuncdefmoduler   r   r   r   o   s"    

z)ExecutionRecursionDetector.push_executionN)r   r   r   __doc__r   r   r   r   r   r   r   r    _   s   r    N)r.   
contextlibr   Zjedir   Zjedi.evaluate.base_contextr   r'   r(   r*   r,   objectr	   r   r   r    r   r   r   r   <module>   s   