U
    42isg                     @  s  d dl mZ d dlZd dlmZ d dlmZ 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Z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.m0Z0 d d l1m2Z2 d d!l3m4Z4 erd d"l5m6Z6 d d#l7m8Z8 d$Z9e	ej:j;Z<ed%Z=d&d'd(d)d*d+d,Z>ed-d.d/Z?G d0d1 d1ej@ZAG d2d. d.ejBeAd3ZCd.d4d5d6d7ZDG d8d9 d9eCejBZEd:d)d;d<d=d>ZFG d?d@ d@eEejBZGG dAdB dBeGejBZHG dCdD dDeGejBZIG dEdF dFeCejBZJdS )G    )annotationsN)cached_property)	signature)Path)Any)Callable)cast)Iterable)Iterator)MutableMapping)NoReturn)overload)TYPE_CHECKING)TypeVar)getfslineno)ExceptionInfo)TerminalRepr)	Traceback)TracebackStyle)LEGACY_PATH)Config)ConftestImportFailure)_check_path)NODE_CTOR_FSPATH_ARG)Mark)MarkDecorator)NodeKeywords)fail)absolutepath)
commonpath)Stash)PytestWarning)Self)Session/_Tz
type[Node]Path | NoneLEGACY_PATH | Noner   )	node_typepathfspathreturnc                 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__r   AssertionErrorr   )r(   r)   r*    r3   1/tmp/pip-unpacked-wheel-7n2p7kht/_pytest/nodes.py_imply_path<   s    
r5   	_NodeTypeNode)boundc                      s6   e Zd ZdZddddZddd fd	d
Z  ZS )NodeMetaa  Metaclass used by :class:`Node` to enforce that direct construction raises
    :class:`Failed`.

    This behaviour supports the indirection introduced with :meth:`Node.from_parent`,
    the named constructor to be used instead of direct construction. The design
    decision to enforce indirection with :class:`NodeMeta` was made as a
    temporary aid for refactoring the collection tree, which was diagnosed to
    have :class:`Node` objects whose creational patterns were overly entangled.
    Once the refactoring is complete, this metaclass can be removed.

    See https://github.com/pytest-dev/pytest/projects/3 for an overview of the
    progress on detangling the :class:`Node` classes.
    r   r+   c                 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)r0   
__module__r1   r   )clskkwmsgr3   r3   r4   __call__c   s
    zNodeMeta.__call__ztype[_T]r%   r@   r+   c              
     s   zt  j||W S  tk
r   tt| d  fdd| D }ddlm} t	||  dt
| d t  j|| Y S X d S )N__init__c                   s    i | ]\}}| j kr||qS r3   )
parameters).0rA   vsigr3   r4   
<dictcomp>q   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.)superrD   	TypeErrorr   getattritemsZwarning_typesrN   r.   r/   set)r@   rA   rB   Zknown_kwrN   	__class__rJ   r4   _createl   s    	zNodeMeta._create)r1   r?   __qualname____doc__rD   rV   __classcell__r3   r3   rT   r4   r9   T   s   	r9   c                
   @  s  e Zd ZU dZded< dZd^dddd	d
ddddddZed ddddZe	ddddZ
ddddZdddddZe	dddd Zd!dd"d#Zddd$d%Zddd&d'Zd(dd)d*Zd+dd,d-Zd_d/d0dd1d2d3Zd`dd4d5d6d7Zdadd8d5d9d:Zedd;d5d<d=Zedd>d>d?d@d=Zdbdd;d;d?dAd=ZdBddCdDZdEddFdGZdHddIdJdKZdLdMdNdOdPZdQdRdSdTdUZdcdQdVdWdXdYdZZdddQdVd[dXd\d]ZdS )er7   zBase class of :class:`Collector` and :class:`Item`, the components of
    the test collection tree.

    ``Collector``\'s are the internal nodes of the tree, and ``Item``\'s are the
    leaf nodes.
    r   r*   )r=   parentconfigsessionr)   _nodeid_store__dict__NstrNode | NoneConfig | NoneSession | Noner'   r&   
