U
    42i(                     @  st  d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	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Zddl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l0m1Z1 ddl0m2Z2 dd l3m4Z4 dd!l3m5Z5 dd"l6m7Z7 erdd#l8m9Z9 dd$l:m;Z; d%d&d'd(d)Z<d*d*d+d,d-Z=d.d/d0d1d2d3Z>d.d0d4d5d6Z?d.d7d8d9d:d;Z@d7d&d<d=d>ZAd7d?d<d@dAZBdBd?d+dCdDZCdBd.dEdFdGdHZDdBdIdJdKdLdMZEdNd.d&dOdPdQZFG dRdS dSZGG dTdU dUeHZIG dVdW dWeJZKejLG dXdY dYeeeMf ZNeG dZd[ d[ejOZPeG d\d7 d7ejQZRd*d]d^d_d`ZSejLdadbG dcdd ddZTdedfdBd*d?dddgdhdiZUdS )jzHCore implementation of the testing process: init, session, runtest loop.    )annotationsN)Path)AbstractSet)Callable)Dict)final)Iterable)Iterator)Literal)overload)Sequence)TYPE_CHECKING)nodes)Config)directory_arg)ExitCode)hookimpl)PytestPluginManager)
UsageError)Parser)PathAwareHookProxy)exitabsolutepath)bestrelpath
fnmatch_ex)safe_exists)scandir)CollectReport)
TestReport)collect_one_node)
SetupState)PytestWarning)Self)FixtureManagerr   None)parserreturnc                 C  s  | j ddddddddd	d
ddg	d | j dddg d | dd}|jddddddd | d}|jddddd | j dd d!d" |jd#d$d%tdd&d'd( |jd)d*d+d |jd,d*d-d |jd.d*d/d |jd0d1d2td3d4d5 |jd6d*d7d8d9d: |jd;d%d<d=d> | d?d@}|jdAdBdCd*dDd |jdEd*dFd |jdGddHdIdJ |jdKddHdLdJ |jdMddNdOdJ |jdPdQd dRtjtdPdSdTdU |jdVd*dWd7dXdY |jdZd[d*d\d7d]dY |jd^d*d_d7d`dY |jdadbdbddcgdddedf | j dgdhd7didj | dkdl}|jdmdnd t	dRdodp d S )qNnorecursedirsz)Directory patterns to avoid for recursionargsz*.eggz.*Z_darcsbuildZCVSdistZnode_modulesvenvz{arch})typedefaultZ	testpathszZDirectories to search for tests when no files or directories are given on the command lineZgeneralzRunning and selection optionsz-xz--exitfirststore_constmaxfail   z,Exit instantly on first error or failed test)actiondestconsthelpzpytest-warningsz-Wz--pythonwarningsappendz<Set which warnings to report, see -W option of Python itself)r3   r6   filterwarningsZlinelistz_Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings.)r.   r6   z	--maxfailnumstorer   z'Exit after first num failures or errors)metavarr3   r.   r4   r/   r6   z--strict-config
store_truezbAny warnings encountered while parsing the `pytest` section of the configuration file raise errorsz--strict-markerszVMarkers not registered in the `markers` section of the configuration file raise errorsz--strictz&(Deprecated) alias to --strict-markersz-cz--config-fileFILEZinifilenamezcLoad configuration from `FILE` instead of trying to locate one of the implicit configuration files.)r;   r.   r4   r6   z--continue-on-collection-errorsFcontinue_on_collection_errorsz4Force test execution even if collection errors occur)r3   r/   r4   r6   z	--rootdirrootdirzDefine root directory for tests. Can be relative path: 'root_dir', './root_dir', 'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: '$HOME/root_dir'.)r3   r4   r6   collect
collectionz--collectonlyz--collect-onlyz--coz&Only collect tests, don't execute themz--pyargsz1Try to interpret all arguments as Python packagesz--ignorepathz-Ignore path during collection (multi-allowed))r3   r;   r6   z--ignore-globz5Ignore path pattern during collection (multi-allowed)z
--deselectZnodeid_prefixzDDeselect item (via node id prefix) during collection (multi-allowed)z--confcutdirZ
confcutdirdir)optnamez1Only load conftest.py's relative to specified dir)r4   r/   r;   r.   r6   z--noconftestZ
noconftestz Don't load any conftest.py files)r3   r4   r/   r6   z--keepduplicatesz--keep-duplicateskeepduplicateszKeep duplicate testsz--collect-in-virtualenvcollect_in_virtualenvz2Don't ignore tests in a local virtualenv directoryz--import-modeprepend	importlibZ
importmodez\Prepend/append to sys.path when importing test modules and conftest files. Default: prepend.)r/   choicesr4   r6   Zconsider_namespace_packagesboolzEConsider namespace packages when resolving module names during import)r.   r/   r6   Zdebugconfigz(test session debugging and configurationz
--basetempZbasetempz^Base temporary directory for this test run. (Warning: this directory is removed if it exists.))r4   r/   r.   r;   r6   )
ZaddiniZgetgroupZ
_addoptionZ	addoptionintstr	functoolspartialr   validate_basetemp)r'   group rQ   0/tmp/pip-unpacked-wheel-7n2p7kht/_pytest/main.pypytest_addoption9   sT   
			rS   rL   rB   r(   c                 C  sl   d}| st |dddddd}|t t|  rDt ||t  t|  rht || S )NzWbasetemp must not be empty, the current working directory or any parent directory of itr   rJ   )basequeryr(   c                 S  s   | |krdS || j kS )z,Return whether query is an ancestor of base.T)parents)rU   rV   rQ   rQ   rR   is_ancestor   s    z&validate_basetemp.<locals>.is_ancestor)argparseArgumentTypeErrorr   cwdabsoluteresolve)rB   msgrX   rQ   rQ   rR   rO      s    


