
    ;OOf                     6   d dl mZmZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dlmZ d dlmZ 	 d dlZd dlmZmZ d dlmZmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZ dZ  G d de!      Z" G d de!      Z# G d de$      Z% G d de$      Z& G d de&      Z' G d de&      Z( G d de&      Z)	 d dl*m+Z+  G d de+      Z, G d de&      Z- G d  d!e&      Z.ej^                  d"k\  rd#d$l0m1Z1 d(d%Z2d& Z3e4d'k(  r e3        yy# e$ r Y w xY w# e$ r e$Z+Y _w xY w))    )divisionprint_functionNwraps)count)WeakKeyDictionary)StoppingContextis_mouse_event)PYTHON3reraise)command_mapREDRAW_SCREEN)PopUpTarget)signals)INPUT_DESCRIPTORS_CHANGEDi   c                       e Zd ZdZy)ExitMainLoopz_
    When this exception is raised within a main loop the main loop
    will exit cleanly.
    N)__name__
__module____qualname____doc__     P/var/www/premiumrankchecker/venv/lib/python3.12/site-packages/urwid/main_loop.pyr   r   2   s     	r   r   c                       e Zd Zy)CantUseExternalLoopN)r   r   r   r   r   r   r   r   9   s    r   r   c                       e Zd ZdZ	 	 	 d dZd Z ed ed      Zd Z ed	 e      Z	d!d
Z
d!dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)"MainLoopa  
    This is the standard main loop implementation for a single interactive
    session.

    :param widget: the topmost widget used for painting the screen, stored as
                   :attr:`widget` and may be modified. Must be a box widget.
    :type widget: widget instance

    :param palette: initial palette for screen
    :type palette: iterable of palette entries

    :param screen: screen to use, default is a new :class:`raw_display.Screen`
                   instance; stored as :attr:`screen`
    :type screen: display module screen instance

    :param handle_mouse: ``True`` to ask :attr:`.screen` to process mouse events
    :type handle_mouse: bool

    :param input_filter: a function to filter input before sending it to
                   :attr:`.widget`, called from :meth:`.input_filter`
    :type input_filter: callable

    :param unhandled_input: a function called when input is not handled by
                            :attr:`.widget`, called from :meth:`.unhandled_input`
    :type unhandled_input: callable

    :param event_loop: if :attr:`.screen` supports external an event loop it may be
                       given here, default is a new :class:`SelectEventLoop` instance;
                       stored as :attr:`.event_loop`
    :type event_loop: event loop instance

    :param pop_ups: `True` to wrap :attr:`.widget` with a :class:`PopUpTarget`
                    instance to allow any widget to open a pop-up anywhere on the screen
    :type pop_ups: boolean


    .. attribute:: screen

        The screen object this main loop uses for screen updates and reading input

    .. attribute:: event_loop

        The event loop object this main loop uses for waiting on alarms and IO
    Nc	                    || _         || _        || _        |sddlm}	 |	j                         }|r|j                  |       || _        d | _        || _	        || _
        t        |d      s|t        d|d      |
t               }|| _        t        | j                  d      r%| j                  j                  | j                  _        i | _        y )Nr   )raw_displayhook_event_loopzscreen object passed z& does not support external event loopssignal_handler_setter)_widgethandle_mousepop_upsurwidr    Screenregister_palettescreenscreen_size_unhandled_input_input_filterhasattrNotImplementedErrorSelectEventLoop
event_loopset_signal_handlerr"   _watch_pipes)
selfwidgetpaletter)   r$   input_filterunhandled_inputr0   r%   r    s
             r   __init__zMainLoop.__init__j   s     () '')F##G, /)v0  ,%>D'G H H(*J$4;; 78 150R0RDKK-r   c                     || _         | j                  r| j                   | j                  _        y | j                   | _        y N)r#   r%   _topmost_widgetoriginal_widget)r3   r4   s     r   _set_widgetzMainLoop._set_widget   s.    <<37<<D  0#'<<D r   c                     | j                   S r:   )r#   r3   s    r   <lambda>zMainLoop.<lambda>   s
    $,, r   zj
       Property for the topmost widget used to draw the screen.
       This must be a box widget.
       )docc                 n    || _         |rt        | j                        | _        y | j                  | _        y r:   )_pop_upsr   r#   r;   )r3   r%   s     r   _set_pop_upszMainLoop._set_pop_ups   s)    #.t||#<D #'<<D r   c                     | j                   S r:   )rC   r?   s    r   r@   zMainLoop.<lambda>   s
    4== r   c                 N      fd} j                   j                  ||      S )a_  
        Schedule an alarm in *sec* seconds that will call *callback* from the
        within the :meth:`run` method.

        :param sec: seconds until alarm
        :type sec: float
        :param callback: function to call with two parameters: this main loop
                         object and *user_data*
        :type callback: callable
        c                               y r:   r   callbackr3   	user_datas   r   cbz!MainLoop.set_alarm_in.<locals>.cb       T9%r   )r0   alarm)r3   secrI   rJ   rK   s   ` `` r   set_alarm_inzMainLoop.set_alarm_in   s    	&$$S"--r   c                 x      fd} j                   j                  |t        j                         z
  |      S )a  
        Schedule an alarm at *tm* time that will call *callback* from the
        within the :meth:`run` function. Returns a handle that may be passed to
        :meth:`remove_alarm`.

        :param tm: time to call callback e.g. ``time.time() + 5``
        :type tm: float
        :param callback: function to call with two parameters: this main loop
                         object and *user_data*
        :type callback: callable
        c                               y r:   r   rH   s   r   rK   z!MainLoop.set_alarm_at.<locals>.cb   rL   r   )r0   rM   time)r3   tmrI   rJ   rK   s   ` `` r   set_alarm_atzMainLoop.set_alarm_at   s*    	&$$R$))+%5r::r   c                 8    | j                   j                  |      S )zf
        Remove an alarm. Return ``True`` if *handle* was found, ``False``
        otherwise.
        )r0   remove_alarmr3   handles     r   rV   zMainLoop.remove_alarm   s    
 ++F33r   c                     t        j                         \  }t        j                  t        j                  t         j                         d fd} j
                  j                  |      f j                  |<   |S )a  
        Create a pipe for use by a subprocess or thread to trigger a callback
        in the process/thread running the main loop.

        :param callback: function taking one parameter to call from within
                         the process/thread running the main loop
        :type callback: callable

        This method returns a file descriptor attached to the write end of a
        pipe. The read end of the pipe is added to the list of files
        :attr:`event_loop` is watching. When data is written to the pipe the
        callback function will be called and passed a single value containing
        data read from the pipe.

        This method may be used any time you want to update widgets from
        another thread or subprocess.

        Data may be written to the returned file descriptor with
        ``os.write(fd, data)``. Ensure that data is less than 512 bytes (or 4K
        on Linux) so that the callback will be triggered just once with the
        complete value of data passed in.

        If the callback returns ``False`` then the watch will be removed from
        :attr:`event_loop` and the read end of the pipe will be closed. You
        are responsible for closing the write end of the pipe with
        ``os.close(fd)``.
        Nc                      t        j                  t              }  |       }|du r1j                  j	                         t        j
                         y y NF)osreadPIPE_BUFFER_READ_SIZEr0   remove_watch_fileclose)datarvalrI   pipe_rdr3   watch_handles     r   rK   zMainLoop.watch_pipe.<locals>.cb   sG    777$9:DD>Du}11,?! r   )r\   pipefcntlF_SETFL
