
    Cj;Y                    J   S r SSKJr  SSKrSSKJrJr  SSKrSSK	J
r
  SSKJrJr  SSKJr  SSKJrJrJrJrJrJr  SS	KJrJr  SS
KJr       S             SS jjr " S S\5      r " S S\5      r\R@                  RC                  SS9 " S S\\   5      5       r"g)z

This module contains the `Pilot` class used by [App.run_test][textual.app.App.run_test] to programmatically operate an app.

See the guide on how to [test Textual apps](/guide/testing).

    )annotationsN)AnyGeneric)wait_for_idle)App
ReturnType)HeadlessDriver)Click	MouseDown
MouseEvent	MouseMoveMouseUpResize)OffsetSize)Widgetc                X    U R                   R                  U-   u  pgU UUSSUUUUUUS.nU$ )zNGet the arguments to pass into mouse messages for the click and hover methods.r   )widgetxydelta_xdelta_ybuttonshiftmetactrlscreen_xscreen_y)regionoffset)	targetr    r   r   r   controlclick_xclick_ymessage_argumentss	            _/home/rurouni/.local/share/pipx/venvs/strix-agent/lib/python3.13/site-packages/textual/pilot.py_get_mouse_message_argumentsr'      sL     }}++f4G     c                      \ rS rSrSrSrg)OutOfBounds2   zFRaised when the pilot mouse target is outside of the (visible) screen. N__name__
__module____qualname____firstlineno____doc____static_attributes__r,   r(   r&   r*   r*   2   s    Pr(   r*   c                      \ rS rSrSrSrg)WaitForScreenTimeout6   zException raised if messages aren't being processed quickly enough.

If this occurs, the most likely explanation is some kind of deadlock in the app code.
r,   Nr-   r,   r(   r&   r5   r5   6   s    r(   r5   T)angularc                     \ rS rSrSrSS jrSS jr\SS j5       rSS jr	SS jr
      S             SS	 jjr     S           SS
 jjr       S               S S jjr      S             SS jjr      S             SS jjr  S!     S"S jjr       S#                 S$S jjrS%S&S jjrS'S(S jjrS)S jrS)S jrS*S jrSrg)+Pilot=   zPilot object to drive an app.c                    Xl         g N_app)selfapps     r&   __init__Pilot.__init__A   s    	r(   c              #  ,   #    SU R                   4v   g 7f)Nr@   r=   r?   s    r&   __rich_repr__Pilot.__rich_repr__D   s     TYYs   c                    U R                   $ )z$App: A reference to the application.r=   rD   s    r&   r@   	Pilot.appG   s     yyr(   c                   #    U(       a<  U R                   R                  U5      I Sh  vN   U R                  5       I Sh  vN   gg N N7f)z7Simulate key-presses.

Args:
    *keys: Keys to press.
N)r>   _press_keys_wait_for_screen)r?   keyss     r&   pressPilot.pressL   s?      ))''---''))) -)s!   &AAA A	A	Ac                $  #    [        X5      n[        U R                  R                  [        5      (       a  X0R                  R                  l        U R                  R                  [        X35      5        U R                  5       I Sh  vN   g N7f)zResize the terminal to the given dimensions.

Args:
    width: The new width of the terminal.
    height: The new height of the terminal.
N)	r   
isinstancer@   _driverr	   _sizepost_messager   pause)r?   widthheightsizes       r&   resize_terminalPilot.resize_terminalV   s^      E"dhh&&77%)HH"fT01jjls   BBB	BNc           
        #     U R                  [        [        /UUUUUUS9I Sh  vN $  N! [         a  nUSeSnAff = f7f)a  Simulate a [`MouseDown`][textual.events.MouseDown] event at a specified position.

The final position for the event is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Args:
    widget: A widget or selector used as an origin
        for the event offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to target a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the event may not land on the widget you specified.
    offset: The offset for the event. The offset is relative to the selector / widget
        provided or to the screen, if no selector is provided.
    shift: Simulate the event with the shift key held down.
    meta: Simulate the event with the meta key held down.
    control: Simulate the event with the control key held down.
    button: The mouse button to press.

Raises:
    OutOfBounds: If the position for the event is outside of the (visible) screen.

Returns:
    True if no selector was specified or if the event landed on the selected
        widget, False otherwise.
