
    ^hOP              
          S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKJr  SSKJrJrJr  SSKJr  SSKJr  SSKJrJr  SSKJr  SS	KJr  SS
K
Jr  S rSr0 r \!" \" S5      5      \ S'   \!" \" S5      5      \ S'   \!" \" S5      5      \ S'    " S S\5      r" " S S5      r#S r$S r% " S S\#5      r&S r'S8S jr(S r)S r*\RV                  " SS9r,\,R[                  SSS S!9  \,R[                  S"S#S$S%9  \,R[                  S&S'S(9  \,R[                  S)S*S+SS,\.S-S.9  \,R[                  S/S#S0S%9  \,R[                  S1S2S3S49  S5 r/S6 r0\1S7:X  a  \0" 5         gg)9zNotebook Javascript Test Controller

This module runs one or more subprocesses which will actually run the Javascript
test suite.
    N)BytesIO)ThreadLockEvent)patch)jupyter_runtime_dir)bytes_to_strwhich)get_sys_info)TemporaryDirectory)TimeoutExpiredc                 $    U R                  U5      $ N)wait)ptimeouts     J/home/james-whalen/.local/lib/python3.13/site-packages/nbclassic/jstest.py
popen_waitr      s    66'?    
   casperjs	phantomjsslimerjsc                   R   ^  \ rS rSrSrSrSU 4S jjrS rS rS r	S r
S	 rS
rU =r$ )StreamCapturer)   TFc                    > [         TU ]  5         Xl        / U l        [	        5       U l        [        R                  " 5       u  U l        U l	        [        5       U l        [        5       U l        g r   )super__init__echostreamsr   bufferospipereadfdwritefdr   buffer_lockr   stop)selfr    	__class__s     r   r   StreamCapturer.__init__,   sJ    	i$&GGI!T\6G	r   c                 H   SU l         U R                  R                  5       (       d  [        R                  " U R
                  S5      nU R                     U R                  R                  U5        S S S 5        U R                  (       a(  [        R                  R                  [        U5      5        U R                  R                  5       (       d  M  [        R                  " U R
                  5        [        R                  " U R                  5        g ! , (       d  f       N= f)NTi   )startedr(   is_setr#   readr%   r'   r"   writer    sysstdoutr	   closer&   )r)   chunks     r   runStreamCapturer.run5   s    ))""$$GGDKK.E!!!!%( "yy

  e!45 ))""$$ 	
 "!s   D
D!c                     U R                      U R                  R                  S5        U R                  R                  S5        S S S 5        g ! , (       d  f       g = f)Nr   )r'   r"   truncateseekr)   s    r   reset_bufferStreamCapturer.reset_bufferC   s;    KK  #KKQ s   7A
Ac                     U R                      U R                  R                  5       sS S S 5        $ ! , (       d  f       g = fr   )r'   r"   getvaluer:   s    r   
get_bufferStreamCapturer.get_bufferH   s'    ;;'') s   1
?c                 H    U R                   (       d  U R                  5         g g r   )r-   startr:   s    r   ensure_startedStreamCapturer.ensure_startedL   s    ||JJL r   c                     U R                   (       d  gU R                  R                  5         [        R                  " U R
                  S5        U R                  5         g)zSafely stop the thread.N    )r-   r(   setr#   r0   r&   joinr:   s    r   haltStreamCapturer.haltP   s4    ||		
u%		r   )r"   r'   r    r%   r-   r(   r!   r&   )F)__name__
__module____qualname____firstlineno__daemonr-   r   r5   r;   r?   rC   rI   __static_attributes____classcell__r*   s   @r   r   r   )   s0    FG 
* r   r   c                   b    \ rS rSrSrSrSrSrSrSr	Sr
S rS rSS jrS rS rS	 rS
 r\rSrg)TestControllerZ   zRun tests in a subprocess
    Nc                 .    / U l         0 U l        / U l        g r   )cmdenvdirsr:   s    r   r   TestController.__init__j   s    	r   c                     g)zCreate temporary directories etc.

