+
    Ki>Y  c            
       s>   R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H	t
 ^ RIHt ^ RIHtHtHtHtHtHtHtHtHtHt ^ RIHtHt ^ RIHt ^ RIHt ^ RIH t  ^ R	I!H"t" ]
! R
4      ]
! R4      ]
! R4      ]
! R4      ]
! R4      ]
! R4      ]
! R4      ]
! R4      3t#R R lt$R_R R llt%R_R R llt&R`R R llt'RaR R llt(RbR R llt)R R lt*R R  lt+R! R" lt,R# R$ lt-R% R& lt.R' R( lt/R) R* lt0R+ R, lt1R- R. lt2RcR/ R0 llt3R1 R2 lt4R3 R4 lt5R5 R6 lt6RdR7 R8 llt7R9 R: lt8R; R< lt9R= R> lt:R? R@ lt;RA RB lt<RC RD lt=RE RF lt>RcRG RH llt?ReRI RJ llt@RK RL ltARM RN ltBRO RP ltCRQ RR ltDRS RT ltERU RV ltFRW RX ltGRY RZ ltHR[ R\ ltIR] R^ ltJR# )fzSystem utilitiesN)gettext)Path)
IODictIterableListMappingOptionalSequenceSetTupleUnion)GioGLib)settings)MissingExecutableError)logger)TrashPortalZ	DocumentsZ	DownloadsZDesktopZPicturesZVideosZProjectsZGamesc                sF    V ^8  d   QhR\         \        \        3,          /#    return)r   strformat   "7/usr/lib/python3.14/site-packages/lutris/util/system.py__annotate__r   #   s     ` `c3h `    c                 s    \         P                  P                  4        U Uu/ uF   w  rV P                  R4      '       d   K  WbK"  	  upp # u upp i )zReturn a safe to use copy of the system's environment.
Values starting with BASH_FUNC can cause issues when written in a text file.Z	BASH_FUNC)osenvironitems
startswith)keyZvalues     r   get_environmentr!   #   s=     *,)9)9);_);:33>>R]C^JCJ);___s   AAc                s    V ^8  d   QhR\         \        ,          R\        \        \        \        3,          ,          R\        \        ,          R\        R\        R\        \
        ,          R\        /# r   commandenvcwdquietshelltimeoutr   )r   r   r   r   boolfloatr   r   r   r   r   )   sg      #Y	$sCx.	! 
# 	
  e_ 	r   c           	     s&    \        WW#WER7      w  rgV# )a  
Execute a system command and return its standard output; standard error is discarded.

Params:
    command (list): A list containing an executable and its parameters
    env (dict): Dict of values to add to the current environment
    cwd (str): Working directory
    quiet (bool): Do not display log messages
    timeout (int): Number of seconds the program is allowed to run, disabled by default

Returns:
    str: stdout output
)r$   r%   r&   r'   r(   _execute)r#   r$   r%   r&   r'   r(   stdoutZ_stderrs   &&&&&&  r   executer.   )   s    * wSUdOFMr   c                s   V ^8  d   QhR\         \        ,          R\        \        \        \        3,          ,          R\        \        ,          R\        R\        R\        \
        ,          R\        \        \        3,          /# r"   r   r   r   r   r)   r*   r
   r   r   r   r   r   B   sx     o o#Yo	$sCx.	!o 
#o 	o
 o e_o 38_or   c           
     s"    \        WVRW4VR7      # )a  
Execute a system command and return its standard output and; standard error in a tuple.

Params:
    command (list): A list containing an executable and its parameters
    env (dict): Dict of values to add to the current environment
    cwd (str): Working directory
    quiet (bool): Do not display log messages
    timeout (int): Number of seconds the program is allowed to run, disabled by default

Returns:
    str, str: stdout output and stderr output