rO   r   z2Callable[[Config, Session], int | ExitCode | None]int | ExitCode)configdoitr(   c                 C  s`  t | }tj|_d}zz4|   d}| jj|d d}|| |pFd|_W nr tk
rn   tj|_ Y nT tk
r   tj|_Y n8 tt
jfk
r   tjj }tj}t|j t
jr|j jdk	r|j j}|dk rtj|j! d|j j" d | jj#|d	 ||_Y n t$k
r   tj%|_tjj }z| &|| j' W nX t
jk
r } z6|jdk	rr|j|_tjt|j d| d W 5 d}~X Y nX t|j t(rtjd
 Y nX W 5 d}t|j |dkrPz| jj	||jd W nX t
jk
rN } z6|jdk	r |j|_tjt|j d| d W 5 d}~X Y nX |   X |jS )zSkeleton command line program.r   N   )session
exitstatusz: 
r2   rc   )excinfoz(mainloop: caught unexpected SystemExit!
))Sessionfrom_configr   OKrd   oschdir	startpathhookZpytest_sessionfinishr   	Exception
returncodesysstderrwriter.   __name__Z_ensure_unconfigureZ_do_configureZpytest_sessionstartr   ZUSAGE_ERRORFailedTESTS_FAILEDKeyboardInterrupt_pytest_codeZExceptionInfoZfrom_currentZINTERRUPTED
isinstancevaluetypenamer^   Zpytest_keyboard_interruptBaseExceptionINTERNAL_ERRORZnotify_exceptionoption
SystemExit)r`   ra   rc   Z	initstaterg   excrd   rQ   rQ   rR   wrap_session  sd    

0
 
0
r   r`   r(   c                 C  s
   t | tS N)r   _mainr`   rQ   rQ   rR   pytest_cmdline_mainI  s    r   rh   zint | ExitCode | None)r`   rc   r(   c                 C  s<   | j j|d | j j|d |jr(tjS |jdkr8tjS dS )z[Default command line protocol for initialization, session,
    running tests and reporting.rf   r   N)rn   pytest_collectionpytest_runtestlooptestsfailedr   rv   testscollectedZNO_TESTS_COLLECTED)r`   rc   rQ   rQ   rR   r   M  s    
