+
    Ki  c                   s    ^ RI Ht ^ RIHtHtHtHtHtHt ^ RI	H
t
HtHt ^ RIHt ^ RIHt ^ RIHt ]'       d   ^ RIHt ]R]3,          tRR
 R lltR R ltRR R lltR R ltR	# )i    )wraps)TYPE_CHECKINGAnyCallableIterableOptionalcast)GLibGObjectGtk)display_error)get_required_main_window)logger)Game.Nc                sX    V ^8  d   QhR\         RRR\        \        .\        3,          /# )   game_stop_resultgamer   return)r   r   AnyCallableZformat   "?/usr/lib/python3.14/site-packages/lutris/exception_backstops.py__annotate__r      s.          6  X{m]hNhEi      c                s"   a a VoR VV 3R llpV# )a  Decorator used to catch exceptions and send events instead of propagating them normally.
If 'game_stop_result' is not None, and the decorated function returns that, this will
send game-stop and make the game stopped as well. This simplifies handling cancellation.
Also, if an error occurs and is emitted, the function returns this value, so callers
can tell that the function failed.

If you do not provide a game object directly, it is assumed to be in the first argument to
the decorated method (which is 'self', typically).
c                s0    V ^8  d   QhR\         R\         /# )r   functionr   )r   r   r   r   r   Z'watch_game_errors.<locals>.__annotate__   s     * *+ *+ *r   c                 sX   <a  \        S 4      R  VV V3R ll4       p\        \        V4      # )c                <    V ^8  d   QhR\         R\         R\         /# r   argskwargsr   r   r   r   r   r   Z@watch_game_errors.<locals>.inner_decorator.<locals>.__annotate__   s!     	( 	(3 	(# 	(# 	(r   c                 s  < S'       d   SMV ^ ,          p S! V / VB pSe3   VS8X  d,   VP                   VP                  8w  d   VP                  4        V#   \         db   p\        P
                  ! RY$TR7       TP                   TP                  8w  d   TP                  4        TP                  T4       Su Rp?# Rp?ii ; i)z'Catch all exceptions and emit an event.Nz%s has encountered an error: %s)Zexc_info)ZstateZSTATE_STOPPEDZ	stop_game	Exceptionr   	exceptionZsignal_error)r   r   r   Zresultexcaptured_gamer   r   s   *,   r   wrapperZ;watch_game_errors.<locals>.inner_decorator.<locals>.wrapper   s     %2=tAwD
(!4262#/F>N4NSWS]S]aeasasSsNN$ (  !BDWYZ::!3!33NN$!!"%''(s   ?A C!AB=7C=C)r    r   r   )r   r"   r!   r   s   f r   inner_decoratorZ*watch_game_errors.<locals>.inner_decorator   s-    	x	( 	( 
	(  K))r    )r   r   r#   r!   s   f& @r   watch_game_errorsr%      s     M* *( r   c                s    V ^8  d   QhR\         \        \        P                  ,          ,          R\        P
                  /# )r   error_objectsr   )r   r   r   Objectr	   ZWindowr   r   r   r   r   3   s,     & &Xhw~~.F%G &CJJ &r   c                s    V  FH  pV'       g   K   V'       d3   \        VR4      '       d   VP                  4       pV'       d   Vu # KF  KH  KJ  	  \	        4       #   \        P                   d     Kn  i ; i)a  Obtains a top-level window to use as the parent of an
error, by examining s list of objects. Any that are None
are skipped; we call get_toplevel() on each object that has
this method, and return the first non-None result.

If this fails, we turn to the application's main window instead.get_toplevel)hasattrr(   r   ZGErrorr   )r&   Zerror_objectZtoplevels   &  r   _get_error_parentr*   3   sn     &	n E E'3'@'@'B#O  !F| & $%% {{ 		s   A)AAA21A2c                s`    V ^8  d   QhR\         R\        R\        R\        R\        R\         /# )r   handlerhandler_nameerror_resulterror_method_nameconnected_objectr   )r   strr   r   r   r   r   r   J   s<     , ,,(+,;>,SV,jm,,r   c                s   a aaaaa \        S R4      '       d   S P                  MRoR VVVV VV3R llp\        \        V4      # )zzWraps a handler function in an error handler that will log and then report
any exceptions, then return the 'error_result'.__self__Nc                r   r   r   r   r   r   r   Z+_create_error_wrapper.<locals>.__annotate__R   s!        S  C  C  r   c                  s  <  S! V / VB #   \          dk   p\        P                  ! R ST4       S	'       d(   \        S	S4      '       d   \	        S	S4      pT! T4       M\        T\        S	S.4      4       Su Rp?# Rp?ii ; i)zError handling %s: %sN)r   r   r   r)   Zgetattrr
   r*   )