r   r    r   r   r   r"   N)_post_mouse_eventsr   r   r*   )r?   r   r    r   r   r"   r   errors           r&   
mouse_downPilot.mouse_downd   s`     D	"00I& 1      	"T!	"+   A"- +- A- 
?:?Ac           
        #     U R                  [        [        /UUSUUUS9I Sh  vN $  N! [         a  nUSeSnAff = f7f)a  Simulate a [`MouseUp`][textual.events.MouseUp] event at a specified position.

The final position for the event is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Args:
    widget: A widget or selector used as an origin
        for the event offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to target a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the event may not land on the widget you specified.
    offset: The offset for the event. The offset is relative to the widget / selector
        provided or to the screen, if no selector is provided.
    shift: Simulate the event with the shift key held down.
    meta: Simulate the event with the meta key held down.
    control: Simulate the event with the control key held down.

Raises:
    OutOfBounds: If the position for the event is outside of the (visible) screen.

Returns:
    True if no selector was specified or if the event landed on the selected
        widget, False otherwise.
   r[   N)r\   r   r   r*   )r?   r   r    r   r   r"   r]   s          r&   mouse_upPilot.mouse_up   s`     @	"00G$ 1      	"T!	"r`   c                   #     U R                  [        [        [        /UUUUUUUS9I Sh  vN $  N! [         a  nUSeSnAff = f7f)a7  Simulate clicking with the mouse at a specified position.

The final position to be clicked is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Implementation note: This method bypasses the normal event processing in `App.on_event`.

Example:
    The code below runs an app and clicks its only button right in the middle:
    ```py
    async with SingleButtonApp().run_test() as pilot:
        await pilot.click(Button, offset=(8, 1))
    ```

Args:
    widget: A widget or selector used as an origin
        for the click offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to click on a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the click may not land on the widget you specified.
    offset: The offset to click. The offset is relative to the widget / selector provided
        or to the screen, if no selector is provided.
    shift: Click with the shift key held down.
    meta: Click with the meta key held down.
    control: Click with the control key held down.
    times: The number of times to click. 2 will double-click, 3 will triple-click, etc.
    button: The mouse button to click.

Raises:
    OutOfBounds: If the position to be clicked is outside of the (visible) screen.

