
    G@d@$                         d Z ddlZddlZddlZddlmZ ddlZddlZddl	Z	ddl
Z
ddlmZ  ej        e          Zd Zd Zd Zd Zd 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S )zMiscellaneous utilities    N)get_home_dirc                     t          j        |           d         dk    r3dD ]2}t          j        | |z             rt          j        | |z              1dS dS )zCEventually remove .pyc and .pyo files associated to a Python script   .py)coN)ospsplitextexistsosremove)fnameendings     1lib/python3.11/site-packages/spyder/utils/misc.py__remove_pyc_pyor      sh    
|E1&&  	* 	*Fz%&.)) *	%&.))) '&	* 	*    c                 N    t          j        | |           t          |            dS )zt
    Rename file from *source* to *dest*
    If file is a Python script, also rename .pyc and .pyo files if any
    N)r   renamer   )sourcedests     r   rename_filer       s*    
 IfdVr   c                 L    t          j        |            t          |            dS )zd
    Remove file *fname*
    If file is a Python script, also rename .pyc and .pyo files if any
    N)r   r   r   r   s    r   remove_filer   )   s(    
 IeUr   c                 X    ddl }|                    | |           t          |            dS )zr
    Move file from *source* to *dest*
    If file is a Python script, also rename .pyc and .pyo files if any
    r   N)shutilcopyr   )r   r   r   s      r   	move_filer   2   s5    
 MMM
KKr   c                     t          j        |t           j                  s,t          j        |t          j                    | |           dS  )a  Error handler for `shutil.rmtree`.

    If the error is due to an access error (read-only file), it
    attempts to add write permission and then retries.
    If the error is for another reason, it re-raises the error.

    Usage: `shutil.rmtree(path, onerror=onerror)N)r   accessW_OKchmodstatS_IWUSR)functionpathexcinfos      r   onerrorr(   <   sB     9T27## 
t|$$$r   N  c                 R   ddl }	 	  |j         |j        |j        |j                  }|                    d| f           	 |                                 d}nP# |j        $ r}| dz  } Y d}~nd}~ww xY w	 |                                 d}n# |                                 d}w xY w| S )zFind and return a non used portr   NTz	127.0.0.1r   )socketAF_INETSOCK_STREAMIPPROTO_TCPbindcloseerror)default_portr+   sock_msgs       r   select_portr5   L   s    MMM	 6=!'!3!'!35 5D II{L1222 JJLLLDD | 	 	 	ALLLLLL	 JJLLLDD JJLLLDKKKK s)   8A 
A0!A+&B +A00B B#c                    g d|g d}fd}d}d}t          j        |           rt          j        |           D ]t\  }}}|dd         D ]}	|	|v r|                    |	           |t          j        |          |vr0|D ]-}
 |t          j        ||
                    \  }}||z  }||z  }.un ||           \  }}||z  }||z  }||fS )zReturn number of source code lines for all filenames in subdirectories
    of *path* with names ending with *extensions*
    Directory names *excluded_dirnames* will be ignoredN)r   .pyw.ipyz.enamlz.cz.hz.cppz.hppz.inc.z.hhz.hxxz.ccz.cxxz.clz.fz.forz.f77z.f90z.f95z.f2kz.f03z.f08)builddistz.hgz.svnc                 ,   d\  }}t          j        |           d         v rod}t          | d          5 }t          |                                                                                                          }d d d            n# 1 swxY w Y   ||fS )N)r   r   r   rb)r	   r
   openlenreadstrip
splitlines)r&   dfilesdlinestextfile
extensionss       r   get_filelinesz"count_lines.<locals>.get_filelinesl   s    <a J..FdD!! CXX]]__2244??AABBC C C C C C C C C C C C C C Cv~s   ABBBr   )r	   isdirr   walkr   dirnamejoin)r&   rF   excluded_dirnamesrG   linesfilesdirpathdirnames	filenamesdr   rC   rD   s    `           r   count_linesrS   `   sN    & & &
  <<<     EE
y ,.GDMM 		$ 		$(GXyaaa[ ' ')))OOA&&& ({7##+<<<& $ $E%2]38GU3K3K%L%LNFFVOEVOEE		$ 't,,%<r   c                     t           j        dk    r`|                     d          r|                     d          s
| dd         } |                     dd          } |                     dd          } | S )	av  Remove backslashes in *path*

    For Windows platforms only.
    Returns the path unchanged on other platforms.

    This is especially useful when formatting path strings on
    Windows platforms for which folder paths may contain backslashes
    and provoke unicode decoding errors in Python 3 (or in Python 2
    when future 'unicode_literals' symbol has been imported).nt\z\\N/z/'z\')r   nameendswithreplacer&   s    r   remove_backslashesr]      sn     
