B
    7r\)                 @   s  d Z ddlZddlmZ ddlmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZmZmZ dd	lmZ d
ddgZedejedejgZedZdadd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z d d! Z!e d"d# Z"e ed$d% Z#dS )&a  
Docstrings are another source of information for functions and classes.
:mod:`jedi.evaluate.dynamic` tries to find all executions of functions, while
the docstring parsing is much easier. There are three different types of
docstrings that |jedi| understands:

- `Sphinx <http://sphinx-doc.org/markup/desc.html#info-field-lists>`_
- `Epydoc <http://epydoc.sourceforge.net/manual-fields.html>`_
- `Numpydoc <https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt>`_

For example, the sphinx annotation ``:type foo: str`` clearly states that the
type of ``foo`` is ``str``.

As an addition to parameter searching, this module also provides return
annotations.
    N)dedent)parseParserSyntaxError)u)indent_block)evaluator_method_cache)iterator_to_context_set
ContextSetNO_CONTEXTS)LazyKnownContextsz\s*:type\s+%s:\s*([^\n]+)z\s*:param\s+(\w+)\s+%s:[^\n]*z\s*@type\s+%s:\s*([^\n]+)z\s*:rtype:\s*([^\n]+)z\s*@rtype:\s*([^\n]+)z:[^`]+:`([^`]+)`c           
   C   sP   t ttrtyddlm}  | aW n( tk
rJ } z
|a W d d }~X Y nX tS )Nr   )NumpyDocString)
isinstance_numpy_doc_string_cacheImportErrorZnumpydoc.docscraper   )r   e r   7lib/python3.7/site-packages/jedi/evaluate/docstrings.py_get_numpy_doc_string_cls0   s    
r   c          
   C   sv   yt  | jd }W n tttfk