Returns:
    `True` if no selector was specified or if the selected widget was under the mouse
        when the click was initiated. `False` is the selected widget was not under the pointer.
)r   r    r   r   r   r"   timesN)r\   r   r   r
   r*   )	r?   r   r    r   r   r"   rf   r   r]   s	            r&   clickPilot.click   se     Z	"00GU+ 1 	 	 	 	  	"T!	"s0   A(3 13 A3 
AA  AAc           
     D   #    U R                  XX4USUS9I Sh  vN $  N7f)a  Simulate double clicking with the mouse at a specified position.

Alias for `pilot.click(..., times=2)`.

The final position to be clicked is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Implementation note: This method bypasses the normal event processing in `App.on_event`.

Example:
    The code below runs an app and double-clicks its only button right in the middle:
    ```py
    async with SingleButtonApp().run_test() as pilot:
        await pilot.double_click(Button, offset=(8, 1))
    ```

Args:
    widget: A widget or selector used as an origin
        for the click offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to click on a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the click may not land on the widget you specified.
    offset: The offset to click. The offset is relative to the widget / selector provided
        or to the screen, if no selector is provided.
    shift: Click with the shift key held down.
    meta: Click with the meta key held down.
    control: Click with the control key held down.
    button: The mouse button to click.

Raises:
    OutOfBounds: If the position to be clicked is outside of the (visible) screen.

Returns:
    `True` if no selector was specified or if the selected widget was under the mouse
        when the click was initiated. `False` is the selected widget was not under the pointer.
   rf   r   Nrg   r?   r   r    r   r   r"   r   s          r&   double_clickPilot.double_click   3     Z ZZE&   
 
 	
 
     c           
     D   #    U R                  XX4USUS9I Sh  vN $  N7f)a  Simulate triple clicking with the mouse at a specified position.

Alias for `pilot.click(..., times=3)`.

The final position to be clicked is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Implementation note: This method bypasses the normal event processing in `App.on_event`.

Example:
    The code below runs an app and triple-clicks its only button right in the middle:
    ```py
    async with SingleButtonApp().run_test() as pilot:
        await pilot.triple_click(Button, offset=(8, 1))
    ```

Args:
    widget: A widget or selector used as an origin
        for the click offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to click on a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the click may not land on the widget you specified.
    offset: The offset to click. The offset is relative to the widget / selector provided
        or to the screen, if no selector is provided.
    shift: Click with the shift key held down.
    meta: Click with the meta key held down.
    control: Click with the control key held down.
    button: The mouse button to click.

Raises:
    OutOfBounds: If the position to be clicked is outside of the (visible) screen.

Returns:
    `True` if no selector was specified or if the selected widget was under the mouse
        when the click was initiated. `False` is the selected widget was not under the pointer.
   rk   Nrl   rm   s          r&   triple_clickPilot.triple_click,  rp   rq   c                   #    U R                  5       I Sh  vN    U R                  [        /XSS9I Sh  vN $  N# N! [         a  nUSeSnAff = f7f)a  Simulate hovering with the mouse cursor at a specified position.

The final position to be hovered is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

Args:
    widget: A widget or selector used as an origin
        for the hover offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to hover a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the hover may not land on the widget you specified.
    offset: The offset to hover. The offset is relative to the widget / selector provided
        or to the screen, if no selector is provided.

Raises:
    OutOfBounds: If the position to be hovered is outside of the (visible) screen.

Returns:
    True if no selector was specified or if the hover landed on the selected
        widget, False otherwise.
Nr   )r   )rT   r\   r   r*   )r?   r   r    r]   s       r&   hoverPilot.hover]  sX     8 jjl	"00)fUV0WWW 	W 	"T!	"s:   A:A> <> A> 
AAAAc	           	     `  #    U R                   n	U	R                  n
Uc  U
nO)[        U[        5      (       a  UnOU
R	                  U5      n[        UUUUUUS9n[        US   US   5      nX:R                  ;  a  [        S5      eSn[        SUS-   5       Hk  nU Hb  nU R                  5       I Sh  vN   UnU[        L a  0 UESU0EnUc  U	R                  " U6 u  nnU" S0 UD6nX9l        U
R                  U5        Md     Mm     U R                  5       I Sh  vN   USL =(       d    XL $  Ny N7f)	aS  Simulate a series of mouse events to be fired at a given position.

The final position for the events is computed based on the selector provided and
the offset specified and it must be within the visible area of the screen.

This function abstracts away the commonalities of the other mouse event-related
functions that the pilot exposes.

Args:
    widget: A widget or selector used as the origin
        for the event's offset. If this is not specified, the offset is interpreted
        relative to the screen. You can use this parameter to try to target a
        specific widget. However, if the widget is currently hidden or obscured by
        another widget, the events may not land on the widget you specified.
    offset: The offset for the events. The offset is relative to the widget / selector
        provided or to the screen, if no selector is provided.
    shift: Simulate the events with the shift key held down.
    meta: Simulate the events with the meta key held down.
    control: Simulate the events with the control key held down.
    times: The number of times to click. 2 will double-click, 3 will triple-click, etc.
Raises:
    OutOfBounds: If the position for the events is outside of the (visible) screen.

Returns:
    True if no selector was specified or if the *final* event landed on the
        selected widget, False otherwise.
N)r   r   r   r"   r   r   z<Target offset is outside of currently-visible screen region.rb   chainr,   )r@   screenrP   r   	query_oner'   r   r   r*   rangerT   r
   get_widget_atmouse_position_forward_event)r?   eventsr   r    r   r   r   r"   rf   r@   r{   target_widgetr%   	widget_atrz   mouse_event_clskwargs_events                      r&   r\   Pilot._post_mouse_events  sV    L hh>"M''"M",,V4M8
 )#.0A#0FG&N  	1eai(E#)jjl"" +"e+777F$#&#4#4f#=LIq'1&1
 &,"%%e,) $* ). jjl~;!;;- #* 	s%   B.D.0D*1A&D.D,D.,D.c                  ^^#     U R                   R                  nU R                   /UR                  SS9QnSm[        R
                  " 5       mS
UU4S jjnU H   nUR                  U5      (       d  M  TS-  mM"     T(       a  [        R                  " TR                  5       5      [        R                  " U R                   R                  R                  5       5      /n[        R                  " UU[        R                  S9I Sh  vN u  pxU H  n	U	R                  5         M     [        U5      [        U5      :H  n
U
(       a  [        S	5      eTS:  a  gg! [         a     gf = f N`7f)a}  Wait for the current screen and its children to have processed all pending events.

Args:
    timeout: A timeout in seconds to wait.

Returns:
    `True` if all events were processed. `False` if an exception occurred,
    meaning that not all events could be processed.

Raises:
    WaitForScreenTimeout: If the screen and its children didn't finish processing within the timeout.
