B
    Wcf                 @   s  d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dlm!Z! d dl"m#Z# d dl"m$Z$ d dl%m&Z& d dl%m'Z' d dl%m(Z( d dl)m*Z* d d l+m,Z, d d!l+m-Z- d d"l.m/Z/ d d#l0m1Z1 erd d$l2m3Z3 d d%lm4Z4 d&Z5eej6j7Z8e9ee9 d'd(d)Z:eedd*d+d,Z;ed- ee ee ed.d/d0Z<ed1d-d2Z=G d3d4 d4e>Z?G d5d- d-e?d6Z@d-eee9ef eeA f d7d8d9ZBG d:d; d;e@ZCd<eee9 d=d>d?ZDG d@dA dAeCZEG dBdC dCeEZFG dDdE dEe@ZGdS )F    N)	signature)Path)Any)Callable)cast)Iterable)Iterator)List)MutableMapping)Optional)overload)Set)Tuple)Type)TYPE_CHECKING)TypeVar)Union)getfslineno)ExceptionInfo)TerminalRepr)cached_property)LEGACY_PATH)Config)ConftestImportFailure)#FSCOLLECTOR_GETHOOKPROXY_ISINITPATH)NODE_CTOR_FSPATH_ARG)Mark)MarkDecorator)NodeKeywords)fail)absolutepath)
commonpath)Stash)PytestWarning)Session)_TracebackStyle/)nodeidreturnc             c   s   d}|  d}|dkrd}dV  x>|  t||}|dkr:P |dkrP| d| V  |tt }q"W x<|  d|}|dkrxP |dkr| d| V  |td }qbW | r| V  dS )a  Return the parent node IDs of a given node ID, inclusive.

    For the node ID

        "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source"

    the result would be

        ""
        "testing"
        "testing/code"
        "testing/code/test_excinfo.py"
        "testing/code/test_excinfo.py::TestFormattedExcinfo"
        "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source"

    Note that / components are only considered until the first ::.
    r   z::N )findSEPlen)r'   posZfirst_colonsZat r/   ,lib/python3.7/site-packages/_pytest/nodes.pyiterparentnodeids3   s*    