r.   g S X x@|D ]8\}}}||kr6td|}|rb|d}tt	|S q6W g S )zASearch `docstr` (in numpydoc format) for type(-s) of `param_str`.Z
Parametersz"([^,]+(,[^,]+)*?)(,[ ]*optional)?$   )
r   _parsed_dataKeyErrorAttributeErrorr   rematchgrouplist_expand_typestr)docstr	param_strZparamsZp_nameZp_typeZp_descrmr   r   r   _search_param_in_numpydocstr=   s    
r    c          	   c   s   yt  | }W n tk
r"   dS X y|jd }||jd 7 }W n ttfk
rX   dS X x2|D ]*\}}}|sr|}xt|D ]
}|V  q|W q`W dS )zP
    Search `docstr` (in numpydoc format) for type(-s) of function returns.
    NZReturnsZYields)r   r   r   r   r   r   )r   docZreturnsZr_nameZr_typeZr_descrtype_r   r   r   _search_return_in_numpydocstrN   s    
r#   c             c   s   t d| r6x| dD ]}|dd  V  qW nt d| rT| dd V  n| drt| ddjd }|jd	krxf|jd
 jD ]N}|jdkrd|jkrdV  qdV  q|jdkrd|j	
 krdV  qdV  qW n| V  dS )z@
    Attempts to interpret the possible types in `type_str`
    z\bor\borZofr   z\bof\b{z3.6)versionatomr   Znumber.floatintstringbbytesstrN)r   searchsplitstrip
startswithr   childrentypevalueZstring_prefixlower)type_strtZnodeZleafr   r   r   r   e   s$    




r   c                sH    fddt D }x*|D ]"}|| }|rt|dgS qW t|  S )a  
    Search `docstr` for type(-s) of `param_str`.

    >>> _search_param_in_docstr(':type param: int', 'param')
    ['int']
    >>> _search_param_in_docstr('@type param: int', 'param')
    ['int']
    >>> _search_param_in_docstr(
    ...   ':type param: :class:`threading.Thread`', 'param')
    ['threading.Thread']
    >>> bool(_search_param_in_docstr('no document', 'param'))
    False
    >>> _search_param_in_docstr(':param int param: some description', 'param')
    ['int']

    c                s    g | ]}t |t   qS r   )r   compileescape).0p)r   r   r   
<listcomp>   s   z+_search_param_in_docstr.<locals>.<listcomp>r   )DOCSTRING_PARAM_PATTERNSr/   _strip_rst_roler   r    )r   r   Zpatternspatternr   r   )r   r   _search_param_in_docstr   s    


rA   c             C   s    t | }|r|dS | S dS )a  
    Strip off the part looks like a ReST role in `type_str`.

    >>> _strip_rst_role(':class:`ClassName`')  # strip off :class:
    'ClassName'
    >>> _strip_rst_role(':py:obj:`module.Object`')  # works with domain
    'module.Object'
    >>> _strip_rst_role('ClassName')  # do nothing when not ReST role
    'ClassName'

    See also:
    http://sphinx-doc.org/domains.html#cross-referencing-python-objects

    r   N)REST_ROLE_PATTERNr   r   )r7   r   r   r   r   r?      s    

r?   c          	   C   s   t td}|d krg S x td|D ]}d| | }q&W | jj}y|j|t|dd}W n t	k
rr   g S X y&t
| }|jd jd jd }W n ttfk
r   g S X |jdkrg S d	d
lm} || j| |}	|	 }
tt|
|S )Nz
    def pseudo_docstring_stuff():
        '''
        Create a pseudo function for docstring statements.
        Need this docstring so that if the below part is not valid Python this
        is still a function.
        '''
    {}
    z((?:\w+\.)*\w+)\.z
import %s
F)Zerror_recovery)namer'   Z	atom_exprr   )FunctionContext)r   r   r   findall	evaluatorZlatest_grammarr   formatr   r   nextZiter_funcdefsr3   r   
IndexErrorr4   jedi.evaluate.contextrF   Zget_function_executionr   _execute_types_in_stmt)module_contextr+   codeelementZgrammarmoduleZfuncdefstmtrF   function_contextZfunc_execution_contextr   r   r   _evaluate_for_statement_string   s2    
rT   c                s"     |}t fdd|D S )z
    Executing all types or general elements that we find in a statement. This
    doesn't include tuple, list and dict literals, because the stuff they
    contain is executed. (Used as type information).
    c             3   s   | ]}t  j|V  qd S )N)_execute_array_valuesrH   )r;   d)rN   r   r   	<genexpr>   s   z)_execute_types_in_stmt.<locals>.<genexpr>)Z	eval_noder	   	from_sets)rN   rR   Zdefinitionsr   )rN   r   rM      s    

rM   c                sv   ddl m}m} t||rjg }x:| D ].}t fdd| D }|t	| q(W | |j
|hS | S dS )z
    Tuples indicate that there's not just one return value, but the listed
    ones.  `(str, int)` means that it returns a tuple with both types.
    r   )SequenceLiteralContextFakeSequencec             3   s   | ]}t  |V  qd S )N)rU   )r;   typ)rH   r   r   rW     s   z(_execute_array_values.<locals>.<genexpr>N)Zjedi.evaluate.context.iterablerY   rZ   r   Z
py__iter__r	   rX   Zinferappendr   Z
array_typeZexecute_evaluated)rH   ZarrayrY   rZ   valuesZlazy_contextZobjectsr   )rH   r   rU      s    

rU   c                s   ddl m} ddlm}  fdd}|    }|jdkrDtS ||  }t	| |rt	| j
|r| j dkr| j
jj}||| O }|S )Nr   )InstanceArguments)FunctionExecutionContextc                s"   t  fddt| jjD S )Nc             3   s"   | ]}t  |D ]
}|V  qqd S )N)rT   )r;   r   r<   )rN   r   r   rW     s   z6infer_param.<locals>.eval_docstring.<locals>.<genexpr>)r	   from_iterablerA   rE   r5   )Z	docstring)rN   paramr   r   eval_docstring  s    
z#infer_param.<locals>.eval_docstringZlambdef__init__)Zjedi.evaluate.context.instancer^   rL   r_   get_root_contextZget_parent_functionr4   r
   	py__doc__r   Zvar_argsrS   Z
py__name__instanceclass_context)Zexecution_contextra   r^   r_   rb   functypesrg   r   )rN   ra   r   infer_param  s    


rj   c             c   s@   dd }x2||   D ]"}xt|  |D ]
}|V  q*W qW d S )Nc             s   sH   x*t D ]"}|| }|rt|dV  qW xt| D ]
}|V  q6W d S )Nr   )DOCSTRING_RETURN_PATTERNSr/   r?   r   r#   )rO   r<   r   r"   r   r   r   search_return_in_docstr(  s    

z3infer_return_types.<locals>.search_return_in_docstr)re   rT   rd   )rS   rl   r7   Z	type_evalr   r   r   infer_return_types%  s    	rm   )$__doc__r   textwrapr   Zparsor   r   Zjedi._compatibilityr   Zjedi.evaluate.utilsr   Zjedi.evaluate.cacher   Zjedi.evaluate.base_contextr   r	   r
   Zjedi.evaluate.lazy_contextr   r>   r9   Mrk   rB   r   r   r    r#   r   rA   r?   rT   rM   rU   rj   rm   r   r   r   r   <module>   s6   
!3