ó
’›V]c           @   s™   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
 d	 e f d
 „  ƒ  YZ e d „  ƒ Z e d „ Z d e f d „  ƒ  YZ d S(   sò  
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
iÿÿÿÿ(   t   contextmanager(   t   debug(   t   NO_CONTEXTSi   iÈ   i   i   t   RecursionDetectorc           B   s   e  Z d  „  Z RS(   c         C   s   g  |  _  d  S(   N(   t   pushed_nodes(   t   self(    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt   __init__6   s    (   t   __name__t
   __module__R   (    (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyR   5   s   c         c   sg   |  j  j } | | k r? t j d | t | d d ƒ ƒ t Vn$ z | j | ƒ t VWd | j	 ƒ  Xd S(   s   
    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.
    s   catched stmt recursion: %s @%st	   start_posN(
   t   recursion_detectorR   R   t   warningt   getattrt   Nonet   Falset   appendt   Truet   pop(   t	   evaluatort   nodeR   (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt   execution_allowed:   s    	c            s   ‡  f d †  } | S(   Nc            s   ‡ ‡  f d †  } | S(   Nc            sO   |  j  j } | j |  ƒ } z" | r- ˆ  } n ˆ |  |  } Wd  | j ƒ  X| S(   N(   R   t   execution_recursion_detectort   push_executiont   pop_execution(   R   t   kwargst   detectort   limit_reachedt   result(   t   defaultt   func(    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt   wrapperP   s    	(    (   R   R   (   R   (   R   s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt	   decoratorO   s    (    (   R   R   (    (   R   s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt   execution_recursion_decoratorN   s    t   ExecutionRecursionDetectorc           B   s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   s+   
    Catches recursions of executions.
    c         C   s1   | |  _  d |  _ g  |  _ i  |  _ d |  _ d  S(   Ni    (   t
   _evaluatort   _recursion_levelt   _parent_execution_funcst   _funcdef_execution_countst   _execution_count(   R   R   (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyR   c   s
    				c         C   s    |  j  j ƒ  |  j d 8_ d  S(   Ni   (   R$   R   R#   (   R   (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyR   k   s    c         C   s-  | j  } |  j d 7_ |  j j | ƒ | j ƒ  } | |  j j k rJ t S|  j t k rm t	 j
 d t ƒ t S|  j t k r t	 j
 d t ƒ t S|  j d 7_ |  j j | d ƒ t k rç | j ƒ  d	 k rÐ t St	 j
 d t | ƒ t S|  j | c d 7<|  j j | ƒ t k r)t	 j
 d t | ƒ t St S(
   Ni   s   Recursion limit (%s) reacheds%   Function execution limit (%s) reachedi    t   builtinst   typings-   Per function execution limit (%s) reached: %ss-   Per function recursion limit (%s) reached: %s(   R'   R(   (   t	   tree_nodeR#   R$   R   t   get_root_contextR"   t   builtins_moduleR   t   recursion_limitR   R   R   R&   t   total_function_execution_limitR%   t
   setdefaultt   per_function_execution_limitt
   py__name__t   countt   per_function_recursion_limit(   R   t	   executiont   funcdeft   module(    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyR   o   s:    	(   R   R   t   __doc__R   R   R   (    (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyR!   _   s   		N(   R6   t
   contextlibR    t   jediR   t   jedi.evaluate.base_contextR   R,   R-   R/   R2   t   objectR   R   R    R!   (    (    (    s6   lib/python2.7/site-packages/jedi/evaluate/recursion.pyt   <module>   s   