T)r$   r%   capture_stderrr&   r'   r(   r+   )r#   r$   r%   r&   r'   r(   s   &&&&&&r   execute_with_errorr1   B   s    * G#d%fmnnr   c                s   V ^8  d   QhR\         \        ,          R\        \        \        \        3,          ,          R\        \        ,          R\        R\        R\        R\        \
        ,          R\        \        \        3,          /# )	r   r#   r$   r%   r0   r&   r'   r(   r   r/   r   r   r   r   r   Z   sy     02 02#Y02	$sCx.	!02 
#02 	02
 02 02 e_02 38_02r   c                 s   V '       g   \         P                  ! R 4       R# \        P                  P	                  V ^ ,          4      '       d2   \        V ^ ,          4      '       g   \         P                  ! RV 4       R# V'       g@   \         P                  ! RRP                  V  Uu. uF  p\        V4      NK  	  up4      4       \        4       pV'       d}   V'       g;   \         P                  ! RP                  R VP                  4        4       4      4       VP                  4        U	U
u/ uF  w  rV
f   K  WbK  	  pp	p
VP                  V4        \        P                  ! T T\        P                  V'       d   \        P                  M\        P                  VVRR7      ;_uu_ 4       pVP!                  VR	7      w  rRRR4       XP)                  4       X;'       g    RP)                  4       3# u upi u up
p	i   + '       g   i     LE; i  \"        \$        3 d%   p\         P                  ! R
YT4       Ru Rp?# Rp?i\        P&                   d    \         P                  ! RY4       Ru # i ; i)No executable provided! No executable found in %szExecuting %s c              3   H   "   T F  w  rR P                  W4      x  K  	  R# 5iz{}={}Nr   .0kv   &  r   	<genexpr>Z_execute.<locals>.<genexpr>r        !O;41'.."6"6;    "Nreplace)r'   r-   stderrr$   r%   errors)r(   &Could not run command %s (env: %s): %szCommand %s after %s seconds)r3   r3   )r   errorr   pathisabspath_existsdebugjoinr   r!   r   update
subprocessPopenPIPEDEVNULLcommunicateOSError	TypeErrorTimeoutExpiredstrip)r#   r$   r%   r0   r&   r'   r(   iexisting_envr:   r;   Zcommand_processr-   rA   exs   &&&&&&&        r   r,   r,   Z   s    ./	ww}}WQZ  WQZ)@)@0':^SXXw.Gw!s1vw.G%HI #$L
LL!O399;!OOP #		=qtqt=C ??&4:??*:L:L
 
 ,888INF