O_NONBLOCKr0   
watch_filer2   )r3   rI   pipe_wrrK   rc   rd   s   ``  @@r   
watch_pipezMainLoop.watch_pipe   si    8 779GU]]BMM:	" 11'2>&2G%<'"r   c                     	 | j                   j                  |      \  }}| j                  j	                  |      syt        j                  |       y# t        $ r Y yw xY w)z
        Close the read end of the pipe and remove the watch created by
        :meth:`watch_pipe`. You are responsible for closing the write end of
        the pipe.

        Returns ``True`` if the watch pipe exists, ``False`` otherwise
        FT)r2   popKeyErrorr0   r_   r\   r`   )r3   write_fdrd   rc   s       r   remove_watch_pipezMainLoop.remove_watch_pipe   s\    	$($5$5$9$9($C!L' 00>
  		s   A 	AAc                 :    | j                   j                  ||      S )z
        Call *callback* when *fd* has some data to read. No parameters are
        passed to callback.

        Returns a handle that may be passed to :meth:`remove_watch_file`.
        )r0   ri   r3   fdrI   s      r   ri   zMainLoop.watch_file  s     ))"h77r   c                 8    | j                   j                  |      S )zn
        Remove a watch file. Returns ``True`` if the watch file
        exists, ``False`` otherwise.
        )r0   r_   rW   s     r   r_   zMainLoop.remove_watch_file  s    
 0088r   c                 D    	 | j                          y# t        $ r Y yw xY w)an  
        Start the main loop handling input events and updating the screen. The
        loop will continue until an :exc:`ExitMainLoop` exception is raised.

        If you would prefer to manage the event loop yourself, don't use this
        method.  Instead, call :meth:`start` before starting the event loop,
        and :meth:`stop` once it's finished.
        N)_runr   r?   s    r   runzMainLoop.run  s"    	IIK 		s    	c                      y)a-  
        >>> w = _refl("widget")   # _refl prints out function calls
        >>> w.render_rval = "fake canvas"  # *_rval is used for return values
        >>> scr = _refl("screen")
        >>> scr.get_input_descriptors_rval = [42]
        >>> scr.get_cols_rows_rval = (20, 10)
        >>> scr.started = True
        >>> scr._urwid_signals = {}
        >>> evl = _refl("event_loop")
        >>> evl.enter_idle_rval = 1
        >>> evl.watch_file_rval = 2
        >>> ml = MainLoop(w, [], scr, event_loop=evl)
        >>> ml.run()    # doctest:+ELLIPSIS
        screen.start()
        screen.set_mouse_tracking()
        screen.unhook_event_loop(...)
        screen.hook_event_loop(...)
        event_loop.enter_idle(<bound method MainLoop.entering_idle...>)
        event_loop.run()
        event_loop.remove_enter_idle(1)
        screen.unhook_event_loop(...)
        screen.stop()
        >>> ml.draw_screen()    # doctest:+ELLIPSIS
        screen.get_cols_rows()
        widget.render((20, 10), focus=True)
        screen.draw_screen((20, 10), 'fake canvas')
        Nr   r?   s    r   	_test_runzMainLoop._test_run#      r   c                    | j                   j                          | j                  r| j                   j                          t	        | j                   d      st        d      	 t        j                  | j                   t        | j                         | j                          | j                  j                  | j                        | _        t        |       S # t        $ r Y Pw xY w)a  
        Sets up the main loop, hooking into the event loop where necessary.
        Starts the :attr:`screen` if it hasn't already been started.

        If you want to control starting and stopping the event loop yourself,
        you should call this method before starting, and call `stop` once the
        loop has finished.  You may also use this method as a context manager,
        which will stop the loop automatically at the end of the block:

            with main_loop.start():
                ...

        Note that some event loop implementations don't handle exceptions
        specially if you manage the event loop yourself.  In particular, the
        Twisted and asyncio loops won't stop automatically when
        :exc:`ExitMainLoop` (or anything else) is raised.
        r!   z1Screen {0!r} doesn't support external event loops)r)   startr$   set_mouse_trackingr-   r   r   connect_signalr   _reset_input_descriptors	NameErrorr0   
enter_idleentering_idleidle_handler	   r?   s    r   r|   zMainLoop.start@  s    $ 	KK**,t{{$56%CE E	""4;;0I--/
 	%%'??55d6H6HIt$$  		s   #/C 	C#"C#c                 .   | j                   j                  | j                         | `t        j                  | j
                  t        | j                         | j
                  j                  | j                          | j
                  j                          y)z
        Cleans up any hooks added to the event loop.  Only call this if you're
        managing the event loop yourself, after the loop stops.
        N)