str | NoneNone)r=   rZ   r[   r\   r*   r)   nodeidr+   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 providedr)   r*   z::()z!nodeid or parent must be providedz::)r=   rZ   r[   rP   r\   rQ   r5   typer)   r   keywordsown_markersrS   extra_keyword_matchesr2   r]   rf   r    stashr^   )selfr=   rZ   r[   r\   r*   r)   rf   r3   r3   r4   rF      s4    
zNode.__init__r"   )rZ   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_parentrZ   )rP   rV   )r@   rZ   rB   r3   r3   r4   from_parent   s
    zNode.from_parentzpluggy.HookRelayr:   c                 C  s   | j | jS )z6fspath-sensitive hook proxy used to call pytest hooks.)r\   Zgethookproxyr)   rm   r3   r3   r4   ihook   s    z
Node.ihookc                 C  s   d | jjt| dd S )Nz<{} {}>r=   )r0   rU   r1   rQ   ro   r3   r3   r4   __repr__   s    zNode.__repr__Warning)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.
        z8warning must be an instance of Warning or subclass, got NrM   )categoryfilenamelineno)
isinstancerr   
ValueErrorget_fslocation_from_itemr2   r.   warn_explicitr`   )rm   rs   r)   rv   r3   r3   r4   r/      s    
z	Node.warnc                 C  s   | j S )z;A ::-separated string denoting its collection tree address.)r]   ro   r3   r3   r4   rf     s    zNode.nodeidintc                 C  s
   t | jS N)hashr]   ro   r3   r3   r4   __hash__  s    zNode.__hash__c                 C  s   d S r|   r3   ro   r3   r3   r4   setup   s    z
Node.setupc                 C  s   d S r|   r3   ro   r3   r3   r4   teardown#  s    zNode.teardownzIterator[Node]c                 c  s   | }|dk	r|V  |j }qdS )zIterate over all parent collectors starting from and including self
        up to the root of the collection tree.

        .. versionadded:: 8.1
        N)rZ   )rm   rZ   r3   r3   r4   iter_parents&  s    zNode.iter_parentsz
list[Node]c                 C  s.   g }| }|dk	r"| | |j}q|  |S )zxReturn a list of all parent collectors starting from the root of the
        collection tree down to and including self.N)appendrZ   reverse)rm   chainitemr3   r3   r4   	listchain1  s    
zNode.listchainTzstr | MarkDecoratorbool)markerr   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   rw   r   r`   rQ   rx   ri   r=   rj   r   markinsert)rm   r   r   r   Zmarker_r3   r3   r4   
add_marker<  s    

zNode.add_markerzIterator[Mark])r=   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 )rM   Nr3   rH   xr3   r3   r4   	<genexpr>X  s     z$Node.iter_markers.<locals>.<genexpr>r<   )iter_markers_with_noderm   r=   r3   r3   r4   iter_markersR  s    zNode.iter_markerszIterator[tuple[Node, Mark]]c                 c  s@   |   D ]2}|jD ]&}|dks.t|dd|kr||fV  qq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.
        Nr=   )r   rj   rQ   )rm   r=   noder   r3   r3   r4   r   Z  s    
zNode.iter_markers_with_nodezMark | Nonec                 C  s   d S r|   r3   r   r3   r3   r4   get_closest_markerg  s    zNode.get_closest_markerr   )r=   defaultr+   c                 C  s   d S r|   r3   rm   r=   r   r3   r3   r4   r   j  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.
        r<   )nextr   r   r3   r3   r4   r   m  s    zset[str]c                 C  s$   t  }|  D ]}||j q|S )z;Return a set of all extra keywords in self and any parents.)rS   r   updaterk   )rm   Zextra_keywordsr   r3   r3   r4   listextrakeywordsv  s    zNode.listextrakeywordsz	list[str]c                 C  s   dd |   D S )Nc                 S  s   g | ]
}|j qS r3   r<   r   r3   r3   r4   
<listcomp>~  s     z"Node.listnames.<locals>.<listcomp>)r   ro   r3   r3   r4   	listnames}  s    zNode.listnameszCallable[[], object])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)rm   r   r3   r3   r4   r     s    zNode.addfinalizerztype[_NodeType]z_NodeType | NonerE   c                 C  s$   |   D ]}t||r|  S qdS )zGet the closest 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)r   rw   )rm   r@   r   r3   r3   r4   	getparent  s    