" <<>FLLb//111= /H >
 
 Y =wRP$$ 2GEs`   &G4,G99G9(H =0H -G?H ?H	
H H I6#I<I6I6I65I6c                s    V ^8  d   QhR\         \        ,          R\        \        \        3,          R\        R\        R\        RR/# )r   r#   r$   r%   r&   r'   r   N)r   r   r   r)   r   r   r   r   r      sP     (Q (Qc](Q!%c3h(Q=@(QPT(Qei(Q	(Qr   c                s   V '       g   \         P                  ! R4       R# \        P                  P	                  V ^ ,          4      '       d2   \        V ^ ,          4      '       g   \         P                  ! RV 4       R# V'       g@   \         P                  ! RRP                  V  Uu. uF  p\        V4      NK  	  up4      4       \        4       pV'       d}   V'       g;   \         P                  ! RP                  R VP                  4        4       4      4       VP                  4        UUu/ uF  w  rxVf   K  WxbK  	  pppVP                  V4        \        P                  ! W\        P                  \        P                  WbR7       R# u upi u uppi   \        \         3 d$   p	\         P                  ! RYT	4        Rp	?	R# Rp	?	ii ; i)	a6  
Execute a system command but discard its results and do not wait
for it to complete.

Params:
    command (list): A list containing an executable and its parameters
    env (dict): Dict of values to add to the current environment
    cwd (str): Working directory
    quiet (bool): Do not display log messages
r2   Nr4   zSpawning %sr5   c              3   r6   r7   r   r8   r<   r   r=   Zspawn.<locals>.<genexpr>   r>   r?   )r'   r-   rA   r$   r%   rC   )r   rD   r   rE   rF   rG   rH   rI   r   r!   r   rJ   rK   rL   rN   rP   rQ   )
r#   r$   r%   r&   r'   rT   rU   r:   r;   rV   s
   &&&&&     r   spawnrW      s>    ./	ww}}WQZ  WQZ)@)@0':]CHHg-Fgc!fg-F$GH #$L
LL!O399;!OOP #		=qtqt=C Q););JDVDV\h	
 .G > Y Q=wRPPQs*   &F,F9F6F G(GGc          
      s    V ^8  d   QhR\         \        ,          R\        R\        \        \        3,          R\        \        ,          R\        /# )r   r#   r(   r$   error_resultr   )r   r   intr   r   r   r   r   r   r      sG      c]%(3:383D[cdg[hr   c                s     \         P                  ! WVRRR7      P                  4       #   \        \         P                  \         P
                  3 d)   p\        P                  ! RY4       Tf   h Tu Rp?# Rp?ii ; i)zReturn the output of a command as a string; if 'error_result' is not None,
returns that on errors. If it is, raises an exception instead.zutf-8Zignore)r(   r$   ZencodingrB   z%s command failed: %sN)rK   Zcheck_outputrS   rP   ZCalledProcessErrorrR   r   rD   )r#   r(   r$   rX   rV   s   &&&& r   read_process_outputrZ      sj    
&&wSSZcklrrttZ22J4M4MN ,g:	s   '* *A<A71A<7A<c                0    V ^8  d   QhR\         R\         /# r   filenamer   r   r   r   r   r   r      s      S S r   c           	     s   \         P                  ! V R4      ;_uu_ 4       pVP                  4       p\        V4      ^8  d   \        P
                  ! RW^ ,          4       VP                  V^ ,          4      ;_uu_ 4       p\        V4      pRRR4       RRR4       X#   + '       g   i     L; i  + '       g   i     X# ; i)z&Return the md5 hash of a file in a zipZrz3More than 1 file in archive %s, reading 1st one: %sN)zipfileZZipFileZnamelistlenr   warningopenread_file_md5)r]   ZarchivefilesZfile_in_zip_hash   &    r   get_md5_in_ziprg      s    	3	'	'7  "u:>NNPRZbc\de\\%(##{!+.E $	 
( L $#	 
(	' Ls$   AB0?B	B0B-(B00C	c                sR    V ^8  d   QhR\         R\        \        \         3,          /# r\   )r   r   r)   r   r   r   r   r      s#      3 5s#3 r   c                s     \        V R4      ;_uu_ 4       p\        V4      pRRR4       V#   + '       g   i     X# ; i  \         d    \        P                  ! RT 4        R# i ; i)zReturn the md5 hash of a file.rbNzError reading %sF)rb   rc   ZIOErrorr   ra   )r]   Z_filere   r<   r   get_md5_hashri      s^    (D!!U!%(E "
 L "!
 L  )84s(   A  ,A  =	A  A   "A&%A&c                sF    V ^8  d   QhR\         \        ,          R\        /# )r   filedescr   )r   Zbytesr   r   r   r   r   r      s      BuI # r   c                 s   a  \         P                  ! 4       p\        V 3R  lR4       F  pVP                  V4       K  	  VP	                  4       # )c                  &   < S P                  R 4      # )i    Zread)rj      r   <lambda>Zread_file_md5.<locals>.<lambda>   s    hmmD1r   r   )hashlibmd5iterrJ   	hexdigest)rj   rp   chunks   f  r   rc   rc      s8    
++-C137

5 8==?r   c                s<    V ^8  d   QhR\         R\         R\         /# )r   r]   	hash_typer   r^   r   r   r   r   r      s!         r   c                s  a \         P                  ! V4      p\        V R4      ;_uu_ 4       o\        V3R lR4       F  pVP	                  V4       K  	  RRR4       VP                  4       #   + '       g   i     TP                  4       # ; i)z<Return the checksum of type `hash_type` for a given filenamerh   c                  rk   )i   rl   )
input_filerm   r   rn   Z#get_file_checksum.<locals>.<lambda>   s    *//$"7r   r   N)ro   Znewrb   rq   rJ   rr   )r]   rt   Zhasherrs   ru   s   &&  @r   get_file_checksumrv      sn    [[#F	h		7=EMM%  > 
  
	 s   )A--B	c                0    V ^8  d   QhR\         R\        /# )r   	exec_pathr   r   r)   r   r   r   r   r      s     ) )S )T )r   c                sL    \         P                  ! V \         P                  4      # )z)Return whether exec_path is an executable)r   ZaccessZX_OK)rx      &r   is_executabler{      s    99Y((r   c                (    V ^8  d   QhR\         RR/# )r   rx   r   Nr^   r   r   r   r   r      s     ; ;s ;t ;r   c                 s    \         P                  ! V 4      p\         P                  ! WP                  \        P                  ,          4       R # N)r   statZchmodZst_modeZS_IEXEC)rx   Z
file_stats   & r   make_executabler      s+    #JHHY**T\\9:r   c                rw   r   	exec_namer   ry   r   r   r   r   r      s     , ,3 ,4 ,r   c                s*    \        \        V 4      4      # )zChecks if an executable can be located; if false,
find_executable will return None, and find_required_executable
will raise an exception.)r)   find_executabler   rz   r   can_find_executabler      s     	*++r   c                F    V ^8  d   QhR\         R\        \         ,          /# r   r   r   r   r   r   r   r      s     : :s :x} :r   c                sB    V '       d   \         P                  ! V 4      # R# )zLReturn the absolute path of an executable, or None if
it could not be found.N)shutilZwhichr   rz   r   r   r      s     '06<<	"9T9r   c                r[   r   r^   r   r   r   r   r     s        r   c                sb    \        V 4      pV'       g   \        \        R4      V ,          4      hV# )zhReturn the absolute path of an executable, but raises a
MissingExecutableError if it could not be found.z'The executable '%s' could not be found.)r   r   _)r   Zexer   r   find_required_executabler     s-     )
$C$Q'P%QT]%]^^Jr   c          
      s    V ^8  d   QhR\         R\        R\        \        \         \        \         ,          3,          ,          /# )r   programmultipler   )r   r)   r   r   r   r   r   r   r   r     s3      S D XeCcN>S5T r   c                s    \        RV .4      pVP                  4       '       g   R# VP                  4       pV'       d   V# V^ ,          # )zReturn pid of process.

:param str program: Name of the process.
:param bool multiple: If True and multiple instances of the program exist,
    return all of them; if False only return the first one.
ZpgrepN)r.   rS   split)r   r   Zpids   && r   get_pidr     s=     GW%&D::<<::<D7Nr   c                r[   )r   unsafe_stringr   r^   r   r   r   r   r     s     A AS AS Ar   c                s<    R R lp\         P                  ! RW4      # )zDConverts a string to something that can be used as a python variablec                sZ    V ^8  d   QhR\         P                  \        ,          R\        /# )r   matchobjr   )reZMatchr   r   r   r   r   Z'python_identifier.<locals>.__annotate__  s"     3 3BHHSM 3c 3r   c                 sD    V P                  ^ 4      P                  RR4      # )i    -r   )Zgroupr@   )r   rz   r   	_dashreplZ$python_identifier.<locals>._dashrepl  s    ~~a ((c22r   z(\${)([\w-]*)(}))r   Zsub)r   r   r   r   python_identifierr     s    3 66%y@@r   c                s^    V ^8  d   QhR\         R\        \         \         3,          R\         /# )r   string_template	variablesr   )r   r   r   r   r   r   r   %  s)     / / /S#X /3 /r   c           
     s   \        \        V 4      4      p VP                  4       p\        R VP	                  4        4       4      pV FC  pV P                  RP                  V4      RP                  VP                  RR4      4      4      p KE  	  \        P                  ! V 4      pV \        VP                  4       4      9   d	   W,          # VP                  V4      # )zExpand variables on a string template

Args:
    string_template (str): template with variables preceded by $
    variables (dict): mapping of variable identifier > value

Return:
    str: String with substituted values
c              3   sN   "   T F  w  rVP                  R R4      V3x  K  	  R# 5i)r   r   N)r@   r8   r<   r   r=   Zsubstitute.<locals>.<genexpr>5  s$     L:K$!aiiS)1-:Ks   #%z${}r   r   )r   r   ZkeysZdictr   r@   r   stringZTemplateZlistZsafe_substitute)r   r   Zidentifiers
identifierZtemplates   &&   r   
substituter   %  s     (O(<=O.."K
 L)//:KLLI!
)11%,,z2JELLYcYkYkloqtYuLvw " /H$y~~/00))##I..r   c                4    V ^8  d   QhR\         R\         RR/# r   sourcedestinationr   Nr^   r   r   r   r   r   ?  s&     u u# uC uD ur   c           	     s.   \         P                  ! RW4       \        P                  P	                  V 4      p \        P
                  ! V 4       EF0  w  r#pV\        V 4      R P                  R4      p\        P                  P                  W4      pV FP  p\        P                  P                  Wg4      p\         P                  ! RV4        \        P                  ! V4       KR  	  V F  p	\        P                  P                  V4      '       g   \        P                  ! V4       \        P                  ! \        P                  P                  W)4      \        P                  P                  Wi4      RR7       K  	  EK3  	  R#   \         d     EK  i ; i)z+Merges the content of source to destinationzMerging %s into %sN/zcreating dir: %sF)Zfollow_symlinks)r   rH   r   rE   abspathwalkr`   rS   rI   ZmkdirrP   existsmakedirsr   Zcopy)