r0   remove_enter_idler   r   disconnect_signalr)   r   r   unhook_event_loopstopr?   s    r   r   zMainLoop.stopf  sh    
 	))$*:*:;!!$++/H))	+%%doo6r   c                     | j                   j                  | j                         | j                   j                  | j                  | j                         y r:   )r)   r   r0   r!   _updater?   s    r   r   z!MainLoop._reset_input_descriptorss  s4    %%doo6##DOOT\\Br   c                 n   	 | j                          	 | j
                  j                          | j	                          y # t        $ rM 	 | j                         | j                  j	                          cY S # | j                  j	                          w xY ww xY w#  | j                  j	                           xY wr:   )r|   r   _run_screen_event_loopr)   r   r0   rw   r?   s    r   rv   zMainLoop._runw  s    	#JJL	OO! 			 # 	##224  "  "		#	KKs,   > B 	BA4B4BBB4c                 h    | j                  ||      }|r| j                  |       d|v rd| _        yyy)a  
        >>> w = _refl("widget")
        >>> w.selectable_rval = True
        >>> w.mouse_event_rval = True
        >>> scr = _refl("screen")
        >>> scr.get_cols_rows_rval = (15, 5)
        >>> evl = _refl("event_loop")
        >>> ml = MainLoop(w, [], scr, event_loop=evl)
        >>> ml._input_timeout = "old timeout"
        >>> ml._update(['y'], [121])    # doctest:+ELLIPSIS
        screen.get_cols_rows()
        widget.selectable()
        widget.keypress((15, 5), 'y')
        >>> ml._update([("mouse press", 1, 5, 4)], [])
        widget.mouse_event((15, 5), 'mouse press', 1, 5, 4, focus=True)
        >>> ml._update([], [])
        window resizeN)r6   process_inputr*   r3   keysraws      r   r   zMainLoop._update  sA    $   s+t$$&#'  ' r   c                 B   d}	 | j                          |s?| j                  j                  r)t        j                  | j                  j                        }d}|s|r@t        d|d   t        j                         z
        }| j                  j                  |       n| j                  j                  d       | j                  j                  d      \  }}|s"|r |d   t        j                         z
  }|dk  rn|s| j                  |      }|r| j                  |       |rr|d   t        j                         z
  }|dkD  rnR|\  }}} |        | j                  j                  r*t        j                  | j                  j                        }nd}|rrd|v rd| _        )z
        This method is used when the screen does not support using
        external event loops.

        The alarms stored in the SelectEventLoop in :attr:`event_loop`
        are modified by this method.
        NTr   r   )draw_screenr0   _alarmsheapqheappopmaxrR   r)   set_input_timeouts	get_inputr6   r   r*   )r3   
next_alarmr   rN   r   rS   	tie_breakrI   s           r   r   zMainLoop._run_screen_event_loop  sg    
$//"9"9"]]4??+B+BC
DaA!<=CKK2237KK2248 KK11$7	c
$Q-$))+5Cax  $$T3/D""4( mdiik17*4'Ix
??**!&t/F/F!GJ!%J  $&#' K r   c                      y)aq  
        >>> w = _refl("widget")
        >>> scr = _refl("screen")
        >>> scr.get_cols_rows_rval = (10, 5)
        >>> scr.get_input_rval = [], []
        >>> ml = MainLoop(w, screen=scr)
        >>> def stop_now(loop, data):
        ...     raise ExitMainLoop()
        >>> handle = ml.set_alarm_in(0, stop_now)
        >>> try:
        ...     ml._run_screen_event_loop()
        ... except ExitMainLoop:
        ...     pass
        screen.get_cols_rows()
        widget.render((10, 5), focus=True)
        screen.draw_screen((10, 5), None)
        screen.set_input_timeouts(0)
        screen.get_input(True)
        Nr   r?   s    r   _test_run_screen_event_loopz$MainLoop._test_run_screen_event_loop  rz   r   c           	      D   | j                   s| j                  j                         | _         d}|D ]  }|dk(  r	t        |      rK|\  }}}}t	        | j
                  d      rn| j
                  j                  | j                   ||||d      rCd}n@| j
                  j                         r&| j
                  j                  | j                   |      }|rKt        |   t        k(  r| j                  j                          d}|t        | j                  |            z  }d} |S )a  
        This method will pass keyboard input and mouse events to :attr:`widget`.
        This method is called automatically from the :meth:`run` method when
        there is input, but may also be called to simulate input from the user.

        *keys* is a list of input returned from :attr:`screen`'s get_input()
        or get_input_nonblocking() methods.

        Returns ``True`` if any key was handled by a widget or the
        :meth:`unhandled_input` method.
        Fr   mouse_eventTfocusN)r*   r)   get_cols_rowsr
   r-   r;   r   
selectablekeypressr   r   clearboolr7   )r3   r   something_handledkeventbuttoncolrows           r   r   zMainLoop.process_input  s    #{{88:D! 	)AO#a *+'vsC4//?++778H8H!634 8 A %%002((11$2B2BAFq>]2KK%%'(,%%d.B.B1.E)FF%$(!%	)( ! r   c                      y)a  
        >>> w = _refl("widget")
        >>> w.selectable_rval = True
        >>> scr = _refl("screen")
        >>> scr.get_cols_rows_rval = (10, 5)
        >>> ml = MainLoop(w, [], scr)
        >>> ml.process_input(['enter', ('mouse drag', 1, 14, 20)])
        screen.get_cols_rows()
        widget.selectable()
        widget.keypress((10, 5), 'enter')
        widget.mouse_event((10, 5), 'mouse drag', 1, 14, 20, focus=True)
        True
        Nr   r?   s    r   _test_process_inputzMainLoop._test_process_input  rz   r   c                 B    | j                   r| j                  ||      S |S )av  
        This function is passed each all the input events and raw keystroke
        values. These values are passed to the *input_filter* function
        passed to the constructor. That function must return a list of keys to
        be passed to the widgets to handle. If no *input_filter* was
        defined this implementation will return all the input events.
        )r,   r   s      r   r6   zMainLoop.input_filter  s%     %%dC00r   c                 >    | j                   r| j                  |      S y)a  
        This function is called with any input that was not handled by the
        widgets, and calls the *unhandled_input* function passed to the
        constructor. If no *unhandled_input* was defined then the input
        will be ignored.

        *input* is the keyboard or mouse input.

        The *unhandled_input* function should return ``True`` if it handled
        the input.
        N)r+   )r3   inputs     r   r7   zMainLoop.unhandled_input(  s#       ((// !r   c                 R    | j                   j                  r| j                          yy)z
        This method is called whenever the event loop is about to enter the
        idle state. :meth:`draw_screen` is called here to update the
        screen when anything has changed.
        N)r)   startedr   r?   s    r   r   zMainLoop.entering_idle7  s"     ;; r   c                     | j                   s| j                  j                         | _         | j                  j	                  | j                   d      }| j                  j                  | j                   |       y)a5  
        Render the widgets and paint the screen. This method is called
        automatically from :meth:`entering_idle`.

        If you modify the widgets displayed outside of handling input or
        responding to an alarm you will need to call this method yourself
        to repaint the screen.
        Tr   N)r*   r)   r   r;   renderr   )r3   canvass     r   r   zMainLoop.draw_screen@  s]     #{{88:D%%,,T-=-=T,J 0 0&9r   )r   NTNNNFr:   ) r   r   r   r   r8   r=   propertyr4   rD   r%   rO   rT   rV   rk   rp   ri   r_   rw   ry   r|   r   r   rv   r   r   r   r   r   r6   r7   r   r   r   r   r   r   r   <   s    +Z 37BF%*!F0 .F0 0,?G.; 4)V$89:$%LC (2/(b*%!N