This is only called when we know the test group will be run. Things
created here may be cleaned up by self.cleanup().
N r:   s    r   setupTestController.setupo   s     	r   c                 x   [         R                  R                  5       nUR                  U R                  5        U(       a  Sn[        U(       + S9=U l        nUR                  5         U(       a  UR                  OS nU(       a  [        R                  OS n[        R                  " U R                  UXcS9U l        g )NT)r    )r2   stderrrX   )r#   environcopyupdaterX   r   stdout_capturerrB   r&   
subprocessSTDOUTPopenrW   process)r)   buffer_outputcapture_outputrX   cr2   r`   s          r   launchTestController.launchw   s     jjoo

488!N#1=7H#IIq		,$&4""$!''(r   c                     U R                   R                  5         U R                  R                  5         U R                  R	                  5       U l        U R                   R                  $ r   )rh   r   rd   rI   r?   r2   
returncoder:   s    r   r   TestController.wait   sJ    !!#**557||&&&r   c                     g)a  Print extra information about this test run.

If we're running in parallel and showing the concise view, this is only
called if the test group fails. Otherwise, it's called before the test
group is started.

The base implementation does nothing, but it can be overridden by
subclasses.
Nr\   r:   s    r   print_extra_infoTestController.print_extra_info   s     	r   c                 X   U R                   nUb  UR                  5       b  g [        SUR                   35        UR	                  5         [        S5       H,  nUR                  5       c  [        R                  " S5        M,    O    UR                  5       c  [        S5        gg!    N"= f)z2Cleanup on exit by killing any leftover processes.NzCleaning up stale PID: r   皙?z+... failed. Manual cleanup may be required.)rh   pollprintpidkillrangetimesleep)r)   subpis      r   cleanup_processTestController.cleanup_process   s    ||<DIIK3	+DHH:67IIK 2Y99;&JJsO	  99;?@ 	 s   (B% %B)c                 j    U R                  5         U R                   H  nUR                  5         M     g)zDKill process if it's still alive, and clean up temporary directoriesN)r   rY   cleanup)r)   tds     r   r   TestController.cleanup   s%    ))BJJL r   )rW   rY   rX   rh   r2   rd   )FF)rK   rL   rM   rN   __doc__sectionrW   rX   rY   rh   r2   r   r]   rl   r   rr   r   r   __del__rP   r\   r   r   rT   rT   Z   sR     G
C
CDGF
('
A0 Gr   rT   c                      SS K Jn   [        R                  R	                  [        R                  R                  U R                  5      S5      $ )Nr    )nbclassic.teststestsr#   pathrH   dirname__file__)ts    r   get_js_test_dirr      s+    77<<

3R88r   c                      SS K n [        5       nU R                  US-   5      nU Vs/ s H"  n[        R                  R	                  X15      PM$     sn$ s  snf )Nr   z[!_]*/)globr   r#   r   relpath)r   test_dirall_subdirsxs       r   all_js_groupsr      sE     H))Hx/0K2=>+QBGGOOA(+>>>s   )Ac                      ^  \ rS rSrSrS/rSS jrS rS rU 4S jr	U 4S jr
S	 r\S
 5       rS rS rS rS rS rSrU =r$ )JSController   zRun CasperJS tests r   c                    [         R                  U 5        X0l        Xl        X l        X@l        SU l        [        R                  " S[        R                  S9U l
        [        5       nS[        R                  R                  US5      -   n[        R                  R                  XPR                  5      nSSXgSU R                   3/U l        g	)
zCreate new test runner.z/a@b/z^FAIL.*)flagsz--includes=zutil.jsr   testz	--engine=N)rT   r   enginer   xuniturlbase_urlrecompile	MULTILINEslimer_failurer   r#   r   rH   rW   )r)   r   r   r   r   js_test_dirincludes
test_casess           r   r   JSController.__init__   s    %
   jj",,G%' 277<<I#FFWW\\+||<
	$++>WXr   c           	         [        5       U l        [        5       U l        [        5       U l        [        5       U l        U R                  R
                  U R                  R
                  U R                  R
                  S.U l        U R                  R                  U R                  5        U R                  R                  U R                  5        U R                  R                  U R                  5        U R                  R                  U R                  5        [        R                  " [        R                  R                  U R                  R
                  [        R                  R                  SS5      5      5        [        R                  " [        R                  R                  U R                  R
                  [        R                  R                  SS5      5      5        U R                  (       a  U R                  5         U R                  (       aw   [         R"                  " U R                  5      R$                  S:H  nU(       a)  U R&                  R                  SU R                   35        g [)        S	U R                   S
35      eSU l        U R-                  5         U R*                  (       a6  U R&                  R                  SU R*                  S U R.                   35        g [0        R2                  SS/U l        g !   Sn N= f)N)HOMEJUPYTER_CONFIG_DIR
IPYTHONDIRu
   sub ∂ir1u   sub ∂ir 1au
   sub ∂ir2u   sub ∂ir 1b   Fz--url=zCould not reach "z".r   z--url=http://localhost:dz-czraise SystemExit(1))r   ipydir
config_dirnbdirhomenamerX   rY   appendr#   makedirsr   rH   r   	add_xunitr   requestsgetstatus_coderW   	Exceptionserver_port_init_serverr   r1   
executable)r)   alives     r   r]   JSController.setup   s   (*,.')
&(	IINN"&//"6"6++**

 			%		#		)		$
BGGLL"'',,|^2\]^
BGGLL"'',,|^2\]^::NN 88 TXX.::cA &
 34"3DHH:R @AA  !D"9$:J:J19Mdmm_ ]^  NND2GHs   -L L
c                     [         R                  R                  U R                  R	                  SS5      S-   5      nU R
                  R                  SU 35        g )N/.z
.xunit.xmlz--xunit=)r#   r   abspathr   replacerW   r   )r)   
xunit_files     r   r   JSController.add_xunit   sA    WW__T\\%9%9#c%B\%QR
(:,/0r   c                 f   > U R                   S:X  a  U(       d  [        TU ]	  SS9$ [        TU ]	  US9$ )Nr   T)rj   ri   )r   r   rl   )r)   ri   r*   s     r   rl   JSController.launch  s7     ;;*$]7>>66 7>>>>r   c                    > [         TU ]  " U0 UD6nU R                  S:X  aA  [        U R                  5      nUS:w  a  U$ [        U R                  R                  U5      5      $ U$ )z#Wait for the JSController to finishr   r   )r   r   r   r	   r2   boolr   search)r)   pargskwargsretr2   r*   s        r   r   JSController.wait  s_    glE,V, ;;*$!$++.Fax
++226:;;Jr   c                 J    [        SU R                  R                  < 35        g )Nz&Running tests with notebook directory )rw   r   r   r:   s    r   rr   JSController.print_extra_info  s    6tzz6IJKr   c                 Z    [        S U R                  U R                  /-    5       5      nU$ )Nc              3   4   #    U  H  n[         U   v   M     g 7fr   )have).0as     r   	<genexpr>(JSController.will_run.<locals>.<genexpr>   s     L*KQa*Ks   )allrequirementsr   )r)   
should_runs     r   will_runJSController.will_run  s)    L$*;*;t{{m*KLL
r   c           	      p   [         R                  SSSSU R                  R                  SSU R                   3/=U l        n[         R                  R                  S5      (       a  UR                  S5        [        5       =U l
        nUR                  5         [        R                  R                  5       nUR                  U R                   5        ["        R$                  " UUR&                  ["        R(                  U R                  R                  US	9U l        [,        R.                  " S
SU R0                  R                  05         [3        5       nSSS5        [        R4                  R7                  WSU R*                  R8                   S35      U l        U R=                  5         g! , (       d  f       N\= f)z/Start the notebook server in a separate processz-m	nbclassicz--no-browserz--notebook-dirz--ServerApp.token=z--ServerApp.base_url=linuxz--KernelManager.transport=ipc)r2   r`   cwdrX   z
os.environr   Nz	jpserver-z.json)r1   r   r   r   r   server_commandplatform
startswithr   r   stream_capturerrB   r#   ra   rb   rc   rX   re   rg   r&   rf   serverr   dictr   r   r   rH   rx   server_info_file_wait_for_server)r)   commandrk   rX   runtime_dirs        r   r   JSController._init_server#  s?   ),+djjoo #DMM?3)
 	
g <<""7++NN:;#1#33q		jjoo

488 &&wYY&&

	
 ZZvtyy~~&>?-/K @ "(.!
 	 @?s   F''
F5c                    [        S5       H  nU R                  R                  5       b  U R                  5       s  $ [        R
                  R                  U R                  5      (       a   U R                  5           g[        R                  " S5        M     [        SU R                   3[        R                  S9  g! [         a     NLf = f)z0Wait 30 seconds for the notebook server to starti,  Nru   z)Notebook server-info file never arrived: file)rz   r   rv   _failed_to_startr#   r   existsr   _load_server_info
ValueErrorr{   r|   rw   r1   r`   )r)   r~   s     r   r   JSController._wait_for_serverB  s    sA{{!-,,..ww~~d3344**, JJsO  	78M8M7NO	
 "  s   +B==
C
	C
c                     U R                   R                  5       R                  SS5      n[        S[        R
                  S9  [        U R                  5        [        U[        R
                  S9  g)z"Notebook server exited prematurelyzutf-8r   zNotebook failed to start: r   N)r   r?   decoderw   r1   r`   r   )r)   captureds     r   r   JSController._failed_to_startV  sN    ''224;;GYO*<d!!"hSZZ(r   c                     [        U R                  5       n[        R                  " U5      nSSS5        WS   U l        g! , (       d  f       N= f)z7Notebook server started, load connection info from JSONNport)openr   jsonloadr   )r)   finfos      r   r   JSController._load_server_info]  s9    $''(A99Q<D )< )(s   A  
Ac                 Z   [        U S5      (       ak   U R                  R                  5          [	        U R                  [
        5         [	        U R                  [
        5        U R                  R                  5         [        R                  U 5        g ! [         a     Nrf = f! [         aG     [        S[        R                  S9  U R                  R                  5          N! [         a      Nf = ff = f! [         a)    [        SU R                   S3[        R                  S9   Nf = f)Nr   z0Failed to terminate notebook server, killing it.r   zNotebook server still running ())hasattrr   	terminateOSErrorr   NOTEBOOK_SHUTDOWN_TIMEOUTr   rw   r1   r`   ry   r   r   rI   rT   r   r:   s    r   r   JSController.cleanupc  s    4""%%'
4;;(AB4;;(AB   %%'t$5   " 	L ZZ KK$$& 	 " 5d6K6K5LANsL   B B# 	C7 
B B #
C4.2C""
C0,C4/C00C470D*)D*)r   rW   r   r   rX   r   r   r   r   r   r   r   r   r   r   r   r   )Tr   N)rK   rL   rM   rN   r   r   r   r]   r   rl   r   rr   propertyr   r   r   r   r   r   rP   rQ   rR   s   @r   r   r      sa    LLY 'IR1?L   >
()(% %r   r   c           
      z   U R                   nU(       d
  [        5       nU R                  (       a  SOSnU Vs/ s H!  n[        X0R                  X R
                  S9PM#     nnUnU Vs/ s H  ofR                  (       d  M  UPM     nnU Vs/ s H  ofR                  (       a  M  UPM     nnXx4$ s  snf s  snf s  snf )zRReturns two lists of TestController instances, those to run, and those
not to run.r   r   )r   r   r   )
testgroupsr   r   r   r   r   r   )	optionsr  r   r   c_jscontrollersrk   to_runnot_runs	            r   prepare_controllersr    s     ##J"_
"++ZF`jk`jX\L]]6{{S`jDkK$3A

aF3%8+QZZq+G8? l 48s   (B.'B3?B3B8#B8c                      U R                  5         U(       d  U R                  5         U R                  US9  U R                  5       nX4U R                  5         $ ! [         a+    SSKnUR                  5         U S4s U R                  5         $ f = f! [         a&    U [        R                  * 4s U R                  5         $ f = f! U R                  5         f = f)a  Setup and run a test controller.

If buffer_output is True, no output is displayed, to avoid it appearing
interleaved. In this case, the caller is responsible for displaying test
output on failure.

Returns
-------
controller : TestController
  The same controller as passed in, as a convenience for using map() type
  APIs.
exitcode : int
  The exit code of the test subprocess. Non-zero indicates failure.
r   r   N   )r]   rr   rl   r   	traceback	print_excr   r   KeyboardInterruptsignalSIGINT)
controllerri   r  exitcodes       r   do_runr    s    	! ++-M: ??$#
 	  	!!q=  		!  *FMM>))* 	s@   6A B "B>B BB C1C CC Cc                    ^	 [        5       n / m	U	4S jnU" SU S   R                  SS5      5        U" SU S   5        U" SU S	   5        [        S
 T	 5       5      nT	 VVs/ s H  u  p4USU 3 SU S3PM     snnm	/ n/ n[        R	                  5        H0  u  pxU(       a  UR                  U5        M  UR                  U5        M2     U(       aG  T	R                  S5        UR                  5         T	R                  SSR                  U5      -   S-   5        U(       aG  T	R                  S5        UR                  5         T	R                  SSR                  U5      -   S-   5        SR                  T	5      $ s  snnf )z@Return a string with a summary report of test-related variables.c                 *   > TR                  X45        g r   )r   )r   valueouts     r   _addreport.<locals>._add  s    

D=!r   zPython versionsys_version
r   zsys.executablesys_executablePlatformr   c              3   <   #    U  H  u  p[        U5      v   M     g 7fr   )len)r   nvs      r   r   report.<locals>.<genexpr>  s     (C5AACs   <z: z-
Tools and libraries available at test time:
z    z1
Tools and libraries NOT available at test time:
)r   r   maxr   itemsr   sortrH   )
infr!  widthr)  r*  avail	not_availkis_availr   s
            @r   reportr7    sJ   
.C
C" 		3}-55d2>?	3/01S_%(C((E03
4fqa%y\A3b!
4CEIzz|LLOQ	 $ 

DE



5388E?*4/0

HI

5388I..t34773<+ 5s   E4c           
         [        U 5      u  pSS jn/ n[        R                  " 5       n[        5         U R                  S:X  a  U H  n[        SUR                  5        [
        R                  R                  5         [        USS9u  pgU(       a3  UR                  U5        U[        R                  * :X  a  [        S5          O[        5         M     O [        R                  R                  U R                  5      nUR                  [        U5       H  u  pgUS:X  a  SOS	n	[        U" S
UR                  -   U	5      5        U(       d  M7  UR!                  5         [        [#        UR                  5      5        UR                  U5        U[        R                  * :X  d  M  [        S5          O    U H"  n[        U" S
UR                  -   S5      5        M$     [        R                  " 5       n
X-
  n['        U5      n['        U5      n[        S5        [        S5        [        [)        5       5        SUS S3n[        SSS9  U(       d  [        SU S3U5        OkU Vs/ s H  oR                  PM     nn[        SU SU SSR+                  U5       S3U5        [        5         [        S5        [        S/UQ76   [        5         U(       a  [
        R,                  " S5        gg! [$         a     gf = fs  snf )at  Run the entire Javascript test suite.

This function constructs TestControllers and runs them in subprocesses.

Parameters
----------

All parameters are passed as attributes of the options object.

testgroups : list of str
  Run only these sections of the test suite. If empty, run all the available
  sections.

fast : int or None
  Run the test suite in parallel, using n simultaneous processes. If None
  is passed, one process is used per CPU core. Default 1 (i.e. sequential)

inc_slow : bool
  Include slow tests. By default, these tests aren't run.

slimerjs : bool
  Use slimerjs if it's installed instead of phantomjs for casperjs tests.

url : unicode
  Address:port to use when running the JS tests.

xunit : bool
  Produce Xunit XML output. This is written to multiple foo.xunit.xml files.

extra_args : list
  Extra arguments to pass to the test subprocesses, e.g. '-v'
c                 V    U S-  n SU-   R                  U[        U 5      -
  U5      nX-   $ )Nr-  )rjustr(  )ltextrtextr2  fills       r   justifyrun_jstestall.<locals>.justify  s2    u##ECJ$6=}r   r  zTest group:Fr   Interruptedr   OKFAILEDzTest group: NzNOT RUNF______________________________________________________________________z?Test suite completed for system with the following information:zTook z.3fzs.zStatus: r   )endzOK (z test groups).zERROR - z out of z test groups failed (z, z).z"You may wish to rerun these, with:z  python -m nbclassic.jstest)F   -)r  r{   rw   fastr   r1   r2   flushr  r   r  r  multiprocessingpool
ThreadPoolimap_unorderedrr   r	   r  r(  r7  rH   exit)r  r  r  r>  failedt_startr  resrJ  
res_stringt_endt_testsnrunnersnfailtookrk   failed_sectionss                    r   run_jstestallrX    sn   B *'2OF FiikG	G||q J-!3!34JJ$ZuEOJj)6==.(-(G !	"''227<<@D%)%8%8%H!%(AXT8
gnz/A/AA:NO3//1,z'8'89:MM*-v}}n,m, &I 
gnz'9'999EF  IIKEoG6{HKE	&M	
KL	&(O73-r"D	*"XJn-t4 /55f99f5xz1FtyyQ`GaFbbdegkl23,?? 9 ! 		* 6s,   A2K" 	AK" K" ,K" K2"
K/.K/z%Run Jupyter Notebook Javascript tests)descriptionr  *z9Run specified groups of tests. If omitted, run all tests.)nargshelpz
--slimerjs
store_truezGUse slimerjs if it's installed instead of phantomjs for casperjs tests.)actionr\  z--urlzURL to use for the JS tests.)r\  z-jz--fast?r  zlRun test sections in parallel. This starts as many processes as you have cores, or you can specify a number.)r[  constdefaulttyper\  z--xunitzProduce Xunit XML resultsz--subproc-streamscapturezkWhat to do with stdout/stderr from subprocesses. 'capture' (default), 'show' and 'discard' are the options.)ra  r\  c                  >    [         R                  / 5      n / U l        U $ )z_Get an argparse Namespace object with the default arguments, to pass to
:func:`run_iptestall`.
)	argparser
parse_args
extra_args)r  s    r   default_optionsrh  P  s!     ""2&GGNr   c                  ,    [         R                  R                  S5      n [         R                  SU  n[         R                  U S-   S  n[        R                  U5      nX#l        [        U5        g ! [         a    [         R                  SS  n/ n NHf = f)Nz--r  )r1   argvindexr   re  rf  rg  rX  )ixto_parserg  r  s       r   mainrn  X  s    %XX^^D!
 88Ab>XXbde_
""8,G#'  88AB<
s   A1 1BB__main__)T)2r   argparser   multiprocessing.poolrI  r#   r   r   r  r1   re   r{   ior   	threadingr   r   r   unittest.mockr   jupyter_core.pathsr   ipython_genutils.py3compatr	   r
   nbclassic._sysinfor   ipython_genutils.tempdirr   r   r   r  r   r   r   rT   r   r   r   r  r  r7  rX  ArgumentParserre  add_argumentintrh  rn  rK   r\   r   r   <module>r|     s      	 	   
    ) )  2 : + 7 %  	j)*Z {+,[ j)*Z .V .b[ [|9?%> %D D!FfP ##0WX	 	  |3!  " 
  |Lb  d 	  w%C  D 	  tXSacP  Q 
  y4  6 	  *IQ  R  zF r   