r   )rc   r(   c                 C  s   |    d S r   )perform_collectrf   rQ   rQ   rR   r   Z  s    r   rJ   c                 C  s   | j r2| jjjs2| d| j | j dkr(dndf | jjjr@dS t| jD ]b\}}|d t| jk rr| j|d  nd }|jj	j
||d | jr| | j| jrJ| | jqJdS )Nz%d error%s during collectionr2   s T)itemnextitem)r   r`   r   r>   InterruptedZcollectonly	enumerateitemslenrn   Zpytest_runtest_protocol
shouldfailru   
shouldstop)rc   ir   r   rQ   rQ   rR   r   ^  s     
$r   r   c                 C  s<   z |  d p|  dd W S  tk
r6   Y dS X dS )a  Attempt to detect if ``path`` is the root of a Virtual Environment by
    checking for the existence of the pyvenv.cfg file.

    [https://peps.python.org/pep-0405/]

    For regression protection we also check for conda environments that do not include pyenv.cfg yet --
    https://github.com/conda/conda/issues/13337 is the conda issue tracking adding pyenv.cfg.

    Checking for the `conda-meta/history` file per https://github.com/pytest-dev/pytest/issues/12652#issuecomment-2246336902.

    z
pyvenv.cfgz
conda-metahistoryFN)joinpathis_fileOSErrorrB   rQ   rQ   rR   _in_venvr  s    r   zbool | None)collection_pathr`   r(   c                   s    j dkrdS |jd jd}|p$g }|d}|rH|dd |D   |krTdS |jd jd}|pjg }|d	}|r|d
d |D  t fdd|D rdS |d}|st rdS   r|d}t fdd|D rdS d S )N__pycache__TZcollect_ignorer   ignorec                 s  s   | ]}t |V  qd S r   r   .0xrQ   rQ   rR   	<genexpr>  s     z(pytest_ignore_collect.<locals>.<genexpr>Zcollect_ignore_globZignore_globc                 s  s   | ]}t |V  qd S r   r   r   rQ   rQ   rR   r     s     c                 3  s"   | ]}t  t t|V  qd S r   )fnmatchrL   )r   globr   rQ   rR   r     s     rF   r)   c                 3  s   | ]}t | V  qd S r   r   )r   patr   rQ   rR   r     s     )	nameZ_getconftest_pathlistparent	getoptionextendanyr   is_dirZgetini)r   r`   Zignore_pathsZ
excludeoptZignore_globsZexcludegloboptZallow_in_venvZnorecursepatternsrQ   r   rR   pytest_ignore_collect  s<    
 
 