zNode.getparentExceptionInfo[BaseException]r   excinfor+   c                 C  s   |j S r|   )	traceback)rm   r   r3   r3   r4   _traceback_filter  s    zNode._traceback_filterzTracebackStyle | Noner   )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rnd}d}n| j}|dkrd}|d kr| jddd	krd	}nd}| j d
krd}nd}| j dkrdnd}ztt | jjjk}W n tk
r   d}Y nX |jd|| jdd||||dS )Nr   )FixtureLookupErrorvalue	fulltraceFlongautotbstyleshortrM   T   
showlocals)Zfuncargsabspathr   r   tbfiltertruncate_localstruncate_args)Z_pytest.fixturesr   rw   r   r   r   from_exceptioncauser   	Exceptionr>   Z
formatreprr[   	getoptionr   Zget_verbosityr   osgetcwdZinvocation_paramsdirOSErrorZgetrepr)rm   r   r   r   r   r   r   r   r3   r3   r4   _repr_failure_py  sF    

zNode._repr_failure_pystr | TerminalReprc                 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   )rm   r   r   r3   r3   r4   repr_failure  s    zNode.repr_failure)NNNNNN)T)N)N)N)N)N)r1   r?   rW   rX   __annotations__	__slots__rF   classmethodrn   propertyrp   rq   r/   rf   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r3   r3   r3   r4   r7      sR   
      =%	 		 = )	metaclassztuple[str | Path, int | None])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.
    * "path": just a path

    :rtype: A tuple of (str|Path, int) with filename and 0-based line number.
    locationNr   objr)   zunknown location)rQ   r   )r   r   r   r3   r3   r4   ry     s    
ry   c                   @  sT   e Zd ZdZG dd deZejddddZdd	d
ddZ	ddd
ddZ
dS )	CollectorzBase class of all collectors.

    Collector create children through `collect()` and thus iteratively build
    the collection tree.
    c                   @  s   e Zd ZdZdS )zCollector.CollectErrorz6An error during collection, contains a custom message.Nr1   r?   rW   rX   r3   r3   r3   r4   CollectError  s   r   zIterable[Item | Collector]r:   c                 C  s   t ddS )z;Collect children (items and collectors) for this collector.ZabstractNNotImplementedErrorro   r3   r3   r4   collect  s    zCollector.collectr   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   )rw   r   r   r[   r   r`   argsr   )rm   r   excr   r3   r3   r4   r     s     zCollector.repr_failurer   c                 C  sB   t | dr<|j}|j| jd}||kr2|jtd}||S |jS )Nr)   r)   )Zexcludepath)hasattrr   Zcutr)   tracebackcutdirfilter)rm   r   r   Z
ntracebackr3   r3   r4   r     s    

zCollector._traceback_filterN)r1   r?   rW   rX   r   r   abcabstractmethodr   r   r   r3   r3   r3   r4   r     s   r   r#   rd   )r\   r)   r+   c                 C  s@   | j D ]4}t|||krt||}|dkr2dn|  S qd S )Nr;    )Z_initialpathsr   r`   relative_to)r\   r)   Zinitial_pathrelr3   r3   r4   _check_initialpaths_for_relpath"  s
    