r   r   r    Zerror_methodr/   r.   r-   r+   r,   handler_objects
   *,  r   error_wrapperZ,_create_error_wrapper.<locals>.error_wrapperR   s|    
	 D+F++ 	 4lBG'.:K"L"L&~7HIR b"3^EU4V"WX	 s    B AA;5B ;B )r)   r1   r   r   )r+   r,   r-   r.   r/   r3   r2   s   fffff @r   _create_error_wrapperr4   J   s7     *1*)E)EW%%4N    ]++r   c                s    V ^8  d   QhRR/# )r   r   Nr$   r   r   r   r   r   b   s     H3 H3$ H3r   c                 sV  aaaa R V3R llp R V3R llpR V3R llpR V3R llp\         P                  P                  oV \        P                  n        \        P
                  oV\        n        \        P                  oV\        n        \        P                  oV\        n        R	# )
a  This function is called once only, during startup, and replaces ("swizzles") a bunch of
callback setup functions in GLib. The callbacks are all wrapped with error handlers that
log the error and report it.

This is important to do because PyGObject will straight up crash if an exception escapes
these handlers; it's better to tell the user and try to survive.

You can provide certain methods to provide error handling, but if you do not you get an
ErrorDialog. Put these handling methods on the same object as the callback method itself.

We take care of these methods:
    GObject.Object.connect (via on_signal_error(self, error))
    GObject.add_emission_hook (via on_emission_hook_error(self, error))
    GLib.idle_add (via on_idle_error(self, error))
    GLib.timeout_add (via on_timeout_error(self, error))

Idle and timeout handlers will be disconnected if this happens to avoid repeated error reports,
but signals and emission hooks will remain connected.
c                t    V ^8  d   QhR\         P                  R\        R\        R\        R\        R\        /# )r   selfsignal_specr+   r   r   r   )r	   Widgetr0   r   r   r   r   r   r   .init_exception_backstops.<locals>.__annotate__w   sH     
T 
Tjj
T'*
T5@
TIL
TX[
T	
Tr   c                 sF   < \        VR V R2RRV R7      pS! WV.VO5/ VB # )zsignal ''NZon_signal_error)r-   r.   r/   r4   )r6   r7   r+   r   r   r3   _original_connect   &&&*, r   _error_handling_connectZ9init_exception_backstops.<locals>._error_handling_connectw   s@     .{m1%/!
 !MSDSFSSr   c                r5   )r   emitting_typer7   r+   r   r   r   )r   r'   r0   r   r   r   r   r   r   r9      sH     	g 	g~~	g47	gBM	gVY	geh	g		gr   c                 sJ   < \        VR V  RV R2RRR7      pS! WV.VO5/ VB # )zemission hook 'Z.r:   TZon_emission_hook_errorr-   r.   r;   )r?   r7   r+   r   r   r3   _original_add_emission_hookr=   r   !_error_handling_add_emission_hookZCinit_exception_backstops.<locals>._error_handling_add_emission_hook   sE     .m_Ak]!<6	
 +=}fW[f_effr   c                sH    V ^8  d   QhR\         R\        R\        R\        /# )r   r+   r   r   r   )r   r   r   r   r   r   r9      s/     B B+ Bc BS BUX Br   c                 s:   < \        V R RRR7      pS! V.VO5/ VB # )zidle functionFZon_idle_errorr@   r;   )r+   r   r   r3   _original_idle_adds   &*, r   _error_handling_idle_addZ:init_exception_backstops.<locals>._error_handling_idle_add   s0    --	
 "-A$A&AAr   c          
      sT    V ^8  d   QhR\         R\        R\        R\        R\        /# )r   intervalr+   r   r   r   )Zintr   r   r   r   r   r   r9      s9     O Oc OK OPS O_b Ogj Or   c                 s:   < \        VR RRR7      pS! W.VO5/ VB # )ztimeout functionFZon_timeout_errorr@   r;   )rE   r+   r   r   r3   _original_timeout_adds   &&*, r   _error_handling_timeout_addZ=init_exception_backstops.<locals>._error_handling_timeout_add   s0    -0	
 %XNtNvNNr   N)	r	   r8   Zconnectr   r'   Zadd_emission_hookr   Zidle_addZtimeout_add)r>   rB   rD   rG   rA   r<   rC   rF   s       @@@@r   init_exception_backstopsrH   b   s    *
T 
T	g 	gB BO O 

**4GNNU\UnUn AG,DM ,,2Dr   )N)Z	functoolsr    Ztypingr   r   r   r   r   r   Zgi.repositoryr   r   r	   Zlutris.gui.dialogsr
   Zlutris.gui.widgets.utilsr   Zlutris.util.logr   Zlutris.gamer   r   r%   r*   r4   rH   r$   r   r   <module>rI      sG     I I , , , = " sCx  F&.,0H3r   