r   nodes.Collectorznodes.Collector | None)rB   r   r(   c                 C  s   t j|| dS )Nr   )Dirfrom_parentrB   r   rQ   rQ   rR   pytest_collect_directory  s    r   zlist[nodes.Item])r   r`   r(   c                 C  sp   t |dpg }|sd S g }g }| D ]&}|j|rB|| q&|| q&|rl|jj|d || d d < d S )NZdeselect)r   )tupler   nodeid
startswithr7   rn   Zpytest_deselected)r   r`   Zdeselect_prefixes	remainingZ
deselectedZcolitemrQ   rQ   rR   pytest_collection_modifyitems  s    r   c                   @  s.   e Zd ZddddddZddd	d
dZdS )FSHookProxyr   zAbstractSet[object]r&   )pmremove_modsr(   c                 C  s   || _ || _d S r   )r   r   )selfr   r   rQ   rQ   rR   __init__  s    zFSHookProxy.__init__rL   zpluggy.HookCaller)r   r(   c                 C  s    | j j|| jd}|| j|< |S )N)Zremove_plugins)r   Zsubset_hook_callerr   __dict__)r   r   r   rQ   rQ   rR   __getattr__  s    
zFSHookProxy.__getattr__N)rt   
__module____qualname__r   r   rQ   rQ   rQ   rR   r     s   r   c                   @  s   e Zd ZdZdZdS )r   z*Signals that the test run was interrupted.builtinsNrt   r   r   __doc__rQ   rQ   rQ   rR   r     s   r   c                   @  s   e Zd ZdZdS )ru   z"Signals a stop as failed test run.Nr   rQ   rQ   rQ   rR   ru     s   ru   c                   @  s*   e Zd ZU dZded< dddddZdS )	_bestrelpath_cacher   r   rB   rL   rT   c                 C  s   t | j|}|| |< |S r   )r   rB   )r   rB   rrQ   rQ   rR   __missing__  s    z_bestrelpath_cache.__missing__N)rt   r   r   	__slots____annotations__r   rQ   rQ   rQ   rR   r     s   
r   c                      s<   e Zd ZdZedddd fddZdd	d
dZ  ZS )r   a  Collector of files in a file system directory.

    .. versionadded:: 8.0

    .. note::

        Python directories with an `__init__.py` file are instead collected by
        :class:`~pytest.Package` by default. Both are :class:`~pytest.Directory`
        collectors.
    r   r   r$   )r   rB   r(   c                  s   t  j||dS )zThe public constructor.

        :param parent: The parent collector of this Dir.
        :param path: The directory's path.
        :type path: pathlib.Path
        )r   rB   )superr   )clsr   rB   	__class__rQ   rR   r     s    zDir.from_parentz&Iterable[nodes.Item | nodes.Collector]r(   c                 c  s   | j }| j}t| jD ]}| rjt|j}| jj|ddsL|j||drLq|j	|| d}|d k	r|V  q|
 rt|j}| j|s|j||drq|j|| d}|E d H  qd S )NTwith_parents)r   r`   r   	file_pathr   )r`   ihookr   rB   r   r   rc   