0:r   r   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)	EventLoopzT
    Abstract class representing an event loop to be used by :class:`MainLoop`.
    c                     t               )aW  
        Call callback() a given time from now.  No parameters are
        passed to callback.

        This method has no default implementation.

        Returns a handle that may be passed to remove_alarm()

        seconds -- floating point time to wait before calling callback
        callback -- function to call from event loop
        r.   r3   secondsrI   s      r   rM   zEventLoop.alarmU       "##r   c                     t               )z
        Add a callback for entering idle.

        This method has no default implementation.

        Returns a handle that may be passed to remove_idle()
        r   r3   rI   s     r   r   zEventLoop.enter_idlec       "##r   c                     t               )z
        Remove an alarm.

        This method has no default implementation.

        Returns True if the alarm exists, False otherwise
        r   rW   s     r   rV   zEventLoop.remove_alarmm  r   r   c                     t               )z
        Remove an idle callback.

        This method has no default implementation.

        Returns True if the handle was removed.
        r   rW   s     r   r   zEventLoop.remove_enter_idlew  r   r   c                     t               )z
        Remove an input file.

        This method has no default implementation.

        Returns True if the input file exists, False otherwise
        r   rW   s     r   r_   zEventLoop.remove_watch_file  r   r   c                     t               )z
        Start the event loop.  Exit the loop when any callback raises
        an exception.  If ExitMainLoop is raised, exit cleanly.

        This method has no default implementation.
        r   r?   s    r   rw   zEventLoop.run  s     "##r   c                     t               )aV  
        Call callback() when fd has some data to read.  No parameters
        are passed to callback.

        This method has no default implementation.

        Returns a handle that may be passed to remove_watch_file()

        fd -- file descriptor to watch for input
        callback -- function to call when input is available
        r   rr   s      r   ri   zEventLoop.watch_file  r   r   c                 .    t        j                   ||      S )a  
        Sets the signal handler for signal signum.

        The default implementation of :meth:`set_signal_handler`
        is simply a proxy function that calls :func:`signal.signal()`
        and returns the resulting value.

        signum -- signal number
        handler -- function (taking signum as its single argument),
        or `signal.SIG_IGN`, or `signal.SIG_DFL`
        )signal)r3   signumhandlers      r   r1   zEventLoop.set_signal_handler  s     }}VW--r   N)r   r   r   r   rM   r   rV   r   r_   rw   ri   r1   r   r   r   r   r   P  s/    $$$$$$$.r   r   c                   L    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)r/   z3
    Event loop based on :func:`select.select`
    c                 Z    g | _         i | _        d| _        i | _        t	               | _        y Nr   )r   _watch_files_idle_handle_idle_callbacksr   
_tie_breakr?   s    r   r8   zSelectEventLoop.__init__  s*    !'r   c                     t        j                          |z   }|t        | j                        |f}t        j                  | j
                  |       |S #  
        Call callback() a given time from now.  No parameters are
        passed to callback.

        Returns a handle that may be passed to remove_alarm()

        seconds -- floating point time to wait before calling callback
        callback -- function to call from event loop
        )rR   nextr   r   heappushr   )r3   r   rI   rS   rX   s        r   rM   zSelectEventLoop.alarm  s@     YY[7"d4??+X6t||V,r   c                     	 | j                   j                  |       t        j                  | j                          y# t        $ r Y yw xY w)]
        Remove an alarm.

        Returns True if the alarm exists, False otherwise
        TF)r   remover   heapify
ValueErrorrW   s     r   rV   zSelectEventLoop.remove_alarm  s>    	LL'MM$,,' 		s   := 	A	A	c                 $    || j                   |<   |S "  
        Call callback() when fd has some data to read.  No parameters
        are passed to callback.

        Returns a handle that may be passed to remove_watch_file()

        fd -- file descriptor to watch for input
        callback -- function to call when input is available
        r   rr   s      r   ri   zSelectEventLoop.watch_file  s     !)"	r   c                 <    || j                   v r| j                   |= yyg
        Remove an input file.

        Returns True if the input file exists, False otherwise
        TFr   rW   s     r   r_   z!SelectEventLoop.remove_watch_file  s&     T&&&!!&)r   c                 v    | xj                   dz  c_         || j                  | j                   <   | j                   S )q
        Add a callback for entering idle.

        Returns a handle that may be passed to remove_idle()
           r   r   r   s     r   r   zSelectEventLoop.enter_idle  7     	Q2:T../   r   c                 >    	 | j                   |= y# t        $ r Y yw xY w[
        Remove an idle callback.

        Returns True if the handle was removed.
        FTr   rn   rW   s     r   r   z!SelectEventLoop.remove_enter_idle  .    	$$V,   		    	c                 P    | j                   j                         D ]	  } |         y)z9
        Call all the registered idle callbacks.
        N)r   valuesr   s     r   _entering_idlezSelectEventLoop._entering_idle  s'     ,,335 	HJ	r   c                     	 d| _         	 	 | j                          # t        j                  $ r}|j                  d   dk7  r Y d}~,d}~ww xY w# t
        $ r Y yw xY w)
        Start the event loop.  Exit the loop when any callback raises
        an exception.  If ExitMainLoop is raised, exit cleanly.
        Tr      N)_did_something_loopselecterrorargsr   )r3   es     r   rw   zSelectEventLoop.run  se    

	"&DJJL  || vvayA~ &  		s6   A  A AAA AA 	AAc                    t        | j                  j                               }| j                  s| j                  r| j                  r3| j                  d   d   }t        d|t        j                         z
        }| j                  r!| j                  r| j                  r	dkD  rd}d}t        j                  |g |      \  }}}nd}t        j                  |g |      \  }}}|sPdk(  r| j                          d| _        n3|1t        j                  | j                        \  }}} |        d| _        |D ]  }	 | j                  |	           d| _         y)z6
        A single iteration of the event loop
        r   idleNFT)listr   r   r   r   r   rR   r   r   r   r   )