r   r   ZdirpathZdirnamesZ	filenamesZsource_relpathZdst_abspathdirnameZnew_dirr]   s
   &&        r   merge_foldersr   ?  s   
LL%v; WW__V$F(*$9 V/55c:ggll;?Gggll;8GLL+W5!	   "H77>>+..K(KKW7k9\nst	 " )8  s   FFFc                s    V ^8  d   QhR\         R\        \        P                  ,          R\        \        P                  ,          RR/# )r   rE   completion_functionerror_functionr   N)r   r   r   ZCompletionFunctionZErrorFunctionr   r   r   r   r   V  sL     ` `
`!+"@"@A` [667` 
	`r   c                s   \         P                  P                  V 4      '       g)   \        P                  ! RV 4       V'       d   V! 4        R# \         P                  P                  \         P                  P                  R4      V 4      '       d   V'       d   V! \        R4      4       R# \        P                  ! RV 4       \        V .WR7       R# )zTrashes a folder specified by path, asynchronously. The folder
likely exists after this returns, since it's using DBus to ask
for the entrashification.
Non existent path: %sN~z%Lutris tried to trash home directory!zTrashing folder %s)r   r   )
r   rE   r   r   ra   samefile
expanduserRuntimeErrorrH   r   )rE   r   r      &&&r   remove_folderr   V  s     77>>$.5!	ww**3/66<(OPQ
LL%t,,?_r   c                rw   r   rE   r   ry   r   r   r   r   r   m  s        r   c                s   \         P                  P                  V 4      '       g   \        P                  ! RV 4       R# \         P                  P                  \         P                  P                  R4      V 4      '       d   \        R4      h\        P                  ! RV 4        \        P                  ! V 4       R#   \         d8   p\        P                  ! RYP                  TP                  4        Rp?R# Rp?ii ; i)	zDelete a folder specified by path immediately. The folder will not
be recoverable, so consider remove_folder() instead.

Returns true if the folder was successfully deleted.
r   Fr   z%Lutris tried to erase home directory!zDeleting folder %sz.Failed to delete folder %s: %s (Error code %s)NT)r   rE   r   r   ra   r   r   r   rH   r   ZrmtreerP   rD   ZstrerrorZerrno)rE   rV   r   r   delete_folderr   m  s     77>>$.5	ww**3/66BCC
LL%t,d   Et[[Z\ZbZbcs   %B= =C?,C::C?c                r   r   r   r   r   r   r   r     s        r   c                s    V '       g   R# \         P                  P                  V 4      p \         P                  ! V RR7       V # )z"Creates a folder specified by pathNT)Zexist_ok)r   rE   r   r   rE   rz   r   create_folderr     s/    77d#DKKt$Kr   c                s\    V ^8  d   QhR\         \        ,          R\         \        ,          /# )r   foldersr   )r   r   r   r   r   r   r     s"        #  8C=  r   c                s    / pV  FB  p\         P                  ! V4      pVP                  : RVP                  : 2pWA9  g   K>  W!V&   KD  	  VP	                  4       # )z2Deduplicate directories with the same Device.InodeZ.)r   r~   Zst_devZst_inoZvalues)r   Zunique_dirsZfolderZfolder_statr   rf   r   list_unique_foldersr     sS    Kggfo + 2 2K4F4FG
(&,
#	 
 r   c                s^    V ^8  d   QhR\         R\        \         \         3,          R\        /# )r   rE   system_configr   )r   r   r)   r   r   r   r   r     s)     ! ! !DcN !t !r   c                s   \        V 4      '       g   R# V P                  R4      P                  R4      pV'       g   R# V^ ,          R8X  d#   \        V4      ^8  d   V^,          R9   d   R# R# V^ ,          R	9   d   R# V^ ,          R8X  d7   \        V4      ^8:  d   R# \        V4      ^8X  d   V^,          \        9   d   R# V'       d'   VP                  R4      p\        WRR7      '       d   R# R# )
zCheck if a folder is safe to remove (not system or home, ...). This needs the
system config dict so it can check the default game path, too.Fr   ZvarTZhomeZ	game_path)resolve_symlinks)ZmntZmedia)ZusrZlibZetcZbootZsbinZbin)rG   rS   r   r`   PROTECTED_HOME_FOLDERSgetpath_contains)rE   r   partsZdefault_game_paths   &&  r   is_removeabler     s     tJJsO!!#&EQx5 u:>eAh*::Qx??Qx6u:?u:?uQx+AA)--k:5IIr   c                r[   r   r^   r   r   r   r   r     s        r   c                sV   V '       d=   \         P                  P                  V 4      '       g   V P                  R4      '       g   V # V P	                  R4      P                  R4      pRpV F  pTp\         P                  P                  W#4      p\         P                  P                  V4      '       d   KK  \         P                  P                  V4      '       g   Kr   \         P                  ! V4      pV FH  pVP                  4       VP                  4       8X  g   K(  \         P                  P                  WF4      p K  	  K  	  \        V4      \        VP	                  R4      P                  R4      4      8X  d   V# V #   \         d    \        P                  ! RT4       . p Li ; i)zDo a case-insensitive check, return the real path with correct case. If the path is
not for a real file, this corrects as many components as do exist.r   zCan't read contents of %s)r   rE   r   r   rS   r   rI   isdirlistdirrP   r   rD   Zlowerr`   )rE   r   Zcurrent_pathZpartZparent_pathZpath_contentsr]   s   &      r   fix_path_caser     s1    277>>$''ts/C/CJJsO!!#&EL"ww||L7ww~~l++k0J0J# "