isinitpathr   r   r   pytest_collect_file)r   r`   r   ZdirentryrB   colcolsrQ   rQ   rR   r@     s$    

zDir.collect)rt   r   r   r   classmethodr   r@   __classcell__rQ   rQ   r   rR   r     s   r   c                      s  e Zd ZU dZeZeZded< ded< ded< dd	d
 fddZedd d
ddZ	ddddZ
eddddZejdd	dddZeddddZejdd	dddZeddddZddddd Zed!d"d	dd#d$Zed!d"d%d	d&d'd(ZeZd)d*d+d,d,d-d.d/Zd0d1d2d3d4Zdd5d6d7d8d9ZedRd;d<d=d>d?d@ZedSd;d,dAd>dBd@ZdTd;d,dAd>dDd@ZdUdEd,dFdGdHdIZdJddKdLZdMdNdOdPdQZ  ZS )Vrh   zoThe root of the collection tree.

    ``Session`` collects the initial paths given as arguments to pytest.
    r"   Z_setupstater%   Z_fixturemanagerr_   rd   r   r&   r   c              	     s   t  jd|jd d || dd d| _d| _d| _d| _|jj	d| _t
 | _t
 | _g | _g | _i | _g | _t|j| _| jjj| dd d S )Nr   )r   rB   fspathr   r`   rc   r   r   FrA   rc   )r   )r   r   Zrootpathr   r   _shouldstop_shouldfailtracerootget	frozenset_initialpaths_initialpaths_with_parents	_notfound_initial_parts_collection_cacher   r   _bestrelpathcacher`   pluginmanagerregister)r   r`   r   rQ   rR   r   -  s,    	zSession.__init__c                 C  s   | j |d}|S )Nr   )_create)r   r`   rc   rQ   rQ   rR   ri   G  s    zSession.from_configrL   r   c                 C  s$   d| j j| jt| dd| j| jf S )Nz6<%s %s exitstatus=%r testsfailed=%d testscollected=%d>rd   z<UNSET>)r   rt   r   getattrr   r   r   rQ   rQ   rR   __repr__L  s    
zSession.__repr__z
bool | strc                 C  s   | j S r   )r   r   rQ   rQ   rR   r   U  s    zSession.shouldstop)r{   r(   c                 C  s.   |dkr$| j r$tjtddd d S || _ d S )NFzCsession.shouldstop cannot be unset after it has been set; ignoring.rb   
stacklevel)r   warningswarnr#   r   r{   rQ   rQ   rR   r   Y  s    c                 C  s   | j S r   )r   r   rQ   rQ   rR   r   g  s    zSession.shouldfailc                 C  s.   |dkr$| j r$tjtddd d S || _ d S )NFzCsession.shouldfail cannot be unset after it has been set; ignoring.rb   r   )r   r   r   r#   r   rQ   rQ   rR   r   k  s    r   c                 C  s
   | j jjS )zQThe path from which pytest was invoked.

        .. versionadded:: 7.0.0
        )r`   invocation_paramsrC   r   rQ   rQ   rR   rm   y  s    zSession.startpath)	node_pathr(   c                 C  s
   | j | S r   )r   )r   r   rQ   rQ   rR   _node_location_to_relpath  s    z!Session._node_location_to_relpathT)Ztryfirstc                 C  s(   | j r| | j | jr$| | jd S r   )r   ru   r   r   r   rQ   rQ   rR   pytest_collectstart  s    zSession.pytest_collectstartzTestReport | CollectReport)reportr(   c                 C  sH   |j rDt|dsD|  jd7  _| jd}|rD| j|krDd| j | _d S )NZwasxfailr2   r1   zstopping after %d failures)failedhasattrr   r`   getvaluer   )r   r   r1   rQ   rQ   rR   pytest_runtest_logreport  s
    z Session.pytest_runtest_logreportFr   zstr | os.PathLike[str]rJ   )rB   r   r(   c                C  s2   t |tr|nt|}|r$|| jkS || jkS dS )a>  Is path an initial path?

        An initial path is a path explicitly given to pytest on the command
        line.

        :param with_parents:
            If set, also return True if the path is a parent of an initial path.

        .. versionchanged:: 8.0
            Added the ``with_parents`` parameter.
        N)rz   r   r   r   )r   rB   r   Zpath_rQ   rQ   rR   r     s    
zSession.isinitpathzos.PathLike[str]zpluggy.HookRelay)r   r(   c                 C  sT   t |tr|nt|}| jj}||}|j|}|rHtt||}n| jj	}|S r   )
rz   r   r`   r   Z_getconftestmodulesZ_conftest_plugins
differencer   r   rn   )r   r   rB   r   Zmy_conftestmodulesr   proxyrQ   rQ   rR   gethookproxy  s    
zSession.gethookproxyz%dict[Path, Sequence[nodes.Collector]]zSequence[nodes.Collector])rB   
path_cacher(   c                 C  sx   ||kr|| S |  rF| |j}|j|| d}|dk	r@|fnd}n&| rh| |}|j|| d}nd}|||< |S )zCreate a Collector for the given path.

        `path_cache` makes it so the same Collectors are returned for the same
        path.
        r   NrQ   r   )r   r   r   r   r   r   )r   rB   r   r   r   r   rQ   rQ   rR   _collect_path  s    
 
