o
    qo™iD  ã                   @   sx   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   úL/home/ubuntu/.local/lib/python3.10/site-packages/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   s\    | j j}||v rt d|t|ddƒ¡ dV  dS z| |¡ dV  W | ¡  dS | ¡  w )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 @%sÚ	start_posNFT)Úrecursion_detectorr   r   ÚwarningÚgetattrÚappendÚpop)Úinference_stateÚnoder   r   r   r   Úexecution_allowed:   s   €
ÿ

r   c                    s   ‡ fdd„}|S )Nc                    s   ‡‡ fdd„}|S )Nc                    sT   | j j}| | ¡}z|rˆ }nˆ| fi |¤Ž}W | ¡  |S W | ¡  |S | ¡  w r
   )r   Úexecution_recursion_detectorÚpush_executionÚpop_execution)r   ÚkwargsÚdetectorÚ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   )Ú_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 |¡ | ¡ }| ¡ rdS | jtkr't dt¡ dS | j	t
kr4t dt
¡ dS |  j	d7  _	| j |d¡tkrU| ¡ dkrLdS t dt|¡ dS | j|  d7  < | j |¡tkrot d	t|¡ dS dS )
Nr0   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)Ú	tree_noder,   r-   r   Úget_root_contextÚis_builtins_moduleÚrecursion_limitr   r   r/   Útotal_function_execution_limitr.   Ú
setdefaultÚper_function_execution_limitÚ
py__name__ÚcountÚper_function_recursion_limit)r   Ú	executionÚfuncdefÚ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)r?   Ú
contextlibr   Újedir   Újedi.inference.base_valuer   r5   r6   r8   r;   r	   r   r)   r*   r   r   r   r   Ú<module>   s"    