; 7 *>>#tzz|3#%77<<#FL *  5zS++C066s;<<K  #8+F "#s   F$F('F(c                r   r   )r   r	   r   r   r   r   r     s     % %c %c#h %r   c                sB   \         P                  P                  V 4      '       g"   \        P                  ! RV 4       \        4       # \        R4      pV'       g!   \        P                  ! R4       \        4       # \        W.RR7      p\        VP                  4       4      # )z'Return a set of pids using file `path`.z-Can't return PIDs using non existing file: %sZfuserz*fuser not available, please install psmiscTr&   )
r   rE   r   r   rD   Zsetr   ra   r.   r   )rE   Z
fuser_pathZfuser_outputr<   r   get_pids_using_filer     so    77>>$DdKu )JCDuJ-T:L|!!#$$r   c                r[   r   r^   r   r   r   r   r     s      S S r   c                s    V '       g   V # \         P                  P                  R4      pV P                  V4      '       d'   V \	        V4      R P                  R4      p RV ,           # V # )z0Replace '/home/username' with '~' in given path.r   Nr   z~/)r   rE   r   r   r`   rS   )rE   Z	user_pathr   r   reverse_expanduserr     sX    ""3'Iy!!C	N$%++C0d{Kr   c                st    V ^8  d   QhR\         \        ,          R\         \        ,          R\        R\        /# )r   parentchildr   r   )r   r   r)   r   r   r   r   r     s8     Z Z(3- Z ZQU Zbf Zr   c                s   V e   Vf   R# \        \        P                  P                  \        P                  P	                  V 4      4      4      p\        \        P                  P                  \        P                  P	                  V4      4      4      pV'       d!   VP                  4       pVP                  4       pWC8H  ;'       g    W4P                  9   # )zTests if a child path is actually within a parent directory
or a subdirectory of it. Resolves relative paths, and ~, and
optionally symlinks.F)r   r   rE   r   r   ZresolveZparents)r   r   r   Zresolved_parentZresolved_childs   &&&  r   r   r     s    
 ~277??277+=+=f+EFGO"''//"''*<*<U*CDEN)113'//1,YYCYCY0YYr   c                sH    V ^8  d   QhR\         R\        R\        R\        /# )r   rE   check_symlinksexclude_emptyr   ry   r   r   r   r   r     s)      c 4  Y] r   c                s   V '       g   R# V P                  R4      '       d    \        P                  P                  V 4      p \        P                  P	                  V 4      '       d.   V'       d$   \        P
                  ! V 4      P                  ^ 8  # R# \        P                  P                  V 4      '       d   \        P                  ! RV 4       V'       * # R# )a  Wrapper around system.path_exists that doesn't crash with empty values

