
    ^h֍                         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JrJr  SSKJ	r	  Sr
SrSrSrS	rS
rSr " S S\5      r " S S\5      r " S S\5      r " S S5      r " S S5      rS rg)a  Utility module for end_to_end testing.

The primary utilities are:
    * NotebookFrontend
    * FrontendElement

Users should use these utilities to write their tests,
and avoid calling the underlying testing library directly.
If you need to do something that isn't currently available,
try to build it onto the utility classes instead of using
playwright functionality/objects directly.

This module was converted and refactored from the older
selenium test suite.
    N)ElementHandleJSHandle)expectBROWSER_CONTEXT	TREE_PAGEEDITOR_PAGESERVER_INFOBROWSER_OBJz.output_subarea  c                       \ rS rSrS rSrg)EndToEndTimeout$   c                 F    U R                   (       d  S $ U R                   S   $ Nr   )argsselfs    Z/home/james-whalen/.local/lib/python3.13/site-packages/nbclassic/tests/end_to_end/utils.py
get_resultEndToEndTimeout.get_result&   s    99t6$))A,6     N)__name__
__module____qualname____firstlineno__r   __static_attributes__r   r   r   r   r   $   s    7r   r   c                       \ rS rSrSS jrSrg)CellTypeError*   c                     Xl         g Nmessage)r   r$   s     r   __init__CellTypeError.__init__,   s    r   r#   N) )r   r   r   r   r%   r   r   r   r   r   r   *   s    r   r   c                       \ rS rSrSrg)FrontendError0   r   N)r   r   r   r   r   r   r   r   r)   r)   0   s    r   r)   c                       \ rS rSrSrSS jrS\4S jrS rSS jr	S	 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g)FrontendElement4   ap  Performs high level tasks on frontend interface components

FrontendElement serves these goals:
- Offers some abstraction/hiding of the underlying testing
  library (with the goal of making future refactors easier
  through providing a single point of reimplementation via
  this utility class rather than exposing implementation
  details of the web library to individual tests)
- Unifies disparate library syntax for common functionalities