w$== 	t}}V'<'< 	9D||D#&&||E6**Kr   c                 j    t          j        d|           }||S t          j        d|           }||S dS )z&Check if text contains a Python error.z  File "(.*)", line (\d*)Nz  File (.*):(\d*)F)rematch)textmatch_pythonipython8_matchs      r   get_error_matchrd      sG     88$??L X2D99N!5r   c                  t    t           j                            dd          } |                     d          rd} | S )z'Return path to Spyder Python executablezpythonw.exez
python.exez
spyder.exe)sys
executabler[   rZ   )rg   s    r   get_python_executablerh      s:    ''|DDJ<(( "!
r   c                       fd}|S )aB  
    Add the decorated method to the given class; replace as needed.

    If the named method already exists on the given class, it will
    be replaced, and a reference to the old method is created as
    cls._old<patch_name><name>. If the "_old_<patch_name>_<name>" attribute
    already exists, KeyError is raised.
    c                     | j         }t          |d           }|Gdd|}t          |d           }|t          ||           nt          j         d|d          t          ||            | S )N_old__r9   z already exists.)__name__getattrsetattrKeyError)funcr   old_funcold_refold_attrcls
patch_names        r   	decoratorz%monkeypatch_method.<locals>.decorator   s    3t,,&0jj%%8GsGT22HWh////"%,,, 9 : : :UD!!!r    )ru   rv   rw   s   `` r   monkeypatch_methodry      s*          r   c                 T    t          j        |           o|                     d          S )zIs it a valid Python script?)r   r7   r8   )r	   isfilerZ   r   s    r   is_python_scriptr|      s$    :eH0G!H!HHr   c                 d    t          j        t          j        | t          j                            S )zReturn absolute parent dir)r	   abspathrK   r   pardirr\   s    r   	abspardirr      s     ;sxbi00111r   c           
         t          j        t          j        |                     }t          |          dk    rt          j        |          st          |          S | D ]R}t          j        t          j        ||t          |          dz   d                             st          |          c S St          j        |          S dS )z,Return common path for all paths in pathlistr   N)r	   normpathcommonprefixr?   rH   r   rK   r~   )pathlistcommonr&   s      r   get_common_pathr      s    \#*84455F
6{{Qy   	+V$$$  + +y&$s6{{Q7G7G2H!I!IJJ -$V,,,,,- {6*** r   c                 \     i x _         t          j                    fd            }|S )z
    Memoize objects to trade memory for execution speed

    Use a limited size cache to store the value, which takes into account
    The calling args and kwargs

    See https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
    c                      t          |           t          |          z   }|vr | i ||<   t                    dk    r                    d           |         S )Nd   F)last)strr?   popitem)argskwargskeycacheobjs      r   memoizerzmemoize.<locals>.memoizer   sk    $ii#f++%ed-f--E#Ju::MMuM%%%Szr   )r   	functoolswraps)r   r   r   s   ` @r   memoizer      sL     ECI_S      Or   c                      	 t          j                    S # t          $ r+ t                              d           t                      cY S w xY w)zSafe version of getcwd that will fallback to home user dir.

    This will catch the error raised when the current working directory
    was removed for an external program.
    zNWARNING: Current working directory was deleted, falling back to home dirertory)r   getcwdOSErrorloggerdebugr   rx   r   r   getcwd_or_homer     sY    y{{    6 	7 	7 	7~~s    2A
	A
c                     	 t          j        |            n+# t           j        $ r}t          |          cY d}~S d}~ww xY wdS )zy
    Return None if the pattern is a valid regular expression or
    a string describing why the pattern is invalid.
    N)r_   compiler1   r   )patternes     r   regexp_error_msgr     sU    


78   1vv4s    ?:??c                 Z   t          j                     }|                    d           t                              d                    | |                     	 |                    | |f           t                              d                    | |                     	 |                                 dS # t           j        $ rN}t                              d                    | ||                     Y d}~|                                 dS d}~ww xY w# |                                 w xY w)z+Verify if `port` is available in `address`.   z&Attempting to connect to {} on port {}zConnected to {} on port {}Tz&Connection to {} on port {} failed: {}NF)r+   
settimeoutr   r   formatconnectr0   r1   )addressportsr   s       r   check_connection_portr     s"    	ALLOOO
LL9@@$    ! ! !				7D/"""188$GGHHH 	
					 <   =DDdA' ' 	( 	( 	(uuu						
 	
				s+   AB4 4D/D2D DD D*)r)   )NN)"__doc__r   loggingr   os.pathr&   r	   r_   rf   r#   r+   spyder.config.baser   	getLoggerrm   r   r   r   r   r   r(   r5   rS   r]   rd   rh   ry   r|   r   r   r   r   r   r   rx   r   r   <module>r      s          				       				 



   + + + + + + 
	8	$	$* * *            ($ $ $ $N  (       >I I I
2 2 2
+ + +  .  	 	 	    r   