Params:
    path (str): File to the file to check
    check_symlinks (bool): If the path is a broken symlink, return False
    exclude_empty (bool): If true, consider 0 bytes files as non existing
Fr   Tz%s is a broken link)
r   r   rE   r   r   r~   st_sizeislinkr   ra   )rE   r   r   r   r   rG   rG     s     sww!!$'	ww~~d774=((1,,	ww~~d,d3!!!r   c                r   r   r^   r   r   r   r   r     s&     
E 
E3 
ES 
ET 
Er   c                s   \         P                  P                  V 4      p\         P                  P                  V4      '       dS   \         P                  P	                  V4      '       g.   \
        P                  ! RV4       \         P                  ! V4        \         P                  ! WVR7       R#   \         d    \
        P                  ! RY4        R# i ; i)zCreate a symlink from source to destination.
If there is already a symlink at the destination and it is broken, it will be deleted.zDeleting broken symlink %s)Ztarget_is_directoryzFailed linking %s to %sN)r   rE   r   r   r   r   ra   ZremoveZsymlinkrP   rD   )r   r   Zis_directoryr   r   create_symlinkr     s     77==(L	ww~~k""277>>++F+F3[A
		+E


6LI E.DEs   B2 2"CCc                    V ^8  d   QhRR/# r   r   N r   r   r   r   r   $  s     N N Nr   c                 s    R F<  p \         P                  P                  V 4      '       g   K*   \         P                  V  K>  	  R#   \         d    \        P
                  ! RT 4        Kg  i ; i)z(Remove library preloads from environmentz(Failed to delete environment variable %sN)ZLD_LIBRARY_PATHZ
LD_PRELOAD)r   r   r   rP   r   rD   )r        r   reset_library_preloadsr   $  sR    0::>>#NJJsO 1  NGMNs   A"A+*A+c                r   r   r   r   r   r   r   r   .  s     6 6c 6hsm 6r   c                s    V R8X  d   R# \         P                  P                  V 4      '       d(   \         P                  P                  V 4      '       g   V # \	        \         P                  P                  V 4      4      # )zReturn the 1st existing parent for a folder (or itself if the path
exists and is a directory). returns None, when none of the parents exists.
r3   N)r   rE   r   isfileget_existing_parentr   r   rz   r   r   r   .  sP     rz	ww~~dBGGNN4$8$8rwwt455r   c                r   r   r   r   r   r   r   r   9  s     s sd sr   c                 s&   \        R4      '       d   \        RR\        P                  P	                  \
        P                  ! 4       R4      .RR7       \        RR\        P                  P	                  \        P                  R4      .RR7       R# R# )zlUpdate Icon for GTK+ desktop manager