r3   fdsrS   timeoutreadywerrr   alarm_callbackrs   s
             r   r   zSelectEventLoop._loop  s-    4$$))+,<<4..||\\!_Q'adiik!12""DLL\\gk"MM#r3@ME1cB"MM#r37ME1cV|##%&+#05dll0K-I~ &*# 	'B!Db!#"&D	'r   N)r   r   r   r   r8   rM   rV   ri   r_   r   r   r   rw   r   r   r   r   r/   r/     s9    "	!
"'r   r/   c                   X    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zy)GLibEventLoopz+
    Event loop based on GLib.MainLoop
    c                     ddl m} || _        g | _        i | _        d| _        d| _        i | _        |j                         | _        d | _	        | j                          i | _        y )Nr   )GLibF)gi.repositoryr  r   r   r   _glib_idle_enabledr   r   r   	_exc_info_enable_glib_idle_signal_handlers)r3   r  s     r   r8   zGLibEventLoop.__init__D  s[    &	"'!]]_
  "r   c                       j                    fd       } j                  j                  t        |dz        |      } j                  j                  |       |fS )r   c                  4              j                          yr[   r  )rI   r3   s   r   	ret_falsez&GLibEventLoop.alarm.<locals>.ret_false[  s    J""$r   i  )handle_exitr  timeout_addintr   append)r3   r   rI   r  rs   s   ` `  r   rM   zGLibEventLoop.alarmQ  sZ     
			 
	 YY""3wt|#4i@BH~r   c                     t         j                  t         j                  t         j                  t         j                  t         j
                  g} j                  j                  ddd      s|j                  t         j                         ||vry| j                  v r4 j                  j                   j                  j                  |             t         j                  k(  rd nt         j                  k(  ry fd} j                  j                   j                  j                   |||      }| j                  |<   y)a  
        Sets the signal handler for signal signum.

        .. WARNING::
            Because this method uses the `GLib`-specific `unix_signal_add`
            function, its behaviour is different than `signal.signal().`

            If `signum` is not `SIGHUP`, `SIGINT`, `SIGTERM`, `SIGUSR1`,
            `SIGUSR2` or `SIGWINCH`, this method performs no actions and
            immediately returns None.

            Returns None in all cases (unlike :func:`signal.signal()`).
        ..

        signum -- signal number
        handler -- function (taking signum as its single argument),
        or `signal.SIG_IGN`, or `signal.SIG_DFL`
           6   r   Nc                      y r:   r   )xs    r   r@   z2GLibEventLoop.set_signal_handler.<locals>.<lambda>  rz   r   c                 @     |        j                   j                  S r:   )r  SOURCE_CONTINUE)signal_numberr   r3   s    r   final_handlerz7GLibEventLoop.set_signal_handler.<locals>.final_handler  s    M"99,,,r   )r   SIGHUPSIGINTSIGTERMSIGUSR1SIGUSR2r  check_versionr  SIGWINCHr  source_removerm   SIG_IGNSIG_DFLunix_signal_addPRIORITY_DEFAULT)r3   r   r   glib_signalsr  sources   ` `   r   r1   z GLibEventLoop.set_signal_handlerd  s    ( MMMMNNNNNN
 yy&&q"a00%T***II##D$9$9$=$=f$EFfnn$$G&	- **499+E+Ev}^de(.f%r   c                     	 | j                   j                  |d          | j                  j                  |d          y# t        $ r Y yw xY w)r   r   TF)r   r   r  r%  r   rW   s     r   rV   zGLibEventLoop.remove_alarm  sH    	LLq	*II##F1I. 		s   <? 	A
Ac                       j                    fd       } j                  j                  | j                  j                  |       j                  |<   |S )r   c                 4             j                          yNTr  )r+  cb_conditionrI   r3   s     r   io_callbackz-GLibEventLoop.watch_file.<locals>.io_callback  s    J""$r   )r  r  io_add_watchIO_INr   )r3   rs   rI   r1  s   ` ` r   ri   zGLibEventLoop.watch_file  sR     
			 
	
 YY##Btyy{C 	"	r   c                     || j                   v r6| j                  j                  | j                   |          | j                   |= yyr   )r   r  r%  rW   s     r   r_   zGLibEventLoop.remove_watch_file  sC     T&&&II##D$5$5f$=>!!&)r   c                 v    | xj                   dz  c_         || j                  | j                   <   | j                   S zw
        Add a callback for entering idle.

        Returns a handle that may be passed to remove_enter_idle()
        r   r   r   s     r   r   zGLibEventLoop.enter_idle  r   r   c                 v    | j                   ry | j                  j                  | j                         d| _         y r/  )r	  r  idle_add_glib_idle_callbackr?   s    r   r  zGLibEventLoop._enable_glib_idle  s.    ""		4334"&r   c                 ^    | j                   j                         D ]	  } |         d| _        yr[   )r   r   r	  r   s     r   r9  z!GLibEventLoop._glib_idle_callback  s0    ,,335 	HJ	"'r   c                 >    	 | j                   |= y# t        $ r Y yw xY wr   r   rW   s     r   r   zGLibEventLoop.remove_enter_idle  r   r   c                 h   	 | j                   j                          | j                   j                         r| j                   j                          	 | j                  r| j                  }d| _        t        |  yy# | j                   j                         r| j                   j                          w w xY wr   N)r   rw   
