U
    nufD                     @   sp   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
Zedd ZefddZG dd d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 the internal ``jedi.inference.cache`` this module also makes |jedi| not
thread-safe, because ``execution_recursion_decorator`` uses class variables to
count the function calls.

.. _settings-recursion:

Settings
~~~~~~~~~~

Recursion settings are important if you don't want extremely
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_VALUES            c                   @   s   e Zd Zdd ZdS )RecursionDetectorc                 C   s
   g | _ d S N)pushed_nodesself r   </tmp/pip-unpacked-wheel-ol4ehs9f/jedi/inference/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 5 |  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   warninggetattrpopappend)inference_state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 5 |  X |S r
   )r   Zexecution_recursion_detectorpush_executionpop_execution)r   kwargsdetectorZlimit_reached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   )Z_inference_state_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| | }| r4dS | jtkrNtdt dS | j	t
krhtdt
 dS |  j	d7  _	| j|dtkr| dkrdS tdt| dS | j|  d7  < | j|tkrtd	t| dS dS )
Nr+   FzRecursion limit (%s) reachedTz%Function execution limit (%s) reachedr   typingz-Per function execution limit (%s) reached: %sz-Per function recursion limit (%s) reached: %s)Z	tree_noder'   r(   r   Zget_root_contextZis_builtins_modulerecursion_limitr   r   r*   total_function_execution_limitr)   
setdefaultper_function_execution_limitZ
py__name__countper_function_recursion_limit)r   Z	executionZfuncdefZmodule_contextr   r   r   r   o   s>    

z)ExecutionRecursionDetector.push_executionN)r   r   r   __doc__r   r   r   r   r   r   r   r&   _   s   r&   N)r3   
contextlibr   Zjedir   Zjedi.inference.base_valuer   r-   r.   r0   r2   r	   r   r%   r&   r   r   r   r   <module>   s   
