'L iådZddlmZddlZddlmZddlmZddlmZddlmZddlm Z ddl Z ddl Z ddl Z ddlZddlZddlZdd lmZddlZdd lmZdd lmZdd lmZdd lmZddlZddlZddlmZddlZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddl%m&Z&ddl%m'Z'ddl(m)Z)ddl*m+Z+ddl,m-Z-ddl,m.Z.ddl,m/Z/ddl,m0Z0ddl,m1Z1ddl,m2Z2ddl3m4Z4dd l3m5Z5dd!l6m7Z7dd"l6m8Z8dd#l9m:Z:er dd$l;mZ>dHd&Z?dId'Z@ dJd(ZAdKd)ZBdLd+ZCdMd,ZDdNd-ZEdOd.ZFdPd/ZG dQd0ZHdRd1ZIGd2d3ZJGd4d5eKZLGd6d7eMZNe jGd8d9ePeeQfZReGd:d;ejZTeGd<d*ejZVd=d> dSd?ZWe jd@AGdBdCZXd=d=dD dTdEZY dUdFZZ dVdGZ[y)WzHCore implementation of the testing process: init, session, runtest loop.) annotationsN)Callable)Iterable)Iterator)Sequence)Set)Path)final)Literal)overload) TYPE_CHECKING)nodes)Config) directory_arg)ExitCode)hookimpl)PytestPluginManager) UsageError)OverrideIniAction)Parser)PathAwareHookProxy)exit absolutepath) bestrelpath fnmatch_ex) safe_exists)samefile_nofollow)scandir) CollectReport) TestReport)collect_one_node) SetupState) PytestWarning)Self)FixtureManagerc |jd}|jdddddd|jd d d tdd d |jdtddd|jdtddd|jdtddd|j dddd|j dddd|j dddd|jd }|jd!d"d#d$%|j d&d'd()|jd*d+}|jd,d-d.d/d0%|jd1d/d2%|jd3d#d4d56|jd7d#d4d86|jd9d#d:d;6|jdt jtddqry)sNgeneralz-xz --exitfirst store_constmaxfailz,Exit instantly on first error or failed test)actiondestconsthelpz --maxfailnumstorerz'Exit after first num failures or errors)metavarr-typer.defaultr0z--strict-config strict_configtruez Enables the strict_config option)r- ini_option ini_valuer0z--strict-markersstrict_markersz!Enables the strict_markers optionz--strictstrictzEnables the strict optionzbAny warnings encountered while parsing the `pytest` section of the configuration file raise errorsbool)r4r5zVMarkers not registered in the `markers` section of the configuration file raise errorszrEnables all strictness options, currently: strict_config, strict_markers, strict_xfail, strict_parametrization_idsFzpytest-warningsz-Wz--pythonwarningsappendz.is_ancestor s 5= $$rm)rqr rrr returnr<)argparseArgumentTypeErrorr cwdabsoluteresolve)rCmsgrss rkrhrhs cC ((--%488:tDz2245((--488:%%'d););)=>((-- Krmc  tj|}tj|_d} |j d}|j j|d}|||xsd|_d}tIjJ|jL|dk\r( |j jO||j |jQ|jS#t$rtj|_t$rtj|_Yttjf$rtj j"j%}tj&}t)|j*tjrt|j*j,|j*j,}|dkrCt.j0j3|j4d|j*j6d|j j9|||_Yt:$r tj<|_tj j"j%} |j?||j@t)|j*tBrt.j0j3d nu#tj$r_}|j,|j,|_t.j0j3tE|jFd|dYd}~nd}~wwxYwYwxYw#tj$r`}|j,|j,|_t.j0j3tE|jFd|dYd}~d}~wwxYw#d}tIjJ|jL|dk\r |j jO||j nu#tj$r_}|j,|j,|_t.j0j3tE|jFd|dYd}~nd}~wwxYw|jQwxYw) zSkeleton command line program.rr,sessionNz:  )excinfoz(mainloop: caught unexpected SystemExit! )r} exitstatus))Session from_configrOKr _do_configurehookpytest_sessionstartr USAGE_ERRORFailed TESTS_FAILEDKeyboardInterruptr Exception_pytest_code ExceptionInfo from_current INTERRUPTED isinstancevalue returncodesysstderrwritetypenamerzpytest_keyboard_interrupt BaseExceptionINTERNAL_ERRORnotify_exceptionoption SystemExitr4__name__oschdir startpathpytest_sessionfinish_ensure_unconfigure)configdoitr} initstaterrexcs rk wrap_sessionr1s!!&)G!GI0% R  "I KK + +G + <I!%fg!6!;!G > ""# > C 00#0B0B1 ""$   U !)!5!5G   7!)!6!6G !4>>2 ,mm11>>@G)1)=)=J'--8==++7!(!9!9Jq=JJ$$(8(8'9GMM>@G R''? gmmZ8JJ$$%PQ >> C>>-),G&   DI$6$6#7r#b!ABB C R,>> C>>-),G&   DI$6$6#7r#b!ABB C ""# > C 00#0B0B1>> C>>-),G&   DI$6$6#7r#b!ABB C ""$sAC'M>#8#8#V#V!!""#61D1D1I#r)RRd e  ~~((W]]+:4+,q53w}}3E+E7==Q'4 00dX0N   ..!3!34 4   %%g&8&89 9 : rmc |jdjxs |jddjS#t$rYywxYw)aAttempt 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-metahistoryF)joinpathis_fileOSErrorrCs rk_in_venvrsR MM, ' / / 1 @}}\95==?  sAA AAc<jdk(ry|jdj}|xsg}|jd}|r|j d|D|vry|jdj}|xsg}|jd}|r|j d |Dt fd |Dry|jd }|s t ryjr&|jd }t fd |Dryy)N __pycache__Tcollect_ignorerignorec32K|]}t|ywrr.0xs rk z(pytest_ignore_collect..s@LO@collect_ignore_glob ignore_globc32K|]}t|ywrrrs rkrz(pytest_ignore_collect..sDLODrc3nK|],}tjtt|.ywr)fnmatchrg)rglobcollection_paths rkrz(pytest_ignore_collect..s% U7??3/T ; Us25rJrPc36K|]}t|ywrr)rpatrs rkrz(pytest_ignore_collect..sMCz#/Ms) name_getconftest_pathlistparent getoptionextendanyris_dirgetini)rr ignore_paths excludeopt ignore_globsexcludeglobopt allow_in_venvnorecursepatternss` rkpytest_ignore_collectrs$},//550L %2L!!(+J@Z@@,&//O$:$:0L %2L%%m4ND^DD U UU$$%<=M Xo6"MM/: M;LM M rmc0tj||S)Nr)Dir from_parentrCrs rkpytest_collect_directoryrs ??6? --rmc t|jdxsg}|syg}g}|D]@}|jj|r|j |0|j |B|r"|j j |||ddyy)Ndeselect)r)tuplernodeid startswithr=rpytest_deselected)rrdeselect_prefixes remaining deselectedcolitems rkpytest_collection_modifyitemsrsf..z:@bA IJ& >> $ $%6 7   g &   W % &  %%J%7armc(eZdZ ddZddZy) FSHookProxyc ||_||_yr)pm remove_mods)selfrrs rk__init__zFSHookProxy.__init__s &rmcr|jj||j}||j|<|S)N)remove_plugins)rsubset_hook_callerr__dict__)rrrs rk __getattr__zFSHookProxy.__getattr__s4 GG & &tDrz)rrrrrgetattrrs rk__repr__zSession.__repr__ns_''($))5++,-"112! 5 D, 2 3 3rmc|jSr)r5rJs rkrzSession.shouldstopvrmct|dur-|jr!tjtddy||_y)NFzCsession.shouldstop cannot be unset after it has been set; ignoring.r~ stacklevel)r5warningswarnr%rrs rkrzSession.shouldstopz< E>d.. MMY    rmc|jSr)r6rJs rkrzSession.shouldfailrMrmct|dur-|jr!tjtddy||_y)NFzCsession.shouldfail cannot be unset after it has been set; ignoring.r~rO)r6rQrRr%rSs rkrzSession.shouldfailrTrmcB|jjjS)zQThe path from which pytest was invoked. .. versionadded:: 7.0.0 )rinvocation_paramsrFrJs rkrzSession.startpaths {{,,000rmc |j|Sr)r@)r node_paths rk_node_location_to_relpathz!Session._node_location_to_relpaths%%i00rmT)tryfirstc|jr|j|j|jr|j|jyr)rrrrrJs rkpytest_collectstartzSession.pytest_collectstarts= ??++doo. . ??""4??3 3 rmc|jrft|dsY|xjdz c_|jj d}|r&|j|k\rd|jd|_yyyyy)Nwasxfailr,r+zstopping after z failures)failedhasattrrrgetvaluer)rreportr+s rkpytest_runtest_logreportz Session.pytest_runtest_logreportsl ==!<    ! kk**95G4++w6$3D4D4D3EY"O7w"==rmFr cxt|tr|n t|}|r||jvS||jvS)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. )rr r<r;)rrCr!path_s rkr%zSession.isinitpaths=$#4.DJ D;;; ;D... .rmc"t|tr|n t|}|jj}|j |}|j j |}|rtt||}|S|jj}|Sr) rr rrA_getconftestmodules_conftest_plugins differencerrr)rr3rCrmy_conftestmodulesrproxys rk gethookproxyzSession.gethookproxys#FD1vtF| [[ & & 33D9**556HI &{2{'CDE KK$$E rmc||vr||S|jr6|j|j}|j||}||fnd}n7|j r%|j|}|j ||}nd}|||<|S)zCreate a Collector for the given path. `path_cache` makes it so the same Collectors are returned for the same path. rr r")rrnrrrr&)rrC path_cacher$r(r)s rk _collect_pathzSession._collect_paths : d# # ;;=%%dkk2E*/*H*H$+I+C9<sfRD \\^%%d+E,,tD,IDD 4 rmcyrr rrQgenitemss rkrzSession.perform_collects #rmcyrr rss rkrzSession.perform_collects25rmc ||jj}|jd|||jjxjdz c_|jj }g|_g|_i|_g|_ |j}|jjd} g}g}t|D cgc]Q\}} t|jjj| ||jjj |S} }} |jj#dst%| |_n| |_|jD]]} |j'| j(|j'| j(|j+| j(j,_t/||_t/||_t5|} |j6j9| |jjxjdzc_|j rMg} |j D]4\} }|r| j'd| d|d !| j'd | 6t;| |s | j<}nG| j>r;| j<D],}|jj+|jA|.|jjBjE|jG||j| g|_g|_i|_|jI| |rtK||_&|Scc} }w#g|_g|_i|_|jI| wxYw) aPerform 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. rr,rZ as_pypathrZrIrdz not found: z (no match in any of )zfound no collectors for )r}rrr|)'rrQr7r8indentrr=r>r?rrrresolve_collection_argumentrXrFrpyargsrnormalize_collection_argumentsr=rCrrpr:r;r<r#r$pytest_collectreportrresultpassedrtrA check_pendingrpytest_collection_finishrr)rrQrtrrrZ initialpathsinitialpaths_with_parentsrargcollection_argscollection_argumentreperrors collectorsnodes rkrzSession.perform_collect s, <;;##D $dD1 !#{{ !# 8< ,0KK,>,> )- #: 8')L46 %(o As,KK1155"kk00770K  O ;;(()9:&D_&U#&5#'+':': S###$7$<$<=)001D1I1IJ)001D1I1I1Q1QR S"+? KK % % 3 3 5  . .T[[ /  DN"$D %'D "  ) )$ ) 7 "%e*D  w f DN"$D %'D "  ) )$ ) 7s /MAMHMM)Nc||jvr|r|j|}|dfSt|}||j|<|dfS)NTF)r?r#)rr handle_dupesrs rk_collect_one_nodezSession._collect_one_nodejsR 4)) )l((.C9 "4(C+.D " "4 (: rmc#Ki}|jj}|jD]}|jd||jjxj dz c_|j }|j}|j}|j}|jr|r Jd||f|g}|7|jD]'} |j| sny|jd| )nd|jd} t|jdD]:\} } | t!| kDs| j"| | k7rn|jd| <d} g} |g||fg}|r|j%\}}|s|d} t'|t(j*s:t'|t,r+t'|dt.sJ|j1|d|}nt!|dk(xr(t'|dt.xr|dj3 }|j5||\}}|s(|j6s|j8j;| |j6s|j<}d}t?|D]}t'|dt.rA|j |dk(}t@jBd k(ry|swtE|j |d}n]t!|dk(r=||jF|d|zk(}n7|jFjd d|dk(}n|jF|dk(}|s|jI||ddfd}|s| jI||r| s;d jKtM|g|}|jNjI|| f|jjxj dzc_yw) Nzprocessing argumentr,z invalid arg r.r~FTrywin32[::)(rrAr>r7r8r{rCpartsparametrization module_namerrp_is_in_confcutdirinsertsplitrrstempoprr Collectorrr rqrrrr$rrreversedrplatformrrr=joinrgr=)rrprrargpathnamesrrpathsrCmodule_name_partsrany_matched_in_initial_partnotfound_collectorswork matchnode matchpartssubnodesrr duplicateany_matched_in_collectorris_match report_args rkr@zSession.collectws=? [[ & &#'#6#6r (  JJ,.A B JJOO " "a ' ")..G'--E1AAO-99K~~ EL'51A0D"EEyIE"#OO*D//5LLD)*%0$5$5c$:!(!<*GAt3011TYYBSUVTVBW5WLLD)*+0 '"$ '''(QD(, % :"#O26/")U__= i1%jmT:::(66z!}jQH J1,4&z!}d;4&qM113$L &*%;%;I|%TNC$SZZ"<$:;37078:0'..y9MP/!YYG '=u'=> %%z3F&GH JJOO " "a ' "er (sL(O+/OA*Oc#K|jd|t|tjr!|jj ||yt|tj sJt|tj }|j||\}}|jr*|jD]}|j|Ed{|s|jj|yy7&w)Nrt)rry) r7rrItemr$pytest_itemcollectedrFilerrrrtr)rrrrrsubnodes rkrtzSession.genitemss :t$ dEJJ ' JJ + + + 6JdEOO4 44)$ ;;L!33D,GNCzz"zz6G#}}W5556 //s/;6sC C4 C2 'C4)rrrtr )rrrtr)rtrg)rt bool | str)rrrtr )rtr )rZr rtrg)rtr )rdzTestReport | CollectReportrtr )rCzstr | os.PathLike[str]r!r<rtr<)r3zos.PathLike[str]rtzpluggy.HookRelay)rCr rpz%dict[Path, Sequence[nodes.Collector]]rtzSequence[nodes.Collector])..)rQSequence[str] | Nonertz Literal[True]rtzSequence[nodes.Item])rQrrtr<rtz&Sequence[nodes.Item | nodes.Collector])NT)T)rr*rr<rtztuple[CollectReport, bool])rtz&Iterator[nodes.Item | nodes.Collector])rznodes.Item | nodes.CollectorrtzIterator[nodes.Item])rr r rrrrrr+rrKpropertyrsetterrrr[rr^rerr%rnrqr rrr@rtr,r-s@rkrr@s K F##A43   ! !   ! !111t44 tPP4 # /$/ /  /0": # >JM#(#:G# ##AD5(5:>5 /55 CG_(_;?_ /_H"    $ z(xz0normalize_collection_arguments..s 399c.A.A.GRHrm)keyNc|jSr)rrs rkrz0normalize_collection_arguments..s C$6$6rm)sortedrr=sort)rcollection_args_sorted normalized last_keptrs rkr~r~sj$ H,.JI%  $FsI$V   c "IOO6O7 rm)rirrtr )rCrgrtrg)rrrz2Callable[[Config, Session], int | ExitCode | None]rtr1)rrrtr1)rrr}rrtzint | ExitCode | None)r}rrtr )r}rrtr<)rCr rtr<)rr rrrtz bool | None)rCr rr*rtznodes.Collector | None)rzlist[nodes.Item]rrrtr )rrgrZr<rtr) rr rrgrrcrxr<rZr<rtr)rrrrrtr<)rzSequence[CollectionArgument]rtzlist[CollectionArgument])\r __future__rrucollections.abcrrrrr AbstractSet dataclassesrrerMimportlib.utilrpathlibr rtypingr r r r rQpluggyrr _pytest._code_pytest.configrrrrrr_pytest.config.argparsingrr_pytest.config.compatr_pytest.outcomesr_pytest.pathlibrrrrrr _pytest.reportsr!r"_pytest.runnerr#r$_pytest.warning_typesr%typing_extensionsr&_pytest.fixturesr'rlrhrrrrrrrrrrrrrr dataclassdictrgr Directoryrrrrrr|rr~r rmrkrsZN"$$$$.    !(##.%7,4!('&'-#)&+%/&/[|28 8L88v' &*#L. .'.. $  # -Y- dCi0 %//0 0 f@C!(!(6:!(!(Hd#$(- LL LL  L "& LL^ !3 01rm