B =_0@s<dZddlZddlZddlZddlZddlmZddlmZddlm Z ddlm Z ddlm Z ddl m Z dd l mZdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%dd lm&Z&ddlZerd!d"Zd#d$Z'Gd%d&d&eZ(e e&)ed'e&)eoe d(Gd)d*d*e(Z*e&)ed+Gd,d-d-e*Z+Gd.d/d/e(Z,e-d0kr8dd1l.m/Z/e/e0dS)2a: 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)bind_unix_socket)chdir) CI_TESTING)copyload_shared_lib) create_exe) get_testfn)HAS_CONNECTIONS_UNIX) HAS_ENVIRON)HAS_MEMORY_MAPS)INVALID_UNICODE_SUFFIX)PsutilTestCase)PYPY) safe_mkdir) safe_rmpath) serialrun)skip_on_access_denied)spawn_testproc) terminate) TESTFN_PREFIX)UNICODE_SUFFIX)unittestcCs6ddlm}y||Stk r0tYnXdS)Nr)r) psutil.testsrZ WindowsError traceback print_exc)pathZrmr$L/opt/alt/python37/lib64/python3.7/site-packages/psutil/tests/test_unicode.pyrss rc Csd}t|d}z^yrE assertEqualrBr#normcase)r1subpprIr$r$r% test_proc_exes  zTestFSAPIs.test_proc_execCsN|j|jgd}t|j}||t|rJ| |t j |jdS)N)r') rr7rFrGrHnamerJr>rErKrBr#basename)r1rMrPr$r$r%test_proc_names  zTestFSAPIs.test_proc_namecCsZ|j|jgd}t|j}|}x|D]}||tq*W|rV| ||jgdS)N)r') rr7rFrGrHcmdlinerJr>rErK)r1rMrNrSpartr$r$r%test_proc_cmdlines  zTestFSAPIs.test_proc_cmdlinec Csj|jd}|t|t|t|t}|}WdQRX||t | rf| ||dS)N2) r7 addCleanuprrr rFrGcwdrJr>rErK)r1dnamerNrXr$r$r% test_proc_cwds   zTestFSAPIs.test_proc_cwdzfails on PYPY + WINDOWSc Cst}t|}t|jdt|}WdQRX||j}||t t rd|sd| dS| r| tj|tj|jdS)Nrbzopen_files on BSD is broken)rFrGsetZ open_filesopenr7popr#rJr>rr0rErKrBrL)r1rNstartnewr#r$r$r%test_proc_open_filess   zTestFSAPIs.test_proc_open_filesz POSIX onlyc Cs|j|jd}y t|}Wn&tk r@tr2n tdYnXt|8t dd}| |j t ts~||j |WdQRXdS)N)r&z not supportedunixr)rr/r r*rrSkipTestrrFrGZ connectionsrJladdrr>rrK)r1rPsockconnr$r$r%test_proc_connectionss  z TestFSAPIs.test_proc_connectionszcan't list UNIX socketsc Csdd}|j|jd}y t|}Wn&tk rHtr:n tdYnXt|:tj dd}t s||}| |j t ||j |WdQRXdS)NcSs2x$|D]}tj|jtr|SqWtddS)Nzconnection not found)rBr#rQrd startswithr ValueError)consrfr$r$r% find_sock s z2TestFSAPIs.test_net_connections..find_sock)r&z not supportedrb)kind)rr/r r*rrrcrrFZnet_connectionsrrJrdr>rK)r1rkrPrerjrfr$r$r%test_net_connectionss   zTestFSAPIs.test_net_connectionscCs,|jd}|t|t|t|dS)NrV)r7rWrrrF disk_usage)r1rYr$r$r%test_disk_usage"s  zTestFSAPIs.test_disk_usagez not supportedz&ctypes does not support unicode on PY2zunstable on PYPYc svt|jd`}ddfddtD}dd|D}|||x|D]}||tqTWWdQRXdS)N)r&cSstjtj|S)N)rBr#realpathrL)rNr$r$r%normpath/sz-TestFSAPIs.test_memory_maps..normpathcsg|]}|jqSr$)r#).0x)rqr$r% 1sz/TestFSAPIs.test_memory_maps..cSsg|]}t|kr|qSr$)r)rrrsr$r$r%rt4s)rr/rFrGZ memory_mapsZassertInrJr>)r1Z funky_pathZlibpathsr#r$)rqr%test_memory_maps(s  zTestFSAPIs.test_memory_mapsN)r3r4r5__doc__rr/ classmethodr9r:rErOrRrUrZrskipIfrrrarrgrrrmrorrrur$r$r$r%r6s$          r6zunreliable on CIc@s eZdZdZeZeddZdS)TestFSAPIsWithInvalidPathz-Test FS APIs with a funky, invalid path name.cCsdS)NTr$)r8r$r$r%rE?sz1TestFSAPIsWithInvalidPath.expect_exact_path_matchN)r3r4r5rvrr/rwrEr$r$r$r%ry:sryc@sBeZdZdZerendZee dee o.e dddZ dS) TestNonFSAPISz&Unicode tests for non fs-related APIs.èz not supportedzsegfaults on PYPY + WINDOWScCsxtj}|j|d<|j|d}t|j}|}x,|D] \}}| |t | |t q>W| |d|jdS)NZ FUNNY_ARG)env) rBenvironcopyr/rrFrGrHitemsrJr>rK)r1r|r,rNkvr$r$r%test_proc_environNs     zTestNonFSAPIS.test_proc_environN) r3r4r5rvrrr/rrxrrrrr$r$r$r%rzJs  rz__main__) run_from_name)1rvrBr(r!r? contextlibrrFrrrrZpsutil._compatrrr r r r r r rrrrrrrrrrrrrrrrrrr-r.rxr6ryrzr3Zpsutil.tests.runnerr__file__r$r$r$r%Jsd