r   c                      sZ   e Zd ZdZdddddddd	dd
d	 fddZeddddddd fddZ  ZS )FSCollectorz%Base class for filesystem collectors.Nr'   zPath | Node | Noner&   rd   ra   rb   rc   re   )	r*   path_or_parentr)   r=   rZ   r[   r\   rf   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rz|
|j	}	W n tk
r   Y n
X t|	}|tjt}|| _	|d kr|d k	st|j}|d kr2z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 )Nrg   )r=   rZ   r[   r\   rf   r)   )rw   r7   r2   r   r   r   r5   rh   r=   r)   r   rx   r`   replacer   sepSEPr\   r[   Zrootpathr   rO   rF   )
rm   r*   r   r)   r=   rZ   r[   r\   rf   r   rT   r3   r4   rF   -  sH    


zFSCollector.__init__)r*   r)   r"   )r*   r)   r+   c                  s   t  jf |||d|S )zThe public constructor.)rZ   r*   r)   )rO   rn   )r@   rZ   r*   r)   rB   rT   r3   r4   rn   c  s    
zFSCollector.from_parent)NNNNNNNN)r1   r?   rW   rX   rF   r   rn   rY   r3   r3   rT   r4   r   *  s           $6r   c                   @  s   e Zd ZdZdS )FilezOBase class for collecting tests from a file.

    :ref:`non-python tests`.
    Nr   r3   r3   r3   r4   r   p  s   r   c                   @  s   e Zd ZdZdS )	Directorya  Base class for collecting files from a directory.

    A basic directory collector does the following: goes over the files and
    sub-directories in the directory and creates collectors for them by calling
    the hooks :hook:`pytest_collect_directory` and :hook:`pytest_collect_file`,
    after checking that they are not ignored using
    :hook:`pytest_ignore_collect`.

    The default directory collectors are :class:`~pytest.Dir` and
    :class:`~pytest.Package`.

    .. versionadded:: 8.0

    :ref:`custom directory collectors`.
    Nr   r3   r3   r3   r4   r   w  s   r   c                      s   e Zd ZdZdZdddddd fdd	Zdd
ddZejdd
ddZ	dddddddZ
dd
ddZedd
ddZ  ZS )ItemzBase class of all test invocation items.

    Note that for a single function there might be multiple test invocation items.
    Nrb   rc   rd   re   )r[   r\   rf   r+   c                   s6   t  j||f|||d| g | _g | _|   d S )N)r[   r\   rf   )rO   rF   _report_sectionsZuser_properties-_check_item_and_collector_diamond_inheritance)rm   r=   rZ   r[   r\   rf   rB   rT   r3   r4   rF     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 r|   )
issubclassr   r1   )rH   baser3   r3   r4   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/)	rh   rQ   setattrjoin	__bases__r.   r/   r1   r!   )rm   r@   	attr_nameproblemsr3   r3   r4   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 subclassNr   ro   r3   r3   r4   runtest  s    zItem.runtestr`   )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   r   )rm   r   r   r   r3   r3   r4   add_report_section  s    zItem.add_report_sectionz.tuple[os.PathLike[str] | str, int | None, str]c                 C  s   | j ddfS )aP  Get location information for this item for test reports.

        Returns a tuple with three elements:

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

        .. seealso:: :ref:`non-python tests`
        Nr   r   ro   r3   r3   r4   
reportinfo  s    zItem.reportinfoztuple[str, int | None, str]c                 C  sF   |   }t|d }| j|}t|d tks4t||d |d fS )z
        Returns a tuple of ``(relfspath, lineno, testname)`` for this item
        where ``relfspath`` is file path relative to ``config.rootpath``
        and lineno is a 0-based line number.
        r   r   rM   )r   r   r\   Z_node_location_to_relpathrh   r`   r2   )rm   r   r)   Z	relfspathr3   r3   r4   r     s
    zItem.location)NNNN)r1   r?   rW   rX   nextitemrF   r   r   r   r   r   r   r   r   rY   r3   r3   rT   r4   r     s       	r   )K
__future__r   r   	functoolsr   inspectr   r   pathlibr   typingr   r   r   r	   r
   r   r   r   r   r   r.   ZpluggyZ_pytest._codeZ_pytestr   Z_pytest._code.coder   r   r   r   Z_pytest.compatr   Z_pytest.configr   r   Z_pytest.config.compatr   Z_pytest.deprecatedr   Z_pytest.mark.structuresr   r   r   Z_pytest.outcomesr   Z_pytest.pathlibr   r   Z_pytest.stashr    Z_pytest.warning_typesr!   Ztyping_extensionsr"   Z_pytest.mainr#   r   __file__rZ   r   r%   r5   r6   ABCMetar9   ABCr7   ry   r   r   r   r   r   r   r3   r3   r3   r4   <module>   sp   ,  b/F