FrontendElement wraps JSHandle, Locator and ElementHandle from
playwright, and provides a unified endpoint for test writers
to grab attributes, inner text, find child elements etc.
Nc                 H   Xl         Xl        SU l        Uc  0 OUU l        Uc  SU l        [	        US5      (       a  UR                  5       S:X  a  SU l        [        U[        5      (       d:  [        U[        5      (       a%  UR                  5       nU(       a  X0l        OSU l        [        U[        5      (       ai  Xl         UR                  U l        UR                  U l        [        R                  " UR                  5      U l        U R                  R                  U5        gg)zWrap a frontend item.

:param item: JSHandle, Locator or ElementHandle
:param user_data: Mainly intended to hold cell data (like cell index),
    pass a dict in and put what you want inside.
TNFcountr   )_raw_element_bool
_user_datahasattrr/   
isinstancer   r   
as_elementr,   copydeepcopyupdate)r   item	user_datar6   s       r   r%   FrontendElement.__init__D   s     	
 ) 1"y <DJ4!!djjla&7DJ$..:dH3M3M*J *"
dO,,I MMDMDJ"mmDOO<DOOO""9- -r   returnc                 ,    [        U R                  5      $ r"   )strr0   r   s    r   __repr__FrontendElement.__repr__b   s    499~r   c                     U R                   $ )z&Returns True if construction succeeded)r2   r   s    r   __bool__FrontendElement.__bool__e   s     zzr   c                 B    U R                   R                  U[        -  S9$ )Ntimeout)r1   clickSECONDS_TO_MILLISECONDS)r   rG   s     r   rH   FrontendElement.clickj   s     }}""75L+L"MMr   c                 6    U R                   R                  5       $ r"   )r1   
inner_textr   s    r   get_inner_textFrontendElement.get_inner_textm       }}''))r   c                 6    U R                   R                  5       $ r"   )r1   
inner_htmlr   s    r   get_inner_htmlFrontendElement.get_inner_htmlp   rO   r   c                 8    U R                   R                  U5      $ r"   )r1   get_attribute)r   	attributes     r   rU   FrontendElement.get_attributes   s    }}**955r   c                 D    SU S3nU R                   R                  U5      $ )NzI(element) => { return window.getComputedStyle(element).getPropertyValue('z') }r1   evaluate)r   	prop_namejss      r   get_computed_property%FrontendElement.get_computed_propertyv   s*    $$-;e5}}%%b))r   c                 8    U R                   R                  U5      $ r"   rY   r   texts     r   rZ   FrontendElement.evaluate{   s    }}%%d++r   c                     [        U R                  S5      (       a  U R                  R                  US9$ [        U R                  S5      (       a  U R                  R                  US9$ [	        S5      e)Nwait_for_element_statestatewait_forz#Could not wait for state on element)r4   r1   rd   rg   r)   )r   rf   s     r   rg   FrontendElement.wait_for~   sa    4==":;;==77e7DDT]]J//==)))66 EFFr   c                 8    U R                   R                  5         g r"   )r1   focusr   s    r   rj   FrontendElement.focus   s    r   c                     U R                   n[        US5      (       a  UR                  U5      nO%[        US5      (       a  UR                  U5      nOSn[	        U5      $ )z-Locate child elements with the given selectorlocatorquery_selectorN)r1   r4   rm   rn   r,   )r   selectorelementresults       r   locateFrontendElement.locate   sV    --7I&&__X.FW.//++H5F Fv&&r   c                 ~   U R                   n[        US5      (       a.  UR                  U5      nU Vs/ s H  n[        U5      PM     nnU$ [        US5      (       aT  UR	                  U5      n[        UR                  5       5       Vs/ s H  n[        UR                  U5      5      PM     nnU$ SnU$ s  snf s  snf )z1Locate all child elements with the given selectorquery_selector_allrm   N)r1   r4   ru   r,   rm   ranger/   nth)r   ro   rp   matchesr:   element_listindexs          r   
locate_allFrontendElement.locate_all   s    --701100:G>EFgdOD1gLF  Wi((ooh/GMRSZS`S`SbMcdMcEOGKK,>?McLd
   L G es   B5	$B:c                 8    U R                   R                  U5      $ )z2Sends the given text as key presses to the element)r1   typer`   s     r   r~   FrontendElement.type   s    }}!!$''r   c                 8    U R                   R                  U5      $ )zSend a key press to the element)r1   press)r   keys     r   r   FrontendElement.press   s    }}""3''r   c                     U R                   $ )zCCurrently this is an unmanaged user data area, use it as you please)r3   r   s    r   get_user_dataFrontendElement.get_user_data   s    r   c                      [        U R                  5      R                  U[        -  S9  g ! [         a  n[        S5      UeS nAf[         a  n[        S5      UeS nAff = f)NrF   z-Cannot expect not_to_be_visible on this type!z Error waiting not_to_be_visible!)r   r1   not_to_be_visiblerI   
ValueError	ExceptionAssertionErrorr   )r   rG   errs      r   expect_not_to_be_visible(FrontendElement.expect_not_to_be_visible   sa    	O4==!33GF]<]3^ 	VKLRUU 	O!"DE3N	Os    ), 
A AA AA c                      [        U R                  5      R                  U5        g ! [         a  n[	        S5      UeS nAff = f)Nz(Cannot expect to have text on this type!)r   r1   to_have_textr   r   )r   ra   r   s      r   expect_to_have_text#FrontendElement.expect_to_have_text   s?    	Q4==!..t4 	QFGSP	Qs   $' 
A=Ac                 6    U R                   R                  5       $ r"   )r1   
is_visibler   s    r   r   FrontendElement.is_visible   rO   r   )r2   r1   r0   r3   r"   )   )r   r   r   r   __doc__r%   r?   r@   rC   rH   rM   rR   rU   r]   rZ   rg   rj   rr   r{   r~   r   r   r   r   r   r   r   r   r   r,   r,   4   sq    .<# 
N**6*
,G' ((OQ*r   r,   c                   P   \ rS rSrSr\r\r\rSKS jrS r	\
S 5       r\
S 5       r\
S 5       r\
S	 5       rS
 rS rS rS rSKS jrS rS rSKS jrS rS rSKS jrS rS rS rS rS rS rS r SLS jr!SMS jr"SMS jr#S r$S  r%S! r&S" r'S# r(S$ r)S% r*S& r+SNS( jr,SOS) jr-SPS* jr.SQS, jr/S- r0S. r1SRS/ jr2S'\4S0 jr3SSS1 jr4STS2 jr5S3 r6SNS4 jr7S5 r8SUS6 jr9SKS7 jr:SVS8 jr;SVS9 jr<S: r=SWS; jr>S+S<.S= jr?S> r@S? rAS@ rBSA rCSB rDSC rESKSD jrFSE rGSF rHSG rISH rJ\KSXSI j5       rLSJrMg)YNotebookFrontend   a  Performs high level Notebook tasks for automated testing.

NotebookFrontend serves these goals:
- Drives high level application tasks for testing
- Offers some encapsulation of the underlying testing
  library, to allow test writers to focus their efforts
  on application features rather than implementation
  details for any given testing task

NotebookFrontend holds a _tree_page (Jupyter file browser), and
an _editor_page (a Python 3 notebook editor page), with the goal
of allowing test writers to drive any desired application tasks,
with the option of selecting a page in most methods.

Many tasks are accomplished by using the evaluate method to run
frontend Jupyter Javascript code on a selected page.

A cells property returns a list of the current notebook cells.

Other design notes: This class works together with FrontendElement
to abstract the testing library implementation away from test
writers. NotebookFrontend holds (private) handles to the underlying
browser/context.

TODO:
Possible future improvements, current limitations, etc
Nc                     Xl         U[           U l        U R                  U5      U l        U R                  5         U R                  5         SU l        g)a  Start the Notebook app via the web UI or from a file.

If an existing_file_name is provided, the web interface
looks for and clicks the notebook entry in the tree page.
If not, the web interface will start a new Python3 notebook
from the kernel selection menu.

:param browser_data: Interfacing object to the web UI
:param str existing_file_name: An existing notebook filename to open
N)_browser_datar   
_tree_page_open_notebook_editor_page_editor_page_wait_for_start#disable_autosave_and_onbeforeunloadcurrent_cell)r   browser_dataexisting_file_names      r   r%   NotebookFrontend.__init__   sN     * 'y1 ;;<NO 	002 r   c                 4   ^  U 4S jnT R                  U5        g)zBWait until the notebook interface is loaded and the kernel startedc                     >  TR                  5       =(       a'    TR                  5       =(       a    TR                  5       n U $ ! [         a     gf = f)NF)is_jupyter_definedis_notebook_definedis_kernel_runningr   )statusr   s    r   check_is_kernel_runningANotebookFrontend._wait_for_start.<locals>.check_is_kernel_running   sV    113 5 4465 224  M  s   >A 
AAN)wait_for_condition)r   r   s   ` r   r    NotebookFrontend._wait_for_start   s    	 	 78r   c                 8    U R                   R                  S5      $ )Nbody)r   rm   r   s    r   r   NotebookFrontend.body  s      ((00r   c                 8    U R                   R                  S5      $ )z,Return a list of the current Notebook cells.z.cell)r   ru   r   s    r   _cellsNotebookFrontend._cells  s       33G<<r   c           	      x    [        U R                  5       VVs/ s H  u  p[        USU0S9PM     nnnU$ s  snnf )z8User facing cell list, gives a list of FrontendElement'srz   r;   )	enumerater   r,   )r   rz   cellcellss       r   r   NotebookFrontend.cells  sG    
  )5
5 DWe,<=5 	 

 
s   6c                 8    U R                  U R                  5      $ r"   )rz   r   r   s    r   current_indexNotebookFrontend.current_index  s    zz$++,,r   c                 ,    U R                  [        5      $ r"   )
screenshotr   r   s    r   
sshot_editNotebookFrontend.sshot_edit#  s    {++r   c                 ,    U R                  [        5      $ r"   )r   r   r   s    r   
sshot_treeNotebookFrontend.sshot_tree&  s    y))r   c                     U[         :X  a  U R                  nUR                  5       $ U[        :X  a  U R                  nUR                  5       $ [	        S5      e)z-Returns bytes of a PNG screenshot of the page-Error, provide a valid page to evaluate from!)r   r   r   r   r   r   r   pagespecified_pages      r   r   NotebookFrontend.screenshot)  sX    9!__N ((** [ !..N ((** KLLr   c                 8    U R                   R                  U5      $ r"   )r   rz   r   r   s     r   rz   NotebookFrontend.index4  s    {{  &&r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eSnUb  SR                  S U 5       5      nUS-  nUR                  R                  XQ-   5        g)zPress a key on the specified page

:param str keycode: The keycode value, see MDN
:param str page: The page name to run on
:param modifiers: A list of modifier keycode strings to press
r   r'   N+c              3   $   #    U  H  ov   M     g 7fr"   r   .0ms     r   	<genexpr>)NotebookFrontend.press.<locals>.<genexpr>G       1y!Ay   )r   r   r   r   r   joinkeyboardr   )r   keycoder   	modifiersr   modss         r   r   NotebookFrontend.press7  sr     9!__N[ !..NKLL 881y11DCKD%%dn5r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR
                  R                  U5        g)z9Mimics a user typing the given text on the specified pager   N)r   r   r   r   r   r   r~   r   ra   r   r   s       r   r~   NotebookFrontend.typeL  sF    9!__N[ !..NKLL$$T*r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR
                  R                  U5        g)r'   r   N)r   r   r   r   r   r   insert_textr   s       r   r   NotebookFrontend.insert_textV  sF    9!__N[ !..NKLL++D1r   c                     SnUb  SR                  S U 5       5      nUS-  nU R                  R                  X1-   5        g)zPress a key on the current_cellr'   Nr   c              3   $   #    U  H  ov   M     g 7fr"   r   r   s     r   r   0NotebookFrontend.press_active.<locals>.<genexpr>e  r   r   )r   r   r   )r   r   r   r   s       r   press_activeNotebookFrontend.press_activea  s@     881y11DCKD/r   c                 :    U R                   R                  U5        g)z7Mimics a user typing the given text on the current_cellN)r   r~   r`   s     r   type_activeNotebookFrontend.type_activej  s    t$r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U5      nUR                  5         g)zIAttempts to find and click an element with the selector on the given pager   N)r   r   r   r   r   rm   rH   )r   ro   r   r   elems        r   try_click_selector#NotebookFrontend.try_click_selectorn  sK    9!__N[ !..NKLL%%h/

r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUb  [        UR                  XS95      $ [        UR                  U5      5      $ )zFWait for the given selector (in the given state) on the specified pager   re   )r   r   r   r   r   r,   wait_for_selector)r   ro   r   rf   r   s        r   r   "NotebookFrontend.wait_for_selectorz  sg    9!__N[ !..NKLL">#C#CH#C#Z[[~??IJJr   c                 >    [         R                  " 5       S   S:X  a  gg)zLJupyter Notebook uses different modifier keys on win (Control) vs mac (Meta)r   DarwinMetaControl)osunamer   s    r   get_platform_modifier_key*NotebookFrontend.get_platform_modifier_key  s    88:a=H$r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U5      $ )zRun some Javascript on the frontend in the given page

:param text: JS to evaluate
:param page: Page (str constant) to evaluate JS in
:return: The result of the evaluated JS
r   r   r   r   r   r   rZ   r   s       r   rZ   NotebookFrontend.evaluate  sE     9!__N[ !..NKLL&&t,,r   c                 8    U R                   R                  5         g r"   )r   pauser   s    r   _pauseNotebookFrontend._pause  s    !r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  5         g)3Find an element matching selector on the given page+Error, provide a valid page to locate from!N)r   r   r   r   r   reloadr   s      r   r  NotebookFrontend.reload  s>    9!__N[ !..NIJJr   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      e[        UR                  U5      5      $ )r  r  )r   r   r   r   r   r,   rm   )r   ro   r   r   s       r   rr   NotebookFrontend.locate  sH    9!__N[ !..NIJJ~55h?@@r   c                 &   U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U5      n[        UR                  5       5       Vs/ s H  n[        UR                  U5      5      PM     nnU$ s  snf )z?Find a list of elements matching the selector on the given pager  )
r   r   r   r   r   rm   rv   r/   r,   rw   )r   ro   r   r   rq   rz   ry   s          r   r{   NotebookFrontend.locate_all  s    9!__N[ !..NIJJ  ''1HMfllnH]^H]u

5(9:H]^ _s   &$Bc                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U5      nUR                  5         [        U5      $ )zFind selector in page and focusr  )r   r   r   r   r   rm   rj   r,   )r   ro   r   r   rm   s        r   locate_and_focus!NotebookFrontend.locate_and_focus  sV    9!__N[ !..NIJJ ((2w''r   c                    ^^^ U[         :X  a  U R                  mO"U[        :X  a  U R                  mO[	        S5      eTb  UU4S jnTb  UU4S jnU R                  W5        g)z5Waits for availability of a frame with the given namez3Error, provide a valid page to wait for frame from!Nc                  l   > TR                    V s/ s H  o R                  T:X  d  M  U PM     nn U$ s  sn f r"   )framesname)fr  r  r   s     r   
frame_wait3NotebookFrontend.wait_for_frame.<locals>.frame_wait  s2    %3%:%:M%:ffn!%:M Ns   11c                  `   > TR                    V s/ s H  o PM     nn [        U5      T:  $ s  sn f r"   )r  len)r  r  r/   r   s     r   r  r    s3    %3%:%:;%:!%:;6{e++ <s   +)r   r   r   r   r   r   )r   r/   r  r   r  r   s    ``  @r   wait_for_frameNotebookFrontend.wait_for_frame  s[    9!__N[ !..NQRR , 	
+r   c                    Uc  Uc  [        S5      eUb  Ub  [        S5      eU[        :X  a  U R                  nO"U[        :X  a  U R                  nO[        S5      eUbD  UR
                   Vs/ s H  ofR                  U:X  d  M  UPM     nnU(       d  [        S5      eUS   nUb  UR
                  U   nWR                  U5      n	[        U	5      $ s  snf )zFinds an element inside a framez0Error, must provide a frame name or frame index!z9Error, provide only one either frame name or frame index!z4Error, provide a valid page to locate in frame from!zNo frames found!r   )	r   r   r   r   r   r  r  r   r,   )
r   ro   r   
frame_nameframe_indexr   r  frame_matchesframerp   s
             r   locate_in_frame NotebookFrontend.locate_in_frame  s    +"5NOO!k&=WXX9!__N[ !..NRSS!(6(=(=V(=1:AUQ(=MV  233!!$E""))+6E))(3w'' Ws   -CCc                 <   Uc  Uc  [        S5      eUb  Ub  [        S5      eSnUbJ  U[        :X  a  U R                  nO"U[        :X  a  U R                  nO[        S5      eUR                  U5      nUb  U R                  U   R                  U5      n[        U5      $ )z1Waits for availability of a given tag on the pageNz$Provide a page or cell to wait from!z.Provide only one of [page, cell] to wait from!r   )
r)   r   r   r   r   r   rm   r   r   r,   )r   tagr   
cell_indexrq   r   s         r   wait_for_tagNotebookFrontend.wait_for_tag  s    $, FGG!d&6 PQQy !%$!%!2!2 OPP#++C0F![[,>>sCFv&&r   c                     SnU[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U5      $ )z;Find an frontend element by selector (Tag, CSS, XPath etc.)Nr   )r   r   r   r   r   rm   )r   ro   r   rq   r   s        r   _locateNotebookFrontend._locate  sH    9!__N[ !..NKLL%%h//r   c                 *    U R                  S[        S9$ )zClear all cell outputsz$Jupyter.notebook.clear_all_output();r   rZ   r   r   s    r   clear_all_output!NotebookFrontend.clear_all_output"  s    }}2  
 	
r   c                 8    SU S3nU R                  U[        S9  g)zClear single cell outputzJupyter.notebook.clear_output()r*  Nr+  r   rz   JSs      r   clear_cell_output"NotebookFrontend.clear_cell_output)  s     -eWA6b{+r   c                 p    [        [        U R                  5      5       H  nU R                  S5        M     g r   )rv   r  r   delete_cell)r   _s     r   delete_all_cells!NotebookFrontend.delete_all_cells.  s*     s4;;'(AQ )r   c                     U R                  5         [        [        U5      S-
  5       H  nU R                  5         M     [	        U5       H  u  p4U R                  SX45        M     g)zGDelete all cells, then add cells using the list of specified cell_texts   N)r7  rv   r  add_cellr   	edit_cell)r   
cell_textsr6  rz   txts        r   populateNotebookFrontend.populate4  sN    s:*+AMMO ,#J/JENN4, 0r   c                 Z    U R                   R                  S5      nUR                  5         g)z3Mimics a user pressing the execute button in the UIzGbutton[data-jupyter-action='jupyter-notebook:run-cell-and-select-next']N)r   rm   rH   )r   execute_buttons     r   click_toolbar_execute_btn*NotebookFrontend.click_toolbar_execute_btn=  s+    **22
 	r   c                 T    U R                  S[        S9  U R                  S[        S9  g)zlDisable request to save before closing window and autosave.

This is most easily done by using js directly.
zwindow.onbeforeunload = null;r*  z)Jupyter.notebook.set_autosave_interval(0)Nr+  r   s    r   r   4NotebookFrontend.disable_autosave_and_onbeforeunloadG  s&    
 	5KHATr   c                 b    U R                   R                  S5        U R                  S[        S9  g)z6Changes us into command mode on currently focused cellEscapezt () => { return Jupyter.notebook.handle_command_mode(Jupyter.notebook.get_cell(Jupyter.notebook.get_edit_index())) }r*  N)r   r   rZ   r   r   s    r   to_command_mode NotebookFrontend.to_command_modeO  s-    		! SYd 	 	fr   r   c                 n    U R                   U   nUR                  5         U R                  5         X l        g)z'Mimic a user focusing on the given cellN)r   rH   rI  r   )r   rz   r   s      r   
focus_cellNotebookFrontend.focus_cellV  s+    {{5!

 r   c                     U R                  U5        U R                  5         [        X!-
  5       H  nU R                  S[        S/5        M     g )NjShift)rL  rI  rv   r   r   )r   initial_indexfinal_indexis       r   select_cell_range"NotebookFrontend.select_cell_range]  s>    &{23AJJsK'3 4r   c                 P  ^^^^ U R                  U5        U R                  5         U R                  S[        5        U R                  R                  S5        U R                  R                  S5      R                  5         U R                  S[        S9mTR                  ST S35        U R                  UU4S jS	S
S9  U R                  S[        S9mTR                  ST S35        U R                  UU4S jS	S
S9  U R                  R                  S5      R                  5         g)zUses Jupyter's find and replacer  z#find-and-replacez#findreplace_allcells_btnz#findreplace_find_inpr*  z(elem) => { elem.value = 'z'; return elem.value; }c                  ,   > T R                  S5      T:H  $ Nz (elem) => { return elem.value; }rZ   )
find_inputfind_txts   r   <lambda>3NotebookFrontend.find_and_replace.<locals>.<lambda>n  s    J''247?@r   r      rG   periodz#findreplace_replace_inpc                  ,   > T R                  S5      T:H  $ rX  rY  )	rep_inputreplace_txts   r   r\  r]  v  s    I&&'IJkYr   z#findreplace_replaceall_btnN)
rL  rI  r   r   r   rm   rH   rr   rZ   r   )r   rz   r[  rc  rZ  rb  s     ``@@r   find_and_replace!NotebookFrontend.find_and_replacec  s   

3$!!"56!!"=>DDF[[!8{[K
9(C[\]@	 	  	
 KK :KM	8E]^_Y 	  	

 	!!"?@FFHr   codec                    U R                  U5        U R                  U   nUS:X  a  U R                  R                  S5        ORUS:X  a  U R                  R                  S5        O0US:X  a  U R                  R                  S5        O[	        U S35      eU R                  U5        U R                  U5        U R                  $ )Nmarkdownr   rawrrf  yz: is not a valid cell type,use 'code', 'markdown', or 'raw')rL  r   r   r   r   _wait_for_stale_cell)r   rz   	cell_typer   s       r   convert_cell_type"NotebookFrontend.convert_cell_type|  s    {{5!
"##C(%##C(& ##C(9+-g hii!!$'   r   c                 &    UR                  S5        g)zThis is needed to switch a cell's mode and refocus it, or to render it.

Warning: there is currently no way to do this when changing between
markdown and raw cells.
hiddenN)rd   r   s     r   rl  %NotebookFrontend._wait_for_stale_cell  s     	##H-r   c                 .    SnU R                  U[        S9$ )z'Get a list of the text inside each cellzU() => { return Jupyter.notebook.get_cells().map(function(c) {return c.get_text();}) }r*  r+  )r   r1  s     r   get_cells_contents#NotebookFrontend.get_cells_contents  s    d}}Rk}22r   c                 Z    U R                   U   R                  U5      R                  5       $ )z Get the text inside a given cell)r   rn   rL   )r   rz   ro   s      r   get_cell_contents"NotebookFrontend.get_cell_contents  s%    {{5!00:EEGGr   c                 ~    U R                   U   R                  5       R                  U5      nUc  g[        USU0S9nU$ )z$Get the cell output for a given cellNrz   r   )r   r6   rn   r,   )r   rz   outputr   rp   s        r   get_cell_output NotebookFrontend.get_cell_output  sB    {{5!,,.==fE<!$7E2BCr   c                    [         R                   R                  5       n[         R                   R                  5       U-
  R                  U:  aX   U" 5       nU(       a  U$ [        R                  " U5        [         R                   R                  5       U-
  R                  U:  a  MX  [        5       e! [
         a*  n[        R                  " 5         [        S5         SnANjSnAff = f)zZWait for check_func to return a truthy value, return it or raise an exception upon timeoutzM
[NotebookFrontend] Ignoring exception in wait_for_condition, read more aboveN)
datetimenowsecondstimesleepr   	traceback	print_excprintr   )r   
check_funcrG   r`  begin	conditionr   s          r   r   #NotebookFrontend.wait_for_condition  s     !!%%'  $$&.77'Ah&L	$$

6"   $$&.77'A "##  h##%fgghs   B0 B0 0
C$: CC$c                     U R                   (       d  [        S5      eSnU R                   U   R                  5       n UR                  [        X#-  S9  U R                  US9$ ! [         a     Nf = f)zAWaits for the cell to finish executing and return the cell outputzError, no cells exist!r   rF   )rz   )r   r   r6   r   CELL_OUTPUT_SELECTORr{  )r   rz   rG   milliseconds_to_secondsr   s        r   wait_for_cell_output%NotebookFrontend.wait_for_cell_output  sx    {{455"&{{5!,,.	""#7Ab"c
 ##%#00	  		s   A" "
A/.A/c                 @    SU SU SU 3nU R                  U[        S9$ )NJupyter.notebook.get_cell(z).metadata.z = r*  r+  )r   rz   r   valuer1  s        r   set_cell_metadata"NotebookFrontend.set_cell_metadata  s-    )%C5E7K}}Rk}22r   c                 6    SU S3nU R                  U[        S9$ )Nz)() => { return Jupyter.notebook.get_cell(z).cell_type }r*  r+  r0  s      r   get_cell_typeNotebookFrontend.get_cell_type  s#    9%O}}Rk}22r   c                 >    SU SU S3nU R                  U[        S9  g )Nr  z).set_input_prompt(r/  r*  r+  )r   rz   	prmpt_valr1  s       r   set_cell_input_prompt&NotebookFrontend.set_cell_input_prompt  s'    )%0CI;aPb{+r   c                 L   Ub  U R                  U5      nU R                  U5        U R                  S[        5        U R                  S[        U R	                  5       /5        U R                  S[        5        U R                  U[        S9  U(       a  U R                  U5        gg)zLSet the contents of a cell to *content*, by cell object or by index
        NEnteraDeleter*  )rz   rL  r   r   r   r~   execute_cell)r   r   rz   contentrenders        r   r<  NotebookFrontend.edit_cell  s     JJt$E 	

7K(

3d&D&D&F%GH

8[)		'	,e$ r   c                     [        U[        5      (       a  UnO2[        U[        5      (       a  U R                  U5      nO[	        S5      eU R                  U5        U R                  R                  S5        g )Nz4execute_cell only accepts an ElementHandle or an intzControl+Enter)r5   intr   rz   	TypeErrorrL  r   r   )r   cell_or_indexrz   s      r   r  NotebookFrontend.execute_cell  s[    mS))!E}55JJ}-ERSS0r   c                     U R                  U5        U R                  R                  S5        US:  a  US-   OUnU(       a  U R                  XS9  US:w  a  U R	                  XBS9  g g )Nbr   r:  )rz   r  rf  )rz   rm  )rL  r   r   r<  rn  )r   rz   rm  r  	new_indexs        r   r;  NotebookFrontend.add_cell  sb    $!&!EAI	NNN8"""H r   c                 F    U R                  XUS9  U R                  U5        g )N)rz   rm  r  )r;  r  )r   rz   rm  r  s       r   add_and_execute_cell%NotebookFrontend.add_and_execute_cell  s     EH% r   c                 |    U R                  U5        U R                  5         U R                  R                  S5        g )Ndd)rL  rI  r   r~   )r   rz   s     r   r5  NotebookFrontend.delete_cell  s.    t$r   c                 D    U R                  USS9  U R                  XUS9  g )Nrh  rm  )rz   r  r  )r;  r<  )r   rz   r  r  s       r   add_markdown_cell"NotebookFrontend.add_markdown_cell  s"    ez2UFCr   r  c                ~    U H7  n[        U[        5      (       a  U R                  UUS9  M*  [        SU< 35      e   g )N)rm  r  z Don't know how to add cell from )r5   r?   r;  r  )r   rm  valuesr  s       r   appendNotebookFrontend.append  sD    E%%%	&+  -  "B5) LMM r   c                 *    U R                  S[        S9$ )z9Checks that the Jupyter object is defined on the frontendzN() => {  try {    return Jupyter != false;  } catch (e) {    return false;  }}r*  r+  r   s    r   r   #NotebookFrontend.is_jupyter_defined  "    }}   	
 		