is_runningquitr
  r   r3   exc_infos     r   rw   zGLibEventLoop.run  s~    
	"JJNNzz$$&

!>>~~H!DNX	  zz$$&

! 's   A: :7B1c                       fd}|S )a,  
        Decorator that cleanly exits the :class:`GLibEventLoop` if
        :exc:`ExitMainLoop` is thrown inside of the wrapped function. Store the
        exception info if some other exception occurs, it will be reraised after
        the loop quits.

        *f* -- function to be wrapped
        c                     	  | i |S # t         $ r j                  j                          Y y dd l} |j                         _        j                  j                         rj                  j                          Y yxY w)Nr   F)r   r   r?  sysrA  r
  r>  )r   kargsrD  fr3   s      r   wrapperz*GLibEventLoop.handle_exit.<locals>.wrapper  sn    &$''' "

! &!-::((*JJOO%s    #BABr   )r3   rF  rG  s   `` r   r  zGLibEventLoop.handle_exit  s    
	 r   N)r   r   r   r   r8   rM   r1   rV   ri   r_   r   r  r9  r   rw   r  r   r   r   r  r  ?  sD    #&0/d&
!'
 r   r  c                       e Zd ZdZ e       ZdZ G d de      Ze	d        Z
ddZd Zd	 Zd
 Zd Zd Zd Zd Zd Zy)TornadoEventLoopa^   This is an Urwid-specific event loop to plug into its MainLoop.
        It acts as an adaptor for Tornado's IOLoop which does all
        heavy lifting except idle-callbacks.

        Notice, since Tornado has no concept of idle callbacks we
        monkey patch ioloop._impl.poll() function to be able to detect
        potential idle periods.
    r   c                   "    e Zd ZdZd Zd Zd Zy)TornadoEventLoop.PollProxyz A simple proxy for a Python's poll object that wraps the .poll() method
            in order to detect idle periods and call Urwid callbacks
        c                 <    || _         || _        d| _        d| _        y )NFr   )_PollProxy__poll_obj_PollProxy__idle_map
_idle_done_prev_timeout)r3   poll_objidle_maps      r   r8   z#TornadoEventLoop.PollProxy.__init__  s    &DO&DO#DO!"Dr   c                 .    t        | j                  |      S r:   )getattrrM  )r3   names     r   __getattr__z&TornadoEventLoop.PollProxy.__getattr__!  s    4??D11r   c           	         || j                   kD  rd| _        || _         t        j                         }| j                  j	                  d      }|r	d| _        |S | j                  s-| j
                  j                         D ]	  } |         d| _        t        dt        |||z   t        j                         z
              }| j                  j	                  |      }|rd| _        |S )NFr   T)	rP  rO  rR   rM  pollrN  r   r   min)r3   r   r|   eventsrI   s        r   rX  zTornadoEventLoop.PollProxy.poll$  s    +++"'!(DIIKE __))!,F"' ?? $ 6 6 8 HJ"& !S'E/DIIK*GHIG__))'2F"'Mr   N)r   r   r   r   r8   rV  rX  r   r   r   	PollProxyrK    s    		#	2	r   r[  c                     || j                   v ryi x| j                   |<   }| j                  |j                  |      |_        y)z@ Wraps original poll object in the IOLoop's poll object
        N)_ioloop_registryr[  _impl)clsiolooprR  s      r   _patch_poll_implz!TornadoEventLoop._patch_poll_impl>  s@     S)))244V$x}}V\\8<r   Nc                     |sddl m} |j                         }|| _        | j	                  |       i | _        i | _        d| _        d | _        y )Nr   IOLoop)	tornado.iolooprd  instance_ioloopra  _pending_alarms_watch_handles_max_watch_handle
_exception)r3   r`  rd  s      r   r8   zTornadoEventLoop.__init__I  sH    -__&Ff%!!#!"!%r   c                       j                   } fd}|j                  |j                         |z   |      d j                  <   S )Nc                  l    	 j                   =  j                                 y # t        $ r Y "w xY wr:   )rh  rn   r  )rI   rX   r3   s   r   wrappedz'TornadoEventLoop.alarm.<locals>.wrappedV  s?    ((0 'DX&(  s   ' 	33r   )rg  add_timeoutrR   rh  )r3   secsrI   r`  rn  rX   s   ` `  @r   rM   zTornadoEventLoop.alarmT  sE    ,,	) ##FKKMD$8'B'(V$r   c                 t    | j                   j                  |       	 | j                  |= y# t        $ r Y yw xY w)NTF)rg  remove_timeoutrh  rn   rW   s     r   rV   zTornadoEventLoop.remove_alarm`  s@    ##F+	$$V,   		s   + 	77c                      ddl m}  fd} j                  j                  |||j                          xj
                  dz  c_         j
                  }| j                  |<   |S )Nr   rc  c                 0     j                               S r:   )r  )rs   rZ  rI   r3   s     r   r@   z-TornadoEventLoop.watch_file.<locals>.<lambda>k  s    $>D$4$4X$>$@ r   r   )re  rd  rg  add_handlerREADrj  ri  )r3   rs   rI   rd  r   rX   s   ` `   r   ri   zTornadoEventLoop.watch_filei  sV    )@  Wfkk:!#''&(F#r   c                 x    | j                   j                  |d       }|y| j                  j                  |       y)NFT)ri  rm   rg  remove_handler)r3   rX   rs   s      r   r_   z"TornadoEventLoop.remove_watch_filer  s7      $$VT2:LL''+r   c                     | xj                   dz  c_         | j                   }| j                  | j                     }|||<   |S )Nr   )_max_idle_handler]  rg  )r3   rI   rX   rR  s       r   r   zTornadoEventLoop.enter_idlez  sA    "((((6#r   c                 `    | j                   | j                     }|j                  |d       }|d uS r:   )r]  rg  rm   )r3   rX   rR  rK   s       r   r   z"TornadoEventLoop.remove_enter_idle  s0    ((6\\&$'~r   c                 2     t               fd       }|S )Nc                      	  | i |S # t         $ r j                  j                          Y yt        $ r+}|_        j                  j                          Y d }~yd }~ww xY wr[   )r   rg  r   	Exceptionrk  )r   kwexcfuncr3   s      r   rG  z-TornadoEventLoop.handle_exit.<locals>.wrapper  sd    $T(R(( $!!#   $"%!!##$s    #A#A#!AA#r   )r3   r  rG  s   `` r   r  zTornadoEventLoop.handle_exit  s     	t	 
	 r   c                 |    | j                   j                          | j                  r| j                  d c}| _        |y r:   )rg  r|   rk  )r3   r  s     r   rw   zTornadoEventLoop.run  s5    ??#'??D CI r   r:   )r   r   r   r   r   r]  rz  objectr[  classmethodra  r8   rM   rV   ri   r_   r   r   r  rw   r   r   r   rI  rI    sf     )*%F %N = =	&

r   rI  )FileDescriptorc                       e Zd Zd Zd Zd Zy)TwistedInputDescriptorc                 L    || _         || _        t        j                  | |       y r:   )_filenorK   r  r8   )r3   reactorrs   rK   s       r   r8   zTwistedInputDescriptor.__init__  s     g.r   c                     | j                   S r:   )r  r?   s    r   filenozTwistedInputDescriptor.fileno  s    ||r   c                 "    | j                         S r:   )rK   r?   s    r   doReadzTwistedInputDescriptor.doRead  s    wwyr   N)r   r   r   r8   r  r  r   r   r   r  r    s    /
r   r  c                   Z    e Zd ZdZdZddZd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd ZddZy)TwistedEventLoopz&
    Event loop based on Twisted_
    g      p?Nc                     |ddl }|j                  j                  }|| _        g | _        i | _        d| _        d| _        i | _        d| _        || _	        | j                          y)a-  
        :param reactor: reactor to use
        :type reactor: :class:`twisted.internet.reactor`.
        :param: manage_reactor: `True` if you want this event loop to run
                                and stop the reactor.
        :type manage_reactor: boolean

        .. WARNING::
           Twisted's reactor doesn't like to be stopped and run again.  If you
           need to stop and run your :class:`MainLoop`, consider setting
           ``manage_reactor=False`` and take care of running/stopping the reactor
           at the beginning/ending of your program yourself.

           You can also forego using :class:`MainLoop`'s run() entirely, and
           instead call start() and stop() before and after starting the
           reactor.

        .. _Twisted: http://twistedmatrix.com/trac/
        Nr   F)twisted.internet.reactorinternetr  r   r   r   _twisted_idle_enabledr   r
  manage_reactor_enable_twisted_idle)r3   r  r  twisteds       r   r8   zTwistedEventLoop.__init__  sf    ( ?+&&..G%*"!,!!#r   c                 \    | j                   j                  || j                  |            }|S r   )r  	callLaterr  )r3   r   rI   rX   s       r   rM   zTwistedEventLoop.alarm  s*     ''1A1A(1KLr   c                 X    ddl m}m} 	 |j                          y# |$ r Y y|$ r Y yw xY w)r   r   )AlreadyCancelledAlreadyCalledTF)twisted.internet.errorr  r  cancel)r3   rX   r  r  s       r   rV   zTwistedEventLoop.remove_alarm  s6     	K	MMO 	 		s    )))c                     t        | j                  || j                  |            }|| j                  |<   | j                  j	                  |       |S r   )r  r  r  r   	addReader)r3   rs   rI   inds       r   ri   zTwistedEventLoop.watch_file  sK     %T\\2X&( #"s#	r   c                     || j                   v r6| j                  j                  | j                   |          | j                   |= yyr   )r   r  removeReaderrW   s     r   r_   z"TwistedEventLoop.remove_watch_file  sC     T&&&LL%%d&7&7&?@!!&)r   c                 v    | xj                   dz  c_         || j                  | j                   <   | j                   S r6  r   r   s     r   r   zTwistedEventLoop.enter_idle  r   r   c                     | j                   ry| j                  j                  | j                  | j	                  | j
                  d             d| _         y)aU  
        Twisted's reactors don't have an idle or enter-idle callback
        so the best we can do for now is to set a timer event in a very
        short time to approximate an enter-idle callback.

        .. WARNING::
           This will perform worse than the other event loops until we can find a
           fix or workaround
        NF)enable_idleT)r  r  r  _idle_emulation_delayr  _twisted_idle_callbackr?   s    r   r  z%TwistedEventLoop._enable_twisted_idle  sL     %%t99T88eL	N%)"r   c                 ^    | j                   j                         D ]	  } |         d| _        y r[   )r   r   r  r   s     r   r  z'TwistedEventLoop._twisted_idle_callback%  s-    ,,335 	HJ	%*"r   c                 >    	 | j                   |= y# t        $ r Y yw xY wr   r   rW   s     r   r   z"TwistedEventLoop.remove_enter_idle*  r   r   c                     | j                   sy| j                  j                          | j                  r| j                  }d| _        t	        |  yyr=  )r  r  rw   r
  r   r@  s     r   rw   zTwistedEventLoop.run6  sD    
 "">>~~H!DNX	 r   c                       fd}|S )a1  
        Decorator that cleanly exits the :class:`TwistedEventLoop` if
        :class:`ExitMainLoop` is thrown inside of the wrapped function. Store the
        exception info if some other exception occurs, it will be reraised after
        the loop quits.

        *f* -- function to be wrapped
        c                  d   d }	  | i |}rj                          |S # t         $ r) j                  rj                  j                          Y E dd l}t         |j                                 |j                         _        j                  rj                  j                          Y xY wr   )
r   r  r  r   rD  printrA  r
  crashr  )r   rE  rb   rD  r  rF  r3   s       r   rG  z-TwistedEventLoop.handle_exit.<locals>.wrapperM  s    D
)$'' ))+K   (&&LL%%')lclln%!-&&LL&&(s   ! /B/AB/r   )r3   rF  r  rG  s   ``` r   r  zTwistedEventLoop.handle_exitD  s    	  r   r/  )T)r   r   r   r   r  r8   rM   rV   ri   r_   r   r  r  r   rw   r  r   r   r   r  r    sG     $$B 
!* +

r   r  c                   R    e Zd ZdZdZdZd Zd Zd Zd Z	d Z
d	 Zd
 ZdZd Zd Zy)AsyncioEventLoopa#  
    Event loop based on the standard library ``asyncio`` module.

    ``asyncio`` is new in Python 3.4, but also exists as a backport on PyPI for
    Python 3.3.  The ``trollius`` package is available for older Pythons with
    slightly different syntax, but also works with this loop.
    Fg?c                 l    d|v r|j                  d      | _        y dd l}|j                         | _        y )Nloopr   )rm   r   asyncioget_event_loop)r3   kwargsr  s      r   r8   zAsyncioEventLoop.__init__l  s-    VF+DJ //1DJr   c                 :    | j                   j                  ||      S )a  
        Call callback() a given time from now.  No parameters are
        passed to callback.

        Returns a handle that may be passed to remove_alarm()

        seconds -- time in seconds to wait before calling callback
        callback -- function to call from event loop
        )r   
call_laterr   s      r   rM   zAsyncioEventLoop.alarms  s     zz$$Wh77r   c                 ~    t        |dd      r|j                         n|j                  }| }|j                          |S )r   	cancelledN)rT  r  
_cancelledr  )r3   rX   r  existeds       r   rV   zAsyncioEventLoop.remove_alarm  sC     v{D1 "" 	
  -r   c                 >    | j                   j                  ||       |S r   )r   
add_readerrr   s      r   ri   zAsyncioEventLoop.watch_file  s     	

b(+	r   c                 8    | j                   j                  |      S )r   )r   remove_readerrW   s     r   r_   z"AsyncioEventLoop.remove_watch_file  s     zz''//r   c                 v     dg fd j                   j                   j                        d<   S )r   Nc                  f              j                   j                  j                        d<   y r   r   r  r  )rI   faux_idle_callbackmutable_handler3   s   r   r  z7AsyncioEventLoop.enter_idle.<locals>.faux_idle_callback  s.    J $

 5 5**,>!@N1r   r   r  )r3   rI   r  r  s   ``@@r   r   zAsyncioEventLoop.enter_idle  sA     	@
 !JJ11&&(:<q r   c                 *    | j                  |d         S )r   r   )rV   rW   s     r   r   z"AsyncioEventLoop.remove_enter_idle  s       ++r   Nc                     |j                  d      }|r?|j                          t        |t              st	        |      ||j
                  f| _        y y |j                  |       y )N	exception)getr   
isinstancer   type__traceback__r
  default_exception_handler)r3   r  contextr  s       r   _exception_handlerz#AsyncioEventLoop._exception_handler  sS    kk+&IIKc<0"&s)S#2C2C!D 1 **73r   c                     | j                   j                  | j                         | j                   j                          | j                  r| j                  }d| _        t        |  yyr=  )r   set_exception_handlerr  run_foreverr
  r   r@  s     r   rw   zAsyncioEventLoop.run  sP    
 	

(()@)@A

 >>~~H!DNX r   )r   r   r   r   _we_started_event_loopr  r8   rM   rV   ri   r_   r   r   r
  r  rw   r   r   r   r  r  `  sI     #"2
80(, I4
r   r  )      r   )TrioEventLoopc                 :     G fddt                |       S )aO  
    This function is used to test the main loop classes.

    >>> scr = _refl("screen")
    >>> scr.function("argument")
    screen.function('argument')
    >>> scr.callme(when="now")
    screen.callme(when='now')
    >>> scr.want_something_rval = 42
    >>> x = scr.want_something()
    screen.want_something()
    >>> x
    42

    c                   *    e Zd ZddZfdZ fdZy)_refl.<locals>.ReflectNc                      || _         || _        y r:   )_name_rval)r3   rU  rb   s      r   r8   z_refl.<locals>.Reflect.__init__  s    DJDJr   c                 p   dj                  |D cg c]  }t        |       c}      }|r|r|dz   }|dj                  |j                         D cg c]  \  }}|dz   t        |      z    c}}      z   }t        | j                  dz   |z   dz          r
t               | j                  S c c}w c c}}w )Nz, =())joinrepritemsr  r  r   r  )r3   arglargdar   r   vexits          r   __call__z_refl.<locals>.Reflect.__call__  s    99t4!d1g45Dd{$))djjl$KsqQsU47]$KLLD$**S.%c)*"n$:: 5 %Ls   B-B2c                     |j                  d      r
t               t        | |dz         r& | j                  dz   |z   t	        | |dz               S  | j                  dz   |z         S )Nr  .)endswithAttributeErrorr-   r  rT  )r3   attrReflects     r   rV  z"_refl.<locals>.Reflect.__getattr__  sc    }}W%$&&tT'\*tzz#~d2GD$w,4OPP4::c>$.//r   r:   )r   r   r   r8   r  rV  )r  r  s   r   r  r    s    			0r   r  )r  )rU  rb   r  r  s     `@r   _reflr    s     0& 0( 4=r   c                  ,    dd l } | j                          y r   )doctesttestmod)r  s    r   _testr    s    OOr   __main__r[   )5
__future__r   r   rR   r   r   r\   r   rD  	functoolsr   	itertoolsr   weakrefr   rf   ImportError
urwid.utilr	   r
   urwid.compatr   r   urwid.command_mapr   r   
urwid.wimpr   r&   r   urwid.display_commonr   r^   r~  r   r   r  r   r   r/   r  rI  twisted.internet.abstractr  r  r  r  version_info_async_kw_event_loopr  r  r  r   r   r   r   <module>r     s9  0 0    	  
   %	 7 ) 8 "  : 	9 		) 	Q:v Q:h^. ^.@L'i L'^II IXLy L^8
^ 
qy qhvy vv v3$L Z	G G/  		l#  Ns#   D 2D D
DDD