r1   )pathfspathr(   c             C   s&   t || kr"td|d| dd S )NzPath(z) != z8
if both path and fspath are given they need to be equal)r   
ValueError)r2   r3   r/   r/   r0   _check_path`   s    r5   Node)	node_typer2   r3   r(   c             C   sV   |d k	r t jtj| jddd |d k	r>|d k	r:t|| |S |d k	sJtt|S d S )N)Znode_type_name   )
stacklevel)warningswarnr   format__name__r5   AssertionErrorr   )r7   r2   r3   r/   r/   r0   _imply_pathh   s    
r?   	_NodeType)Zboundc                   s$   e Zd Zdd Z fddZ  ZS )NodeMetac             O   s*   dj | j d| j d}t|dd d S )NzDirect construction of {name} has been deprecated, please use {name}.from_parent.
See https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent for more details..)nameF)pytrace)r<   
__module__r=   r   )selfkkwmsgr/   r/   r0   __call__   s    zNodeMeta.__call__c          
      s   yt  j||S  tk
rz   tt| d  fdd| D }ddlm} t	||  dt
| d t  j||S X d S )N__init__c                s    i | ]\}}| j kr||qS r/   )Z
parameters).0rG   v)sigr/   r0   
<dictcomp>   s    z$NodeMeta._create.<locals>.<dictcomp>   )PytestDeprecationWarningz7 is not using a cooperative constructor and only takes z.
See https://docs.pytest.org/en/stable/deprecations.html#constructors-of-custom-pytest-node-subclasses-should-take-kwargs for more details.)superrJ   	TypeErrorr   getattritemsZwarning_typesrQ   r:   r;   set)rF   rG   rH   Zknown_kwrQ   )	__class__)rN   r0   _create   s    zNodeMeta._create)r=   rE   __qualname__rJ   rX   __classcell__r/   r/   )rW   r0   rA      s   	rA   c            
   @   s  e Zd ZU dZeed< dZd@edee	 dee ee
 ee dddd	Zed d
ddZedd ZedddZeddddZeedddZedddZddddZddddZed  dddZdAeeef edd d!d"ZdBee ee d#d$d%Z dCee ee!d ef  d#d&d'Z"e#eee d#d(d)Z$e#eeed*d+d)Z$dDeee ee d*d,d)Z$e%e dd-d.Z&ee dd/d0Z'e(g e)f dd1d2d3Z*e+e, ee, d4d5d6Z-e.e/ dd7d8d9Z0dEe.e/ d:e1d;d<d=Z2dFe.e/ d:eee1f d;d>d?Z3dS )Gr6   zBase class for Collector and Item, the components of the test
    collection tree.

    Collector subclasses have children; Items are leaf nodes.
    r3   )rC   parentconfigsessionr2   _nodeid_store__dict__NzOptional[Node]zOptional[Session])rC   r[   r\   r]   r3   r2   r'   r(   c             C   s   || _ || _|r|| _n|s$td|j| _|r8|| _n|sDtd|j| _|d krh|d krht|dd }tt| ||d| _t	| | _
g | _t | _|d k	rd|kst|| _n"| jstd| jjd | j  | _t | _| j| _d S )Nz!config or parent must be providedz"session or parent must be providedr2   )r3   z::()z!nodeid or parent must be providedz::)rC   r[   r\   rS   r]   rT   r?   typer2   r   keywordsown_markersrV   extra_keyword_matchesr>   r^   r'   r"   Zstashr_   )rF   rC   r[   r\   r]   r3   r2   r'   r/   r/   r0   rK      s4    
zNode.__init__)r[   c             K   s4   d|krt dd|kr t d| jf d|i|S )a:  Public constructor for Nodes.

        This indirection got introduced in order to enable removing
        the fragile logic from the node constructors.

        Subclasses can use ``super().from_parent(...)`` when overriding the
        construction.

        :param parent: The parent node of this Node.
        r\   z.config is not a valid argument for from_parentr]   z/session is not a valid argument for from_parentr[   )rS   rX   )clsr[   rH   r/   r/   r0   from_parent   s
    zNode.from_parentc             C   s   | j | jS )z6fspath-sensitive hook proxy used to call pytest hooks.)r]   gethookproxyr2   )rF   r/   r/   r0   ihook  s    z
Node.ihook)r(   c             C   s   d | jjt| dd S )Nz<{} {}>rC   )r<   rW   r=   rT   )rF   r/   r/   r0   __repr__  s    zNode.__repr__)warningr(   c             C   sN   t |tstd|t| \}}|dk	s0ttj|dt||d d dS )aw  Issue a warning for this Node.

        Warnings will be displayed after the test session, unless explicitly suppressed.

        :param Warning warning:
            The warning instance to issue.

        :raises ValueError: If ``warning`` instance is not a subclass of Warning.

        Example usage:

        .. code-block:: python

            node.warn(PytestWarning("some message"))
            node.warn(UserWarning("some message"))

        .. versionchanged:: 6.2
            Any subclass of :class:`Warning` is now accepted, rather than only
            :class:`PytestWarning <pytest.PytestWarning>` subclasses.
        z<warning must be an instance of Warning or subclass, got {!r}NrP   )categoryfilenamelineno)	
isinstanceWarningr4   r<   get_fslocation_from_itemr>   r:   warn_explicitstr)rF   rj   r2   rm   r/   r/   r0   r;     s    
z	Node.warnc             C   s   | j S )z;A ::-separated string denoting its collection tree address.)r^   )rF   r/   r/   r0   r'   7  s    zNode.nodeidc             C   s
   t | jS )N)hashr^   )rF   r/   r/   r0   __hash__<  s    zNode.__hash__c             C   s   d S )Nr/   )rF   r/   r/   r0   setup?  s    z
Node.setupc             C   s   d S )Nr/   )rF   r/   r/   r0   teardownB  s    zNode.teardownc             C   s2   g }| }x|dk	r$| | |j}q
W |  |S )zReturn list of all parent collectors up to self, starting from
        the root of collection tree.

        :returns: The nodes.
        N)appendr[   reverse)rF   chainitemr/   r/   r0   	listchainE  s    


zNode.listchainT)markerrw   r(   c             C   sn   ddl m} t|tr|}nt|tr2t||}ntd|| j|j< |rZ| j	
|j n| j	d|j dS )zDynamically add a marker object to the node.

        :param marker:
            The marker.
        :param append:
            Whether to append the marker, or prepend it.
        r   )MARK_GENz'is not a string or pytest.mark.* MarkerN)Z_pytest.markr}   rn   r   rr   rT   r4   rb   rC   rc   rw   markinsert)rF   r|   rw   r}   Zmarker_r/   r/   r0   
add_markerS  s    


zNode.add_marker)rC   r(   c             C   s   dd | j |dD S )zIterate over all markers of the node.

        :param name: If given, filter the results by the name attribute.
        :returns: An iterator of the markers of the node.
        c             s   s   | ]}|d  V  qdS )rP   Nr/   )rL   xr/   r/   r0   	<genexpr>q  s    z$Node.iter_markers.<locals>.<genexpr>)rC   )iter_markers_with_node)rF   rC   r/   r/   r0   iter_markersk  s    zNode.iter_markersc             c   sL   xFt |  D ]6}x0|jD ]&}|dks6t|dd|kr||fV  qW qW dS )zIterate over all markers of the node.

        :param name: If given, filter the results by the name attribute.
        :returns: An iterator of (node, mark) tuples.
        NrC   )reversedr{   rc   rT   )rF   rC   noder~   r/   r/   r0   r   s  s    zNode.iter_markers_with_nodec             C   s   d S )Nr/   )rF   rC   r/   r/   r0   get_closest_marker  s    zNode.get_closest_marker)rC   defaultr(   c             C   s   d S )Nr/   )rF   rC   r   r/   r/   r0   r     s    c             C   s   t | j|d|S )zReturn the first marker matching the name, from closest (for
        example function) to farther level (for example module level).

        :param default: Fallback return value if no marker was found.
        :param name: Name to filter by.
        )rC   )nextr   )rF   rC   r   r/   r/   r0   r     s    	c             C   s(   t  }x|  D ]}||j qW |S )z;Return a set of all extra keywords in self and any parents.)rV   r{   updaterd   )rF   Zextra_keywordsrz   r/   r/   r0   listextrakeywords  s    zNode.listextrakeywordsc             C   s   dd |   D S )Nc             S   s   g | ]
}|j qS r/   )rC   )rL   r   r/   r/   r0   
<listcomp>  s    z"Node.listnames.<locals>.<listcomp>)r{   )rF   r/   r/   r0   	listnames  s    zNode.listnames)finr(   c             C   s   | j j||  dS )zRegister a function to be called without arguments when this node is
        finalized.

        This method can only be called when this node is active
        in a setup chain, for example during self.setup().
        N)r]   Z_setupstateaddfinalizer)rF   r   r/   r/   r0   r     s    zNode.addfinalizer)re   r(   c             C   s8   | }x|rt ||s|j}qW |dks4t ||s4t|S )zGet the next parent node (including self) which is an instance of
        the given class.

        :param cls: The node class to search for.
        :returns: The node, if found.
        N)rn   r[   r>   )rF   re   Zcurrentr/   r/   r0   	getparent  s
    
zNode.getparent)excinfor(   c             C   s   d S )Nr/   )rF   r   r/   r/   r0   _prunetraceback  s    zNode._prunetracebackzOptional[_TracebackStyle])r   styler(   c             C   s>  ddl m} t|jtr&t|jj}t|jtj	r@|jj
s@d}t|j|rV|j S | jddrjd}n>tj|jd g}| | t|jdkr||_|dkrd}|d kr| jd	dd
krd
}nd}| jdddkrd}nd}ytt | jjjk}W n tk
r   d}Y nX |jd|| jdd|d|dS )Nr   )FixtureLookupErrorvalue	fulltraceFZlongr)   autotbstyleshortverboserP   T
showlocals)Zfuncargsabspathr   r   Ztbfiltertruncate_locals)Z_pytest.fixturesr   rn   r   r   r   Zfrom_exc_infor   r   	ExceptionrD   Z
formatreprr\   	getoption_pytest_codeZ	Traceback	tracebackr   r-   r   osgetcwdZinvocation_paramsdirOSErrorZgetrepr)rF   r   r   r   tbr   r   r/   r/   r0   _repr_failure_py  sD    


zNode._repr_failure_pyc             C   s   |  ||S )zReturn a representation of a collection or test failure.

        .. seealso:: :ref:`non-python tests`

        :param excinfo: Exception information for the failure.
        )r   )rF   r   r   r/   r/   r0   repr_failure  s    zNode.repr_failure)NNNNNN)T)N)N)N)N)N)4r=   rE   rY   __doc__r   __annotations__	__slots__rr   r   r   r   rK   classmethodrf   propertyrh   ri   ro   r;   r'   intrt   ru   rv   r	   r{   r   r   boolr   r   r   r   r   r   r   r   r   r   r   r   objectr   r   r@   r   r   BaseExceptionr   r   r   r   r/   r/   r/   r0   r6      sR   
      4'	
		
6
)	metaclass)r   r(   c             C   sL   t | dd}|dk	r |dd S t | dd}|dk	r<t|S t | dddfS )a  Try to extract the actual location from a node, depending on available attributes:

    * "location": a pair (path, lineno)
    * "obj": a Python object that the node wraps.
    * "fspath": just a path

    :rtype: A tuple of (str|Path, int) with filename and line number.
    locationN   objr3   zunknown locationr)   )rT   r   )r   r   r   r/   r/   r0   rp     s    
rp   c               @   sf   e Zd ZdZG dd deZeed  dddZe	e
 eeef dd	d
Ze	e
 ddddZdS )	Collectorz\Collector instances create children through collect() and thus
    iteratively build a tree.c               @   s   e Zd ZdZdS )zCollector.CollectErrorz6An error during collection, contains a custom message.N)r=   rE   rY   r   r/   r/   r/   r0   CollectError  s   r   )Itemr   )r(   c             C   s   t ddS )zRReturn a list of children (items and collectors) for this
        collection node.ZabstractN)NotImplementedError)rF   r/   r/   r0   collect  s    zCollector.collect)r   r(   c             C   sX   t |j| jr0| jdds0|j}t|jd S | jdd}|dkrJd}| j||dS )zyReturn a representation of a collection failure.

        :param excinfo: Exception information for the failure.
        r   Fr   r   r   r   )r   )rn   r   r   r\   r   rr   argsr   )rF   r   excr   r/   r/   r0   r     s    zCollector.repr_failureNc             C   s@   t | dr<|j}|j| jd}||kr2|jtd}| |_d S )Nr2   )r2   )Zexcludepath)hasattrr   Zcutr2   tracebackcutdirfilter)rF   r   r   Z
ntracebackr/   r/   r0   r   0  s    
zCollector._prunetraceback)r=   rE   rY   r   r   r   r   r   r   r   r   rr   r   r   r   r/   r/   r/   r0   r     s   r   r$   )r]   r2   r(   c             C   s@   x:| j D ]0}t|||krt||}|dkr4dS |S qW d S )NrB   r*   )Z_initialpathsr!   rr   relative_to)r]   r2   Zinitial_pathrelr/   r/   r0   _check_initialpaths_for_relpath9  s
    r   c                   s   e Zd Zdee eeeef  ee ee ee ee	 ed ee dd	 fddZ
edddee ee d fddZd	d
ddZeed	f edddZ  ZS )FSCollectorNr$   )	r3   path_or_parentr2   rC   r[   r\   r]   r'   r(   c	       
         sN  |r@t |tr&|d ksttt|}nt |tr@|d ks<t|}tt| ||d}|d kr|j}|d k	r|j	|kry|
|j	}	W n tk
r   Y n
X t|	}|tjt}|| _	|d kr|d k	st|j}|d kr2yt| j	
|jj}W n  tk
r   t||}Y nX |r2tjtkr2|tjt}t j||||||d d S )N)r3   )rC   r[   r\   r]   r'   r2   )rn   r6   r>   r   r   r   r?   ra   rC   r2   r   r4   rr   replacer   sepr,   r]   r\   Zrootpathr   rR   rK   )
rF   r3   r   r2   rC   r[   r\   r]   r'   r   )rW   r/   r0   rK   B  sF    


zFSCollector.__init__)r3   r2   c               s   t  jf |||d|S )zThe public constructor.)r[   r3   r2   )rR   rf   )re   r[   r3   r2   rH   )rW   r/   r0   rf   x  s    
zFSCollector.from_parentzos.PathLike[str])r3   c             C   s   t jtdd | j|S )Nr   )r9   )r:   r;   r   r]   rg   )rF   r3   r/   r/   r0   rg     s    zFSCollector.gethookproxy)r2   r(   c             C   s   t jtdd | j|S )Nr   )r9   )r:   r;   r   r]   
isinitpath)rF   r2   r/   r/   r0   r     s    zFSCollector.isinitpath)NNNNNNNN)r=   rE   rY   r   r   r   r   r6   rr   r   rK   r   rf   rg   r   r   rZ   r/   r/   )rW   r0   r   A  s          :,$r   c               @   s   e Zd ZdZdS )FilezOBase class for collecting tests from a file.

    :ref:`non-python tests`.
    N)r=   rE   rY   r   r/   r/   r/   r0   r     s   r   c                   s   e Zd ZdZdZdee ed ee dd fddZdddd	Z	ddd
dZ
eeeddddZeedef ee ef dddZeeeee ef dddZ  ZS )r   zvA basic test invocation item.

    Note that for a single function there might be multiple test invocation items.
    Nr$   )r\   r]   r'   r(   c                s6   t  j||f|||d| g | _g | _|   d S )N)r\   r]   r'   )rR   rK   _report_sectionsZuser_properties-_check_item_and_collector_diamond_inheritance)rF   rC   r[   r\   r]   r'   rH   )rW   r/   r0   rK     s    zItem.__init__)r(   c             C   s`   t | }d}t||drdS t||d ddd |jD }|r\t|j d| d	t dS )