zSession._collect_path.zSequence[str] | NonezLiteral[True]zSequence[nodes.Item])r*   genitemsr(   c                 C  s   d S r   rQ   r   r*   r  rQ   rQ   rR   r     s    zSession.perform_collectz&Sequence[nodes.Item | nodes.Collector]c                 C  s   d S r   rQ   r  rQ   rQ   rR   r     s    Nc              	   C  s  |dkr| j j}| d| | | jj jd7  _| j j}g | _g | _i | _g | _	| j	}zHg }g }|D ]P}t| j jj|| j jjd}| j| ||j ||j ||jj qft|| _t|| _t| }	| jj|	d | jj jd8  _| jrJg }
| jD ]:\}}|r.|
d| d|d	 n|
d
|  qt|
 |sX|	j}n(|	jr|	jD ]}| j	| | qf| j j  |j | | j |d W 5 g | _g | _i | _|j
| d X |rt!|| _"|S )a  Perform the collection phase for this session.

        This is called by the default :hook:`pytest_collection` hook
        implementation; see the documentation of this hook for more details.
        For testing purposes, it may also be called directly on a fresh
        ``Session``.

        This function normally recursively expands any collectors collected
        from the session to their items, and only items are returned. For
        testing purposes, this may be suppressed by passing ``genitems=False``,
        in which case the return value contains these collectors unexpanded,
        and ``session.items`` is empty.
        Nr   r2   rf   	as_pypathr   znot found: z
(no match in any of )zfound no collectors for )rc   r`   r   )#r`   r*   r   r   indentrn   r   r   r   r   Zpytest_collection_finishresolve_collection_argumentr   rC   r   Zpyargsr7   rB   r   rW   r   r   r   r!   r   pytest_collectreportr   resultpassedr  r   Zcheck_pendingr   r   r   )r   r*   r  rn   r   ZinitialpathsZinitialpaths_with_parentsargcollection_argumentreperrorsZ
collectorsnoderQ   rQ   rR   r     sn    


  

r   ztuple[CollectReport, bool])r  handle_dupesr(   c                 C  s>   || j kr |r | j | }|dfS t|}|| j |< |dfS d S )NTF)r   r!   )r   r  r  r  rQ   rQ   rR   _collect_one_node:  s    

zSession._collect_one_nodez&Iterator[nodes.Item | nodes.Collector]c                 c  s  i }| j j}| jD ]}| d| | jj jd7  _|j}|j}|j}|	 rf|rft
d||f|g}|d kr|jD ]}||s q|d| qznL|d}	t|jdD ]4\}
}|
t|	ks|j|	|
  kr q|d| qd}g }| ||fg}|r| \}}|s"|V  d}qt|tjs2qt|trdt|d tsRt
||d |}nht|dkot|d to|d   }| ||\}}|s|js|jj|d	 |jsq|j}d}t|D ]}t|d trF|j|d k}t j!d
krn|snt"j#|j|d }|oBt"j$|jt"j$|d k}n(|j%|d kpl|j%dd |d k}|r|&||dd  f d}q|s|&| q|sd't(|f|}| j)&||f | jj jd8  _qd S )Nzprocessing argumentr2   zinvalid arg r   .rb   FTr  win32[::)*r`   r   r   r   r   r  rB   partsmodule_namer   AssertionErrorrW   Z_is_in_confcutdirinsertsplitr   r   stempoprz   r   	Collectorrh   r   r   r   r  r  r   r	  r
  reversedrq   platformrk   samefileislinkr   r7   joinrL   r   )r   r   r   r  Zargpathnamesr  pathsrB   Zmodule_name_partsr   Zany_matched_in_initial_partZnotfound_collectorsZworkZ	matchnodeZ
matchpartsZsubnodesr  r  	duplicateZany_matched_in_collectorr  Zis_matchZ	same_fileZ
report_argrQ   rQ   rR   r@   G  s    