FT)	with_selfr   c                 >   > T S-  m T S:X  a  TR                  5         gg)z@Decrement internal counter, and set an event if it reaches zero.rb   r   N)set)countcount_zero_events   r&   decrement_counter1Pilot._wait_for_screen.<locals>.decrement_counter  s&     QJEz $$& r(   rb   )timeoutreturn_whenNz@Timed out while waiting for widgets to process pending messages.returnNone)r@   r{   	Exceptionwalk_childrenasyncioEvent
call_latercreate_taskwait_exception_eventFIRST_COMPLETEDcancellenr5   )r?   r   r{   childrenr   childwait_forr   pendingtask	timed_outr   r   s              @@r&   rK   Pilot._wait_for_screen  sM    	XX__F HHDv33d3CD"==?	' 	' E 122
   ##$4$9$9$;<##DHH$=$=$B$B$DEH  '||#33  JA     HW5I*V  qy[  		2s<   E+E AE+5BE+E)	AE+
E&#E+%E&&E+c                   #    U R                  5       I Sh  vN   Uc  [        S5      I Sh  vN   O[        R                  " U5      I Sh  vN   U R                  R
                  R                  5         g N^ NJ N-7f)zRInsert a pause.

Args:
    delay: Seconds to pause, or None to wait for cpu idle.
Nr   )rK   r   r   sleepr@   r{   _on_timer_update)r?   delays     r&   rT   Pilot.pause  s]      ##%%%="""--&&&((* 	&"&s1   A;A5A;A7A;A9*A;7A;9A;c                   #    U R                   R                  R                  5       I Sh  vN   U R                  R                  R                  5         g N)7f)z+Wait for any current animation to complete.N)r>   animatorr   r@   r{   r   rD   s    r&   wait_for_animationPilot.wait_for_animation%  s:     ii  ..000((* 	1s   (AA*Ac                @  #    U R                  5       I Sh  vN   U R                  R                  R                  5       I Sh  vN   U R                  5       I Sh  vN   [	        5       I Sh  vN   U R
                  R                  R                  5         g N NU N? N/7f)z:Wait for any current and scheduled animations to complete.N)rK   r>   r   wait_until_completer   r@   r{   r   rD   s    r&   wait_for_scheduled_animations#Pilot.wait_for_scheduled_animations*  sr     ##%%%ii  44666##%%%o((*	 	&6%sE   BB+BBBBB,B-*BBBBc                   #    U R                  5       I Sh  vN   [        5       I Sh  vN   U R                  R                  U5        g N2 N"7f)zhExit the app with the given result.

Args:
    result: The app result returned by `run` or `run_async`.
N)rK   r   r@   exit)r?   results     r&   r   
Pilot.exit2  s<      ##%%%of 	&s   AA	AA!AAr=   )r@   App[ReturnType]r   r   )r   zrich.repr.Result)r   r   )rL   strr   r   )rU   intrV   r   r   r   )Nr   r   FFFrb   )r   "Widget | type[Widget] | str | Noner    tuple[int, int]r   boolr   r   r"   r   r   r   r   r   )Nr   FFF)r   r   r    r   r   r   r   r   r"   r   r   r   )Nr   FFFrb   rb   )r   r   r    r   r   r   r   r   r"   r   rf   r   r   r   r   r   )Nr   )r   )Widget | type[Widget] | str | None | Noner    r   r   r   )Nr   r   FFFrb   )r   zlist[type[MouseEvent]]r   r   r    r   r   r   r   r   r   r   r"   r   rf   r   r   r   )g      >@)r   floatr   r   r<   )r   zfloat | Noner   r   r   )r   r   r   r   )r.   r/   r0   r1   r2   rA   rE   propertyr@   rM   rX   r^   rc   rg   rn   rt   rw   r\   rK   rT   r   r   r   r3   r,   r(   r&   r9   r9   =   s   '  *  6:"(-"2-"  -" 	-"
 -" -" -" 
-"b 6:"(+"2+"  +" 	+"
 +" +" 
+"^ 6:"(9"29"  9" 	9"
 9" 9" 9" 9" 
9"z 6:"(/
2/
  /
 	/

 /
 /
 /
 
/
f 6:"(/
2/
  /
 	/

 /
 /
 /
 
/
f =A"( "9 "   " 
	 "J =A"(X<&X< :X<  	X<
 X< X< X< X< X< 
X<t<|++
+r(   r9   )r   r   FFF)r!   r   r    r   r   r   r   r   r   r   r"   r   r   zdict[str, Any])#r2   
__future__r   r   typingr   r   	rich.reprrichtextual._waitr   textual.appr   r   textual.drivers.headless_driverr	   textual.eventsr
   r   r   r   r   r   textual.geometryr   r   textual.widgetr   r'   r   r*   r5   reprautor9   r,   r(   r&   <module>r      s    #    ' ' : S S ) !
 %  	
   4Q) Q9  |GJ | |r(   