Other desktop manager icon cache commands must be added here if needed
zgtk-update-icon-cachez-tfzicons/hicolorTr   N)	r   r.   r   rE   rI   r   Zget_user_data_dirr   ZRUNTIME_DIRr   r   r   update_desktop_iconsr   9  sj     233(%d>T>T>VXg1hiquv(%h>R>RTc1demqr 4r   c                rw   r   r   rY   r   r   r   r   r   B  s        r   c                sP  a R R lo\         P                  P                  V 4      '       d	   S! V 4      # ^ p\         P                  ! V 4       FP  w  r#pV Uu. uF"  p\         P                  P	                  W%4      NK$  	  ppV\        V3R lV 4       4      ,          pKR  	  V# u upi )z1Return the disk size in bytes of a file or folderc                rw   )r   	file_pathr   r   r   r   r   r   Z#get_disk_size.<locals>.__annotate__E  s     * * * *r   c                 sB    \         P                  ! V 4      P                  # r}   )r   r~   r   )r   rz   r   get_file_sizeZ$get_disk_size.<locals>.get_file_sizeE  s    wwy!)))r   c              3   s   <"   T F[  p\         P                  P                  V4      '       g   K*  \         P                  P                  V4      '       d   KQ  S! V4      x  K]  	  R # 5ir}   )r   rE   r   r   )r9   pr   s   & r   r=   Z get_disk_size.<locals>.<genexpr>N  sC     iEqRWW^^A=N*WYW^W^WeWefgWh*-**Es   'A&"A&A&)r   rE   r   r   rI   Zsum)rE   Z
total_sizeZbaseZ_dirsrd   ZfZpathsr   s   &      @r   get_disk_sizer   B  s    * 
ww~~dT""J ggdmU0561d&6ciEiii
 ,  7s   (B#c                :    V ^8  d   QhR\         \        ,          /# r   )r   r   r   r   r   r   r   R  s      c r   c                 s    \         P                  ! RR.\         P                  R7      ;_uu_ 4       p V P                  4       pRRR4       X^ ,          P	                  R4      P                  4       pV#   + '       g   i     L8; i  \         d5    \        P                  P                  RR4      pT'       d   T.p T# . p T# i ; i)z Return list of available localesZlocalez-a)r-   NZASCIIZLANGr3   )
rK   rL   rM   rO   Zdecoder   ZFileNotFoundErrorr   r   r   )Zlocale_getterZoutputZlocalesZlangs       r   get_locale_listr   R  s    	x.zGG="..0F H)""7+113 N HG  zz~~fb)fG N GNs4   0B A3.B 3B	>B 2C9C?CCc                r   r   )r   rY   r   r   r   r   r   a  s     C Cd3i Cr   c                 s    \         P                  ! R4       U u. uF,  q ^ ,          P                  4       '       g   K!  \        V 4      NK.  	  up # u up i )z8Return the list of PIDs from processes currently runningz/proc)r   r   ZisdigitrY   )r   r   r   get_running_pid_listr   a  s5    JJw/B/qQ4<<>FCF/BBBs
   AAc                sP    V ^8  d   QhR\         \        \        ,          ,          /# r   )r   r   r   r   r   r   r   r   f  s      4. r   c                 s   \         P                  P                  4       p . pV P                  4        F  pVP	                  4       pV'       g   K  VP                  R4      pV'       g(   \        P                  ! RVP                  4       4       K]  RV9   g
   RV9   g   Km  VP                  VP                  4       P                  4       4       K  	  V# )zCReturn a list of mounted discs and ISOs

:rtype: list of Gio.Mount
zunix-devicezNo device for mount %sz/dev/srz	/dev/loop)r   ZVolumeMonitorr   Z
get_mountsZ
get_volumeZget_identifierr   rH   Zget_nameZappendZget_rootZget_path)ZvolumesZdrivesZmountZvolumeZdevices        r   get_mounted_discsr   f  s    
 ##%GF##%!!#6**=9F5u~~7GH F"kV&;enn.779: & Mr   c                r[   r   r^   r   r   r   r   r   |  s      3 3 r   c                s    \         P                  P                  V 4      p \         P                  P                  V 4      '       g"   \         P                  P	                  V 4      p KF  V # )z+Return the mount point a file is located on)r   rE   r   Zismountr   r   rz   r   find_mount_pointr   |  s>    77??4 Dggood##wwt$Kr   c                r|   )r   layoutr   Nr^   r   r   r   r   r     s     " " " "r   c           	      s   R RRV R.pRR\         P                  P                  RR4      .p\        P                  ! V\        P
                  R7      ;_uu_ 4       p\        P                  ! V\         P                  VP                  R	7      ;_uu_ 4       pVP                  4        VP                  4        R
R
R
4       R
R
R
4       R
#   + '       g   i     L; i  + '       g   i     R
# ; i)	setxkbmapz-modelZpc101z-printxkbcompr   ZDISPLAYz:0)stdin)r$   r-   N)r   r   r   rK   rL   rM   r   rO   )r   Zsetxkbmap_commandZxkbcomp_commandr   r   rf   r   set_keyboard_layoutr     s    $hJ #rzz~~i'FGO			/	A	AW/RZZVVZc!!#! W 
B	AVV 
B	A	As$   :C!C	4CCCC*	)NNFFN)NNFFFN)NNFF)i   Nr3   )F)NN)FF)KZ__doc__ro   r   r   r   r~   r   rK   r_   r    r   Zpathlibr   Ztypingr   r   r   r   r   r   r   r	   r
   r   Zgi.repositoryr   r   Zlutrisr   Zlutris.exceptionsr   Zlutris.util.logr   Zlutris.util.portalsr   r   r!   r.   r1   r,   rW   rZ   rg   ri   rc   rv   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rG   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      sQ     	 	         [ [ [ #  4 " + kNkNiLjMhKjMjMgJ	 `2o002f(QV)
;
,: A/4u.`.( !H:%Z$,
EN6s C
,"r   