r   c                 *    U R                  S[        S9$ )zBChecks that the Jupyter.notebook object is defined on the frontendzW() => {  try {    return Jupyter.notebook != false;  } catch (e) {    return false;  }}r*  r+  r   s    r   r   $NotebookFrontend.is_notebook_defined  r  r   c                 *    U R                  S[        S9$ )NzR() => { return Jupyter.notebook.kernel && Jupyter.notebook.kernel.is_connected() }r*  r+  r   s    r   r   "NotebookFrontend.is_kernel_running*  s    }}`  
 	
r   c                 :    U R                   R                  S5        g )Nz.kernel_idle_icon)r   r   r   s    r   wait_for_kernel_ready&NotebookFrontend.wait_for_kernel_ready0  s    ++,?@r   c                    ^  T R                   nSU 3nUR                  U5        UR                  U5      nUR                  5         T R                   R	                  5         U 4S jnT R                  USSS9nUS   nU$ )Nztext=c                     > TR                   [           R                   V s/ s H  n SU R                  ;  d  M  U PM     sn $ s  sn f Ntreer   r   pagesurlpgr   s    r   wait_for_new_pageRNotebookFrontend.get_editor_page_from_existing_notebook.<locals>.wait_for_new_page>  <    !%!3!3O!D!J!Jc!J2f\^\b\bNbB!Jccc
   AA}   r:  r_  r   )r   r   rm   rH   r  r   )r   r   	tree_pagenotebook_name_selectorexisting_notebookr  	new_pageseditor_pages   `       r   &get_editor_page_from_existing_notebook7NotebookFrontend.get_editor_page_from_existing_notebook3  s    OO	 $));(<!=##$:;%--.DE! 	d ++ , 
	
  lr   c                    ^  T R                   nUR                  S5      nUR                  5         SnSU S3nUR                  U5      nUR                  5         U 4S jnT R                  U5      nUS   nU$ )Nz#new-dropdown-buttonkernel-python3#z ac                     > TR                   [           R                   V s/ s H  n SU R                  ;  d  M  U PM     sn $ s  sn f r  r  r  s    r   r  ?NotebookFrontend.get_new_editor_page.<locals>.wait_for_new_pageU  r  r  r   )r   rm   rH   r   )	r   r  new_dropdown_elementkernel_namekernel_selectornew_notebook_elementr  r  r  s	   `        r   get_new_editor_page$NotebookFrontend.get_new_editor_pageJ  s    OO	  )001GH""$&k]"-(00A""$	d ++,=>	lr   c                    ^ ^ T R                   nTb  T R                  UU 4S jSSS9nU$ T R                  U 4S jSSS9nU$ )Nc                  &   > TR                  T 5      $ r"   )r  )r   r   s   r   r\  =NotebookFrontend._open_notebook_editor_page.<locals>.<lambda>b  s    CCDVWr   i  r:  r_  c                  $   > T R                  5       $ r"   )r  r   s   r   r\  r  h  s    002r   )r   r   )r   r   r  r  s   ``  r   r   +NotebookFrontend._open_notebook_editor_page]  s`    OO	)11W 2 K  112 2 K r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  S5      $ )Nr   z%() => { return window.location.href }r   r   s      r   get_page_urlNotebookFrontend.get_page_urlo  sF    9!__N[ !..NKLL &&'NOOr   c                     U[         :X  a  U R                  nUR                  5       $ U[        :X  a  U R                  nUR                  5       $ [	        S5      e)Nr   )r   r   r   r   r   go_backr   s      r   r  NotebookFrontend.go_backz  sX    9!__N %%'' [ !..N %%'' KLLr   c                 .    U R                   [           S   $ )Nr  )r   r	   r   s    r   get_server_info NotebookFrontend.get_server_info  s    !!+.u55r   c                     U[         :X  a  U R                  nO"U[        :X  a  U R                  nO[	        S5      eUR                  U R                  [           S   U-   5        g )Nr   r  )r   r   r   r   r   gotor   r	   )r   r   partial_urlr   s       r   navigate_toNotebookFrontend.navigate_to  sU    9!__N[ !..NKLLD..{;EB[PQr   c                     U " X5      nU$ r"   r   )clsr   r  r   instances        r   new_notebook_frontend&NotebookFrontend.new_notebook_frontend  s    |8r   )r   r   r   r   r"   )NNN)NN)r   )r   r   )r   r'   r'   )r   rf  )r   zdiv .CodeMirror-code)r   g?)r   r   )Nr   r'   F)rf  r'   )r  r'   T)r  N)Nr   r   r   r   r   r   r   r  r%   r   propertyr   r   r   r   r   r   r   rz   r   r~   r   r   r   r   r   r   rZ   r  r  rr   r{   r  r  r  r$  r'  r,  r2  r7  r?  rC  r   rI  rL  rT  rd  rn  rl  rt  rw  r{  r   r  r  r  r  r<  r  r;  r  r5  r  r  r   r   r   r  r  r  r   r  r  r  r  classmethodr  r   r   r   r   r   r      s   : IK/!.9 1 1 = =   - -,*	+'6*+	20%
K- "	 	A(,((2'.
0
,
 -Uf!4I2!".3
H %&.B 	$$133,% 	1I!%
D )/ N


