
    ɧd0                        d 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ZddlmZ ddlm	Z	 ddlm
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddlm!Z! ddlm"Z" ddlm#Z# ddlm$Z$ ddlm%Z% dd lm&Z& erd! Z!d" Z' G d# d$e          Z(e" e&j)        ed%           e&j)        eoe d&           G d' d(e(                                              Z* e&j)        ed)           G d* d+e*                      Z+ G d, d-e(          Z,e-d.k    rdd/l.m/Z/  e/e0           dS dS )0a:	  
Notes about unicode handling in psutil
======================================

Starting from version 5.3.0 psutil adds unicode support, see:
https://github.com/giampaolo/psutil/issues/1040
The notes below apply to *any* API returning a string such as
process exe(), cwd() or username():

* all strings are encoded by using the OS filesystem encoding
  (sys.getfilesystemencoding()) which varies depending on the platform
  (e.g. "UTF-8" on macOS, "mbcs" on Win)
* no API call is supposed to crash with UnicodeDecodeError
* instead, in case of badly encoded data returned by the OS, the
  following error handlers are used to replace the corrupted characters in
  the string:
    * Python 3: sys.getfilesystemencodeerrors() (PY 3.6+) or
      "surrogatescape" on POSIX and "replace" on Windows
    * Python 2: "replace"
* on Python 2 all APIs return bytes (str type), never unicode
* on Python 2, you can go back to unicode by doing:

    >>> unicode(p.exe(), sys.getdefaultencoding(), errors="replace")

For a detailed explanation of how psutil handles unicode see #1040.

Tests
=====

List of APIs returning or dealing with a string:
('not tested' means they are not tested to deal with non-ASCII strings):

* Process.cmdline()
* Process.connections('unix')
* Process.cwd()
* Process.environ()
* Process.exe()
* Process.memory_maps()
* Process.name()
* Process.open_files()
* Process.username()             (not tested)

* disk_io_counters()             (not tested)
* disk_partitions()              (not tested)
* disk_usage(str)
* net_connections('unix')
* net_if_addrs()                 (not tested)
* net_if_stats()                 (not tested)
* net_io_counters()              (not tested)
* sensors_fans()                 (not tested)
* sensors_temperatures()         (not tested)
* users()                        (not tested)

* WindowsService.binpath()       (not tested)
* WindowsService.description()   (not tested)
* WindowsService.display_name()  (not tested)
* WindowsService.name()          (not tested)
* WindowsService.status()        (not tested)
* WindowsService.username()      (not tested)

In here we create a unicode path with a funky non-ASCII name and (where
possible) make psutil return it back (e.g. on name(), exe(), open_files(),
etc.) and make sure that:

* psutil never crashes with UnicodeDecodeError
* the returned path matches
    N)closing)BSD)OPENBSD)POSIX)WINDOWS)PY3)u)APPVEYOR)ASCII_FS)