zSession.collectznodes.Item | nodes.CollectorzIterator[nodes.Item])r  r(   c                 c  s   |  d| t|tjr.|jj|d |V  n~t|tjs>t| j	d}|oXt|tj
 }| ||\}}|rx|sxd S |jr|jD ]}| |E d H  q|s|jj|d d S )Nr  )r   rE   r  )r   rz   r   ZItemr   Zpytest_itemcollectedr  r  r`   r   ZFiler  r  r
  r  r	  )r   r  rE   r  r  r&  ZsubnoderQ   rQ   rR   r    s    
zSession.genitems)..)..)NT)T)rt   r   r   r   r   ru   r   r   r   ri   r   propertyr   setterr   rm   r   r   r   r   r	  r   r   r   r   r   r  r@   r  r   rQ   rQ   r   rR   rh     sZ   
	         U y
str | None)r  r(   c              
   C  sl   zt j| }W n tttfk
r,   Y dS X |dksJ|jdksJ|jdkrNdS |jrbtj	
|jS |jS dS )zaSearch sys.path for the given a dotted module name, and return its file
    system path if found.N	namespace)rH   util	find_specAttributeErrorImportError
ValueErrororiginsubmodule_search_locationsrk   rB   dirname)r  specrQ   rQ   rR   search_pypath  s    r4  T)frozenc                   @  s*   e Zd ZU dZded< ded< ded< dS )	CollectionArgumentzA resolved collection argument.r   rB   zSequence[str]r  r)  r  N)rt   r   r   r   r   rQ   rQ   rQ   rR   r6    s   
r6  Fr  )invocation_pathr  r  r(   c                C  s   t |d\}}}|d^}}|r>|d  | | |d< d}|r^t|}	|	dk	r^|}|	}| | }
t|
}
t|
s|r~dnd}t|j|d|r|
 r|rdnd	}t|j|dt	|
||d
S )a  Parse path arguments optionally containing selection parts and return (fspath, names).

    Command-line arguments can point to files and/or directories, and optionally contain
    parts for specific tests selection, for example:

        "pkg/tests/test_foo.py::TestClass::test_foo"

    This function ensures the path exists, and returns a resolved `CollectionArgument`:

        CollectionArgument(
            path=Path("/full/path/to/pkg/tests/test_foo.py"),
            parts=["TestClass", "test_foo"],
            module_name=None,
        )

    When as_pypath is True, expects that the command-line argument actually contains
    module paths instead of file-system paths:

        "pkg.tests.test_foo::TestClass::test_foo"

    In which case we search sys.path for a matching module, and then return the *path* to the
    found module, which may look like this:

        CollectionArgument(
            path=Path("/home/u/myvenv/lib/site-packages/pkg/tests/test_foo.py"),
            parts=["TestClass", "test_foo"],
            module_name="pkg.tests.test_foo",
        )

    If the path doesn't exist, raise UsageError.
    If the path is a directory and selection parts are present, raise UsageError.
    r  r  Nz9module or package not found: {arg} (missing __init__.py?)z"file or directory not found: {arg})r  z9package argument cannot contain :: selection parts: {arg}z;directory argument cannot contain :: selection parts: {arg})rB   r  r  )
rL   	partitionr  r4  r   r   r   formatr   r6  )r7  r  r  rU   ZsquacketrestZstrpathr  r  Zpyarg_strpathr   r^   rQ   rQ   rR   r    s:    #r  )Vr   
__future__r   rY   Zdataclassesr   rM   rH   importlib.utilrk   pathlibr   rq   typingr   r   r   r   r   r	   r
   r   r   r   r   Zpluggyrx   r   Z_pytest._codeZ_pytest.configr   r   r   r   r   r   Z_pytest.config.argparsingr   Z_pytest.config.compatr   Z_pytest.outcomesr   Z_pytest.pathlibr   r   r   r   r   Z_pytest.reportsr   r    Z_pytest.runnerr!   r"   Z_pytest.warning_typesr#   Ztyping_extensionsr$   Z_pytest.fixturesr%   rS   rO   r   r   r   r   r   r   r   r   r   r   rw   r   ro   ru   Z	dataclassrL   r   Z	Directoryr   r  rh   r4  r6  r  rQ   rQ   rQ   rR   <module>   s    =;&3   8
	