A.&$	P(6R  r   r   c                   ^  U 4S jnU 4S jnSnT R                  U[        5      nSnT R                  U[        5      nSnT R                  U[        5      nX/:X  d   eUS:w  a  US:w  a  [        SU-  5      eX:X  d   eUS:X  a  U" S	5      (       d   eU" S	5      (       d   eg	US:X  a  U" U5      (       d   eU" U5      (       d   eg	g	)
a8  Validate the entire dual mode state of the notebook.
Checks if the specified cell is selected, and the mode and keyboard mode are the same.
Depending on the mode given:
    Command: Checks that no cells are in focus or in edit mode.
    Edit:    Checks that only the specified cell is in focus and in edit mode.
c                    > SnTR                  U[        5      nU c  U H  nUS:X  d  M    g   g[        U5       H  u  pCX@:X  a
  US:w  a    gM  US:X  d  M    g   g)NzO() => { return Jupyter.notebook.get_cells().map(function(c) {return c.mode;}) }editFT)rZ   r   r   )rz   r1  
cells_modemoderS  notebooks        r   is_only_cell_edit2validate_dualmode_state.<locals>.is_only_cell_edit  sn    ^&&r;7
="6>  #  ,GAz6>  " 6>  - r   c                    > SnTR                  U[        5      nU c  US:H  $ US:w  a  gSnTR                  U[        5      nSU  S3nTR                  U[        5      nX4:H  $ )NzD() => { return $('#notebook .CodeMirror-focused textarea').length; }r   r:  Fz@() => { return $('#notebook .CodeMirror-focused textarea')[0]; }z)() => { return IPython.notebook.get_cell(z).code_mirror.getInputField() }r+  )rz   r1  focused_cellsfocused_cellr   r  s        r   is_focused_on.validate_dualmode_state.<locals>.is_focused_on  sv    S ))"k:= A%%AO(([99%@`a  [1##r   z/() => { return IPython.keyboard_manager.mode; }z'() => { return IPython.notebook.mode; }z?() => { return Jupyter.notebook.get_selected_cells_indices(); }commandr  z%An unknown mode was send: mode = "%s"N)rZ   r   r   )	r  r  rz   r  r
  r1  keyboard_modenotebook_moder#  s	   `        r   validate_dualmode_stater    s    &$  
;B%%b+6M	2B%%b+6M 
KB""2{3J   yTV^?DEE    yT"""" &&&&	U#### '''' 
r   )r   r7   r~  r   r  r  playwright.sync_apir   r   r   r   r   r   r	   r
   r  rI   r   r   r   r   r)   r,   r   r  r   r   r   <module>r     s      	   7 & $	(  7i 7J 	I 	N* N*bQ QhB(r   