CI_TESTING)HAS_CONNECTIONS_UNIX)HAS_ENVIRON)HAS_MEMORY_MAPS)INVALID_UNICODE_SUFFIX)PYPYTESTFN_PREFIX)UNICODE_SUFFIX)PsutilTestCase)bind_unix_socket)chdir)copyload_shared_lib)
create_exe)
get_testfn)
safe_mkdirsafe_rmpath)	serialrun)skip_on_access_denied)spawn_testproc)	terminate)unittestc                 n    ddl m} 	  ||           S # t          $ r t          j                     Y d S w xY w)Nr   r   )psutil.testsr   WindowsError	traceback	print_exc)pathrms     9lib/python3.11/site-packages/psutil/tests/test_unicode.pyr   r   s   s[     	322222	"2d88O 	" 	" 	"!!!!!!	"s   
 44c                    d}t          |           }	 t          |           t          |           t          |g          }t	          j        ||dz              t          |dz              	 |t          |           t          |           dS # t          t          f$ r$ Y |t          |           t          |           dS w xY w# |t          |           t          |           w xY w)z`Return True if both the fs and the subprocess module can
    deal with a unicode file name.
    Nsuffixcmdz-2TF)	r   r   r   r    shutilcopyfiler!   UnicodeEncodeErrorIOError)r-   sproctestfns      r*   try_unicoder6      s!    Ev&&&FF6F8,,,...FTM"""  	eF (     	eF
  	eFs$   AB C!C CC "C*c                       e Zd ZdZd ZdS )BaseUnicodeTestNc                 j    | j         )t          | j                   s|                     d          d S d S )Nzcan't handle unicode str)funky_suffixr6   skipTest)selfs    r*   setUpzBaseUnicodeTest.setUp   sM     	@t011 @mm$>???	@ 	@@ @    )__name__
__module____qualname__r:   r=    r>   r*   r8   r8      s-        L@ @ @ @ @r>   r8   zASCII fsztoo much trouble on PYPY2c                      e Zd ZdZeZed             Zed             Zd Z	d Z
d Zd Zd Z ej        eoed	          d
             Z ej        e d          d             Z ej        e d           ej        e d           e            d                                     Zd Z ej        e d           ej        e d           ej        ed          d                                     ZdS )
TestFSAPIsz1Test FS APIs with a funky, valid, UTF8 path name.c                 b    t          | j                  | _        t          | j                   d S )Nr,   )r   r:   
funky_namer   clss    r*   
setUpClasszTestFSAPIs.setUpClass   s-    #3+;<<<3>"""""r>   c                 .    t          | j                   d S N)r   rF   rG   s    r*   tearDownClasszTestFSAPIs.tearDownClass   s    CN#####r>   c                    t          | j        t                    rdnt          d          }t	          j                    5  t	          j        d           | j        t          j        |          v cd d d            S # 1 swxY w Y   d S )N.ignore)	
isinstancerF   strr	   warningscatch_warningssimplefilteroslistdir)r<   heres     r*   expect_exact_path_matchz"TestFSAPIs.expect_exact_path_match   s     !#66BssAcFF$&& 	7 	7!(+++?bj&6&66	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7 	7s   /A;;A?A?c                    |                      | j        g          }t          j        |j                  }|                                }|                     |t                     |                                 rW| 	                    t          j                            |          t          j                            | j                             d S d S Nr.   )r    rF   psutilProcesspidexeassertIsInstancerQ   rX   assertEqualrU   r(   normcase)r<   subppr^   s       r*   test_proc_exezTestFSAPIs.test_proc_exe   s    ""'8"99N48$$eeggc3''''')) 	@RW--c22W--do>>@ @ @ @ @	@ 	@r>   c                 f   |                      | j        g          }t          j        |j                                                  }|                     |t                     |                                 r:| 	                    |t          j                            | j                             d S d S rZ   )r    rF   r[   r\   r]   namer_   rQ   rX   r`   rU   r(   basename)r<   rb   rf   s      r*   test_proc_namezTestFSAPIs.test_proc_name   s    ""'8"99~dh'',,..dC((('')) 	FT27#3#3DO#D#DEEEEE	F 	Fr>   c                 <   |                      | j        g          }t          j        |j                  }|                                }|D ]}|                     |t                     |                                 r| 	                    || j        g           d S d S rZ   )
r    rF   r[   r\   r]   cmdliner_   rQ   rX   r`   )r<   rb   rc   rj   parts        r*   test_proc_cmdlinezTestFSAPIs.test_proc_cmdline   s    ""'8"99N48$$))++ 	- 	-D!!$,,,,'')) 	9Wt&788888	9 	9r>   c                    | j         dz   }|                     t          |           t          |           t	          |          5  t          j                    }|                                }d d d            n# 1 swxY w Y   |                     |                                t                     | 
                                r|                     ||           d S d S N2)rF   
addCleanupr   r   r   r[   r\   cwdr_   rQ   rX   r`   )r<   dnamerc   rq   s       r*   test_proc_cwdzTestFSAPIs.test_proc_cwd   s   #%U+++55\\ 	 	  A%%''C	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	aeeggs+++'')) 	)S%(((((	) 	)s   (A88A<?A<zfails on PYPY + WINDOWSc                    t          j                    }t          |                                          }t	          | j        d          5  t          |                                          }d d d            n# 1 swxY w Y   ||z
                                  j        }|                     |t                     t          r|s|                     d          S |                                 rW|                     t          j                            |          t          j                            | j                             d S d S )Nrbzopen_files on BSD is broken)r[   r\   set
open_filesopenrF   popr(   r_   rQ   r   r;   rX   r`   rU   ra   )r<   rc   startnewr(   s        r*   test_proc_open_fileszTestFSAPIs.test_proc_open_files   sa   NALLNN##$/4(( 	& 	&allnn%%C	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	&e  ""'dC((( 	@t 	@==!>???'')) 	@RW--d33W--do>>@ @ @ @ @	@ 	@s   
"A88A<?A<z
POSIX onlyc                    |                      | j                  }	 t          |          }n*# t          $ r t          r t          j        d          w xY wt          |          5  t          j	                    
                    d          d         }|                     |j        t                     t          s|                     |j        |           d d d            d S # 1 swxY w Y   d S )Nr,   not supportedunixr   )r   r:   r   r2   r   r"   SkipTestr   r[   r\   connectionsr_   laddrrQ   r   r`   )r<   rf   sockconns       r*   test_proc_connectionsz TestFSAPIs.test_proc_connections   s-   d&788	9#D))DD! 	9 	9 	9 9'888		9
 T]] 	3 	3>##//77:D!!$*c222 3  T222	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3s   - 'A&A/C""C&)C&zcan't list UNIX socketsc                    d }|                      | j                  }	 t          |          }n*# t          $ r t          r t          j        d          w xY wt          |          5  t          j	        d          }t          sF ||          }|                     |j        t                     |                     |j        |           d d d            d S # 1 swxY w Y   d S )Nc                     | D ]B}t           j                            |j                                      t
                    r|c S Ct          d          )Nzconnection not found)rU   r(   rg   r   
startswithr   
ValueError)consr   s     r*   	find_sockz2TestFSAPIs.test_net_connections.<locals>.find_sock  sV        7##DJ//::=II  KKK 3444r>   r,   r~   r   )kind)r   r:   r   r2   r   r"   r   r   r[   net_connectionsr   r_   r   rQ   r`   )r<   r   rf   r   r   r   s         r*   test_net_connectionszTestFSAPIs.test_net_connections  s>   	5 	5 	5 d&788	9#D))DD! 	9 	9 	9 9'888		9
 T]] 	3 	3)v666D 3 y%%dj#666  T222	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3 	3s   0 'A)A#CC Cc                     | j         dz   }|                     t          |           t          |           t	          j        |           d S rn   )rF   rp   r   r   r[   
disk_usage)r<   rr   s     r*   test_disk_usagezTestFSAPIs.test_disk_usage"  sG    #%U+++5%     r>   r~   z&ctypes does not support unicode on PY2zunstable on PYPYc                 d   t          | j                  5 }d fdt          j                                                    D             }d |D             }|                      |          |           |D ]}|                     |t                     	 d d d            d S # 1 swxY w Y   d S )Nr,   c                 z    t           j                            t           j                            |                     S rK   )rU   r(   realpathra   )rc   s    r*   normpathz-TestFSAPIs.test_memory_maps.<locals>.normpath/  s(    w''(8(8(;(;<<<r>   c                 0    g | ]} |j                   S rB   )r(   ).0xr   s     r*   
<listcomp>z/TestFSAPIs.test_memory_maps.<locals>.<listcomp>1  s;     A A A !(( A A Ar>   c                 $    g | ]}t           |v |S rB   r   )r   r   s     r*   r   z/TestFSAPIs.test_memory_maps.<locals>.<listcomp>4  s"    BBBa}/ABBBBr>   )r   r:   r[   r\   memory_mapsassertInr_   rQ   )r<   
funky_pathlibpathsr(   r   s       @r*   test_memory_mapszTestFSAPIs.test_memory_maps(  s-    !(9::: 		1j= = =A A A A!'!1!1!=!=!?!?A A AH CB8BBBHMM((:..999  1 1%%dC00001		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1 		1s   B B%%B),B)N)r?   r@   rA   __doc__r   r:   classmethodrI   rL   rX   rd   rh   rl   rs   r"   skipIfr   r   r|   r   r   r   r   r   r   r   r   r   rB   r>   r*   rD   rD      s        <;!L# # [# $ $ [$7 7 7@ @ @F F F9 9 9	) 	) 	) X_T%g'@AA@ @ BA@ X_Y--3 3 .-3  X_Y--X_--/HII3 3  JI .-3.! ! ! X_(/::X_WFGGX_T-..1 1 /. HG ;:1 1 1r>   rD   zunreliable on CIc                   ,    e Zd ZdZeZed             ZdS )TestFSAPIsWithInvalidPathz-Test FS APIs with a funky, invalid path name.c                     dS )NTrB   rG   s    r*   rX   z1TestFSAPIsWithInvalidPath.expect_exact_path_match?  s	     tr>   N)r?   r@   rA   r   r   r:   r   rX   rB   r>   r*   r   r   :  s8        77)L  [  r>   r   c                       e Zd ZdZerendZ ej        e	 d           ej        e
oed          d                         ZdS )TestNonFSAPISz&Unicode tests for non fs-related APIs.   èr~   zsegfaults on PYPY + WINDOWSc                    t           j                                        }| j        |d<   |                     |          }t          j        |j                  }|                                }|                                D ];\  }}| 	                    |t                     | 	                    |t                     <|                     |d         | j                   d S )N	FUNNY_ARG)env)rU   environcopyr:   r    r[   r\   r]   itemsr_   rQ   r`   )r<   r   r4   rc   kvs         r*   test_proc_environzTestNonFSAPIS.test_proc_environN  s     joo,K###,,N59%%iikkIIKK 	* 	*DAq!!!S)))!!!S))))[)4+<=====r>   N)r?   r@   rA   r   r   r   r:   r"   r   r   r   r   r   rB   r>   r*   r   r   J  sr        00%(2>>dLX__o66X_T%g'DEE> > FE 76> > >r>   r   __main__)run_from_name)1r   rU   r0   r&   rR   
contextlibr   r[   r   r   r   r   psutil._compatr   r	   r$   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r6   r8   r   rD   r   r   r?   psutil.tests.runnerr   __file__rB   r>   r*   <module>r      s  B BH 
			                                                  ! ! ! ! ! ! ! ! ! ! ! ! # # # # # # - - - - - - $ $ $ $ $ $ ( ( ( ( ( ( / / / / / /       & & & & & & ' ' ' ' ' ' ' ' ' ' ' ' ) ) ) ) ) )       , , , , , , # # # # # # # # # # # # # # # # # # $ $ $ $ $ $ " " " " " " . . . . . . ' ' ' ' ' ' " " " " " " ! ! ! ! ! !  "" " "$  6@ @ @ @ @n @ @ @ :&&!c'#>??K1 K1 K1 K1 K1 K1 K1 @? '& K1\ /00    
   10> > > > >O > > >. z 111111M( r>   