z
        Check if the current type inherits from both File and Collector
        at the same time, emitting a warning accordingly (#8447).
        Z)_pytest_diamond_inheritance_warning_shownFNTz, c             s   s   | ]}t |tr|jV  qd S )N)
issubclassr   r=   )rL   baser/   r/   r0   r     s    zEItem._check_item_and_collector_diamond_inheritance.<locals>.<genexpr>zF is an Item subclass and should not be a collector, however its bases z are collectors.
Please split the Collectors and the Item into separate node types.
Pytest Doc example: https://docs.pytest.org/en/latest/example/nonpython.html
example pull request on a plugin: https://github.com/asmeurer/pytest-flakes/pull/40/)	ra   rT   setattrjoin	__bases__r:   r;   r=   r#   )rF   re   Z	attr_nameZproblemsr/   r/   r0   r     s    z2Item._check_item_and_collector_diamond_inheritancec             C   s   t ddS )zRun the test case for this item.

        Must be implemented by subclasses.

        .. seealso:: :ref:`non-python tests`
        z,runtest must be implemented by Item subclassN)r   )rF   r/   r/   r0   runtest  s    zItem.runtest)whenkeycontentr(   c             C   s   |r| j |||f dS )a  Add a new report section, similar to what's done internally to add
        stdout and stderr captured output::

            item.add_report_section("call", "stdout", "report section contents")

        :param str when:
            One of the possible capture states, ``"setup"``, ``"call"``, ``"teardown"``.
        :param str key:
            Name of the section, can be customized at will. Pytest uses ``"stdout"`` and
            ``"stderr"`` internally.
        :param str content:
            The full contents as a string.
        N)r   rw   )rF   r   r   r   r/   r/   r0   add_report_section  s    zItem.add_report_sectionzos.PathLike[str]c             C   s   | j ddfS )aH  Get location information for this item for test reports.

        Returns a tuple with three elements:

        - The path of the test (default ``self.path``)
        - The line number of the test (default ``None``)
        - A name of the test to be shown (default ``""``)

        .. seealso:: :ref:`non-python tests`
        Nr*   )r2   )rF   r/   r/   r0   
reportinfo  s    zItem.reportinfoc             C   sL   |   }tt|d }| j|}t|d tks:t||d |d fS )Nr   r   rP   )	r   r    r   r3   r]   Z_node_location_to_relpathra   rr   r>   )rF   r   r2   Z	relfspathr/   r/   r0   r     s
    zItem.location)NNNN)r=   rE   rY   r   Znextitemr   r   rr   rK   r   r   r   r   r   r   r   r   r   rZ   r/   r/   )rW   r0   r     s      	$r   )Hr   r:   inspectr   Zpathlibr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   Z_pytest._coder   r   Z_pytest._code.coder   r   Z_pytest.compatr   r   Z_pytest.configr   r   Z_pytest.deprecatedr   r   Z_pytest.mark.structuresr   r   r   Z_pytest.outcomesr   Z_pytest.pathlibr    r!   Z_pytest.stashr"   Z_pytest.warning_typesr#   Z_pytest.mainr$   r%   r,   __file__r[   r   rr   r1   r5   r?   r@   ra   rA   r6   r   rp   r   r   r   r   r   r/   r/   r/   r0   <module>   st   -	  _$+L