HEX
Server: LiteSpeed
System: Linux atali.colombiahosting.com.co 5.14.0-570.12.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 13 06:11:55 EDT 2025 x86_64
User: coopserp (1713)
PHP: 8.2.29
Disabled: dl,exec,passthru,proc_open,proc_close,shell_exec,memory_limit,system,popen,curl_multi_exec,show_source,symlink,link,leak,listen,diskfreespace,tmpfile,ignore_user_abord,highlight_file,source,show_source,fpaththru,virtual,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,posix_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setid,posix_times,posix_ttyname,posix_uname,proc_get_status,proc_nice,proc_terminate
Upload Files
File: //proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/site-packages.zip
PKok\%M�mm(netifaces.cpython-39-x86_64-linux-gnu.sonuȯ��ELF>�@H�@8@$!�5�5 �5�5 �5 �� 66 6 �����$$P�td444<<Q�tdGNUr���N�m��f�4�/�^(>�5��(	@	57:BE���|�f?��qX������	��u.�� ��J+x�w��;q�j�� �C�X��Y�~�#f���a �k8 R"�_�: �: ��&=�: 	�0.__gmon_start___init_fini_ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalize_Jv_RegisterClassesPyList_NewgetifaddrsstrncmpPyUnicode_FromStringPySequence_ContainsPyList_Append_Py_DeallocfreeifaddrsPyExc_OSErrorPyErr_SetFromErrnogetnameinfosprintfgetpagesizePyDict_NewPyDict_SetItemStringPyDict_GetItemStringmallocsocketbindgetsocknamesendtorecvmsgmemcmpif_indextonameinet_ntop_Py_FalseStructPyTuple_PackPyObject_IsTruePyObject_SizePyLong_FromLongPyDict_SetItemfreeclose__errno_location_Py_TrueStructPyErr_SetStringPyDict_GetItemPyErr_NoMemoryPyArg_ParseTuplestrcmpmemcpyPyExc_ValueErrorPyInit_netifacesPyModule_Create2PyModule_AddIntConstantPyModule_AddObjectPyModule_AddStringConstantlibpthread.so.0libc.so.6_edata__bss_start_endGLIBC_2.2.5GLIBC_2.3� ui	#ii
/ui	#�5 P�5 6 6 �9 �/�9  :  : �/(: @ 8: 0@: �/H: �X: 1`: �/h: �x: P1�7 	�7 �7 �7 8 8 $8 ,8 1 8 2@8 H8 P8 X8 `8 h8 p8 x8 
�8 �8 �8 
�8 �8 �8 �8 �8 �8 �8 �8 �8 �8 �8 �8 �8 9 9  9 !9 " 9 #(9 %09 &89 '@9 (H9 )P9 *X9 +`9 -h9 .p9 /x9 0�9 2�9 3�9 4H����H����5j& �%l& @�%j& h����%b& h�����%Z& h����%R& h����%J& h����%B& h����%:& h����%2& h�p����%*& h�`����%"& h	�P����%& h
�@����%& h�0����%
& h� ����%& h
�����%�% h�����%�% h���%�% h����%�% h�����%�% h����%�% h����%�% h����%�% h����%�% h����%�% h�p����%�% h�`����%�% h�P����%�% h�@����%�% h�0����%�% h� ����%�% h�����%z% h�����%r% h���%j% h ����%b% h!�����%Z% h"����%R% h#����%J% h$����%B% h%����%:% h&����%2% h'�p����%*% h(�`����%"% h)�P����%% h*�@���H��H�u# H��t��H���f�H�& H�=�% UH)�H��H��w]�H�# H��t�]��@H��% H�=�% UH)�H��H��H��H��?H�H�u]�H�# H��t�]H���@�=�% u'H�=�" UH��tH�=�  �����h���]�`% ��fffff.�H�=�  t&H��" H��tUH�=�  H���]�W�����K���f.��AU1�ATUSH��H�$�7���H��I���������H�$H����E1��f�H�mtZL�cH�H��t]H�kH��t�M��t�L��H���/�����t�H������L��H��H���e�����u�H��L������H�mu�H�������DH�<$�g���L��H��[]A\A]�1���I�muL�����H�! H�8����1���AVAUATUH��SH��H�����f������
I�����w
H��4�E1�E1��$�L��H��������tx�EA��Ѓ�
��wH�
�Lc$�I��f��H�]tcO�4dI��wfM��A�E�����t:I�L���H�5H��1�H��H����L9�u�C�D5�1�A�}����H��[]A\A]A^�D�eH�]�D�������f�AWAVAUATU� SH�����H��$�= �N�H�����H���H�����I��H�D$(����H�5^H��H��L�����H�+�qH�|$(H�5:����H�D$XHc�H��H�D$�*���H��I���C1Ҿ��-������$�zH�\$p��Ǻf�L$p�D$xH���D$t�T������8�<$H�T$`H���D$`�������<$�L�Q�fA�T$1�A��L��I�D$A�D$A�$fA�D$A�D$A�D$���H����H��$�E1�H�D$H��$�H�D$H��$�H�D$ H��$�H�D$PH��$�H�D$HfDH�D$H�t$ 1ҋ<$L��$�DŽ$�HDŽ$�H��$�H�D$HDŽ$�HDŽ$�DŽ$�H��$�H�D$H��$�������$� ��H���:����A�,$����9�A����L���.A�B��A)�H�A�����+����D9����{A��űD$t9Cu�D�k�CA��f��E���af�����M�H�S��~��Cf��v�9�|�A�����E1�1�E���3@f��tZf��uD�B����)�H�Hƒ�~N�f��vE9�A�rf��tw�L�Rf��ID����D�J�f.�L�z�f.�H��tM�C<��<
A�����H�5��D�D$8D�L$0�l$D�����D�L$0D�D$8D�T$D�����D��A����M����!Є������H�t$PD��D�D$0����H��H����{H�T$H�L������H�����{�D�D$0��L�=( �C< w)����E���DHǃ��t	D9���D����H������H�|$HH������L��H��H��H�D$8�1��0���L��H�D$0E1��0�����L�L$8��I�)�wH�m�_H�|$0H��t�C������H���zM��t1�{�2���H�|$XH��L��H���o���H�m�I�/��D��R���f�E�������L���/����<$����H�D$(�H�5�D�D$8D�L$0������D�L$0D�D$8�U���A����������S�ډH�� H�8����H�|$(H�H�D$H��H��H��L����<$�C���1�H�Ĉ[]A\A]A^A_�H��������L�=� �F���L����D��v���L�=W �[���H�C H�5�H�8���o���H�������L���z��|���L��H��1��s���L�L$8I���S���@����H�|$(H��H�D$8���L�D$8M���=H����H�l$0H��H�����H�EH�D$8H��H��H�E�*���H�|$0����������fD�������H�D$(H�8H�W�H�<$H�1�H������H�|$(H�$��H�$���H������H�- H�8�u�H�|$(H�H�D$H��H��H�u�g�L����<$��1��_����L�D$8���H��H��L�D$8��H�|$0H�@H��L��H�L$0H�8H�|$(���H�L$0H�)�0���H�����#���H�l$0H�}H�W�H��H�UuH��H�D$���H�D$H��tH�8H�W�H��H�uH����M�������I�/�y���L�����l���@H�! H�8�i�H�|$(H�H�$H��H��H�u�\�L����1��\���H�l$0H�muH��L�D$�4�L�D$I�(�y���L�����l����AWH��H�5q1�AVAUATUSH��HH�T$H�D$ �����C�H��H�$��H�|$ �����H�\$ H����H�D$01�L�|$@H�D$�vH�5�
L���!�M��tI�muL���m�M��tI�.uL���Z�H��tH�muH���F�H�CL���(�'�H�����H�H���eH�{H��t�H�t$����u�H�{H��t�L��E1��"������bH�{ H��t
f�?
��L��E1�����&H�{(L��1�������H�Cf�8����H��I����M��tH�5�L��H����M��tH�5�L��L����H�������CH�������H�5rL�������������H�<$H��H����H���pH����L��H����I�,$����L��������@L���h�H��H�Cf�8�'����@�f1�=������H��tH�m��1��
�H��I������M��tI�muL���}�M��tI�.uL���j�H��tH�muH���V�H�$H�H�D$H��H��H���H���2��DE1�A��D���T���� �t#�΃�@�������@���������3Dƃ�U�gE�L�����D)�D)�A��A��E��`D�G1�M���-fD��D�G	t�uH��$@I9�s	A�$:I��H��D��L��$@���q0��W@��:M�A��A�H0A��W��:AM�M9�sM�D$A�4$M9���A�L$I����D9�u�����H��$@L)�L�t$H�5
1�L�����L��
H����������!�%����t������D�H�JHD��H��H+T$Hc�H9�}H�t$H��L���F�Ƅ$?L���&�I������fDL����I������A��������A��A����?������M���H��$@L)�H���$���I�D$H��$@A�$:A�D$:H)�I������1��i�H�$H�H�D$H��H��H��sH�~ H�5o
H�8���1�H��H[]A\A]A^A_�@H�|$ ����H�$u��@I�,$tyH��t
H�(��H�$H�H�D$H��H��H���H�|$ ����f�����H��I��tRH�@H�<$L��H��L� ��I�m�����L���%���L��H�D$��H�D$�p���H�����r���I�,$t*H�m�`���H������S���H��1�����)���L�������H�<$���B���H�$H�H�D$H��H��H�uH����H�) H�8�q�1����H���r�f��~���M���8���ATH�=� ��US��H��H�����H�5k1�H��H�����H�=W��1�I����L��H��H�����H�5=�H����H�=)�r��I���E�L��H��H����H�5
�H���s�H�=��7��I���
�L��H��H���L�H�5��H���8�H�=����I�����L��H��H����H�5��H����H�=����I����L��H��H�����H�5q�H�����H�=]���I���Y�L��H��H����H�5=�H����H�=)�K��I����L��H��H���`�H�5�H���L�H�=����I�����L��H��H���%�H�5��H����H�=�����I����L��H��H�����H�5��H�����H�=����I���m�L��H��H����H�5y�H����H�=e�_��I���2�L��H��H���t�H�5H�H���`�H�=4�$��I����L��H��H���9�H�5�
H���%�H�=����
I����L��H��H����H�5��
H�����H�=����
I����L��H��H�����H�5��H����H�=��s��I���F�L��H��H����H�5��H���t�H�=m�8��I����L��H��H���M�H�5P�H���9�H�=<���I�����L��H��H����H�5�H����H�=	����I����L��H��H�����H�5��H�����H�=����I���Z�L��H��H����H�5��	H����H�=��L��	I����L��H��H���a�H�5��H���M�H�=s���I�����L��H��H���&�H�5T�H����H�=@����I����L��H��H�����H�5%�H�����H�=���I���n�L��H��H����H�5��H����H�=��`��I���3�L��H��H���u�H�5��H���a�H�=��%��I����L��H��H���:�H�5��H���&�H�=y����I����L��H��H����H�5��H�����H�=����I����L��H��H�����H�5!�H����H�=
�t��I���G�L��H��H����H�5��H���u�H�=��9��I����L��H��H���N�H�5��H���:�H�=����I�����L��H��H����H�5�H��H�����H��H�5�H�����H��[]A\�H��H���%02x:defaultnetlink message truncated/%uaddrnetmaskpeerbroadcastAF_UNSPECAF_UNIXAF_FILEAF_INETAF_AX25AF_SNAAF_DECnetAF_APPLETALKAF_ROUTEAF_LINKAF_PACKETAF_IPXAF_INET6AF_NETBEUIAF_ATMPVCAF_ATMSVCAF_IRDAAF_NETROMAF_BRIDGEAF_X25AF_ROSEAF_SECURITYAF_KEYAF_NETLINKAF_ASHAF_ECONETAF_PPPOXAF_WANPIPEAF_BLUETOOTHaddress_families0.11.0versionnetifacesifaddressesinterfacesgatewaysYou must specify a valid interface name.Obtain information about the specified network interface.

Returns a dict whose keys are equal to the address family constants,
e.g. netifaces.AF_INET, and whose values are a list of addresses in
that family that are attached to the network interface.Obtain a list of the interfaces available on this machine.Obtain a list of the gateways on this machine.

Returns a dict whose keys are equal to the address family constants,
e.g. netifaces.AF_INET, and whose values are a list of tuples of the
format (<address>, <interface>, <is_default>).

There is also a special entry with the key 'default', which you can use
to quickly obtain the default gateway for a particular address family.

There may in general be multiple gateways; different address
families may have different gateway settings (e.g. AF_INET vs AF_INET6)
and on some systems it's also possible to have interface-specific
default gateways.
 ;<���X���p����0�X��zRx�$P���FJw�?;*3$"<D���B�D�A �A(�D@�
(A ABBAD���B�B�B �A(�D0�D@�
0A(A BBBAL�p��B�B�B �B(�A0�F8�G��
8A0A(B BBBAL���B�N�B �B(�A0�A8�G�,
8A0A(B BBBE,l0�=B�M�A �)ABP6 ��
0.�5 �5 ���o���
9(8 �
�(	���o0���o�o�
���o6 ���&6FVfv��������&6FVfv��������&6FVfv�/�������� : �/@ 0�/�1�/�P1GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-55)GCC: (GNU) 4.8.2 20140120 (Red Hat 4.8.2-15)GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-55),���M���-.�
�8�����int�=�iZ
�i��
�i���
�M�`
b#��#��#�
�#�# ?�#(�#0��#8�
�#@�	�#H��#P��#X��#`1!�#h?#b#p�'b#tL)p#x�-F#�.T#�M/�#��3�#�P<{#�3E�#��	F�#�:G�#�AH�#�HI-#�Kb#�M�#��	��
����
�����#���#��b#��������b��
n���?^�F�M��\�b�
��(	1?�2FQ4MA	iV
	r���B��
���
�#9
�#G
ď# �
ď#(�
��#04
ɏ#8�
��#@8
�	#H	
��#P
�R	#X�
��#`�
��#hM
�#pt
�]	#x@
�c#�]
�R	#��

�	#�j
�G	#��
�#�$
�8#�
�#��
�#�~
�#��
�~	#��
�#�'
��	#��
��	#�	
�G#��
�S#��
��#�y
��#�
�7#�
��	#��
��	#��
�#��
�	#�2


#�4
�	#��
�#�D
�#�4
7#�5
7#�
7#�F
	7#��

7#�
�#��
M#�C
�#��
<#�
�i��k�#�l�#�w
m�s�t�#u�#
v�{�!'777���HN7c77u�nt7�777I���b�7G�����7	���7�7���b!7�7��,2bL777��W]br770�}�b�7����b�7r��������
�7����7	7��Hd�'	-	bG	7�7��,�	�!��h	n	�~	7��	�	7�	77b��!{�!I	�n0	�,��,���	�	7
�77�
�

71
��
�P
8�
buf
9�#obj
:7#len
;�#�
<�#�
>b# �
?b#$t
@�#(i
A�
#0`
B�
#8H

C�
#@�
D�#H��
E1
a
G�
�
b7b�

H%+
<7�
JGM7l7l-7r	7 
o�
�
t=#l
u=#�
v=#
w=#�
x=# W
yc#(�
z#0�
{#8�
|#@�
}�#HZ
~#P(
=#X�
�=#`+
�=#h�

�=#pa
�=#x�
�#��	
��#��
�#�l	
�=#�T
�=#�l
�=#�)
�=#�Y
�c#�*
�=#�d
�=#��
�=#�7
�=#��
�=#�
�=#��
�=#�B
�=#�x
�=#��
�#�
�=#�,
�=#�
�wP
�-�
��#�
�=#�
��#�
��#�
��# �
��#(d
��#0�
�L#82
�=#@�
��#Hj
��

�k�
��#q
�=#�
�!#�
�8
���
�#.
�#�
�#�
�v
���
��
#�
�#
����
-k�
7 #G|$#�%P#+&b#d(#�M
(�#get
�#set�#doc#K�# Y�?��
�
 
U��
V#Z
W�#]
-���(	?�
#H?#�# 7��H7*[
�(,��-�#W.�#�	/�#�
07# 7��1l
g=��
>b#`
?�#
�hK|�L�#BM#(�N#0O�#8Pf#@�Q|#HR�#P�
S�#X�T�#`��7�7����	��b�77�
�	,�c.�#�/-#>)-
�2`"U
lF
��a<�-#��a#�q�
��qb��w	� ���������	�a�#� T�����m��
'8�\�ٍ#��c#��\#,�-#�ߍ# d
�-#(r�b#0�8
���-#�`# �#U!L#h
�L�'N-#O�#)
Pb#���s
�
`�M��-#�ު#��#�P#

���-#��#�	�#�5#\�#SM�
�#/%-#�&/#':#�
(#()$#
*?#�d�+s7�	C�
XZW�Wb9W�#W��W��W!WMkW��W�V	W�
W%�W1W=�WI�	8	h	�	�$	�/	:	SE	�P	�[	f	+q	7|	C�\�[$[�9[�#[�[�[![)k[4�[?V	[J�
[U�[`[k�[v,�;_�
8� Y��	��������
��
� 7���� �����\y-��
���:��#�[�����%n�y%��5�
�PO��#?`�;?�
FCM
�k
k�v -#�!F#�"v#|#v#
%&$(v#O)k#p*k#o+v#S,v#
C_M	ab#msgb�#
M�e��m��
��2;
��� �!
"P$,%�&�(�)L*�,�-�	.�0�1E24�6�:$>����
���#���(�
+
yv�{F#h|F#

��?#��?#=	�?#��?#	
�?#��?#A�?#
�?#��M#��36
��&��������|��-o
|��
v
U�	"
F^�
A��
���#x`#F�H�#����J�?�
���F#4F#xb#�F#�?#
?#	P#'��-bS.b
\8 #"�#]#M#h%b#�&b# �/�#(W9�#0���.op�7 q�b}!��7!-�bobj�7"q�7"��7#��b�$af�b���op�7 �UbX!Ub!�V�!�W-"LYb"�Zb"	[b"\c%&n~-&len~-&ptr�"[�%"�
�X ��bB!�b!���!��-%"���&n�M"L�M"��M"Z�M"S��"���"O��'"A�?&x�?&zx�M%"A�?&ch1��&ch2��(�7�}� )o7*�
7;*�C�+^D�@*E�,W *T7--�0X ."v/9I0Uv1
I 0Uv1-I< 0U}0Tv/*KI0U}0Tv2[jJ� 3"]/jI0U}1�hI� 0U01��I� 0Uw1�I� 0Uv0T|0Q@4I�I4y�I5����@".��.�56�7��7�7
,8�2}��az!.�O,`"7z7$�70�7<_2}����!.��9p��!7I/L�I0Uv}0T	@./�J0Uv0Q}0R
0X00Y00w1(��7�8 &.)o�7x*��7�*f
�7�	X��":hdr��#:rt�v#[�.#*��."
*<�.�
;s�bL;seq�b�;ret��+g	����{+��.	4+��c��{*L�b�*��b
*��b�
<+�b+�.��|=�-����#."�/yI0Us,�t++�
	���{>iov
���{+'���{*�b0,01+;dst+�f;gw,��*�-b"*.*.o*�.*.;len/bH*�0b~+gi@.	4+�jE.	�3,��*+�qJ.��}+�r���{*s�*tt*
u7�*�v7�*iw7S*�	x7�*�	x7d-M`��%."\4�I-W���%."�/�I0Uv-.r��m(.X�.LT.@�?�@d@p,�U(.X@.L�.@�?�7dK7p�2<e��&."Y/`I0U��z2Ae��&."|/XI0U��z2e��'."�/�I0Uv2����V'.��A���."�4�I2 ! ��'3"V/ I0Uv2! 8 ��'."
43 I1BJ�'0Uv�1ZJ�'0U��z0T��z1<KI(0Tv1hI-(0U1/AwJ0U��z0T��z0Q��z/w�J0U��z,")*�7--�P��(."�/�I0Uv-����(."�/�I0U4�BJ/�wJ0U��{0Tv0Q-0��Q)."4jI2�����).�UA���."x/�I0U1��J�)0T��{1��J�)0T0Q��{0R
1	I*0Uv1I *0U��{10�JK*0U30T��z0Qv0R4@K1U(Kp*0U|1]=K�*0Uw�/��J0U20T��z0Qv90�**xHZ.�4VK40�I1KdK+0T	�30Q@/�dK0T	40Q41��KX+0Uw�0T��z0Q0/��K0T	N.-z���+."�/�I0U��z2���+."�/�I0U��z2���$,."
/�I0U��z4��K4��K4��K1��Kv,0U0T	F.0Qs1L�,0U��z0T	F.1&#L�,0U��z1C<L�,0U@0T30Q01|^L�,0Uw�0Ts0Q<1��L$-0Uw�0Ts0Q��{1�L`-0Uw�0T|0QL0R00X	40Y<1�(Kx-0U|1�=K�-0Uw�4z�L4��I1�(K�-0U|1�=K�-0Uw�4��I/�(K0U|�.B��"	�b*.� M?@.�	0.	��Z.��$(\�7@ �&/�8)o�7�)T�7�+���}*��7*a�bQ+^���}*�,�7+�J.��}*�7�*�7g *�7!*a7�!-^� p/l0.�D".|�".p1#,�W0@�7�z#7��#7�4$7�}$7��$@�C���},P�/7��%7
&7[&,�07�&7''73`'1W$�I:00U~0T	h./�$�L0U|0T��}/�!� 0T,�t6*A7�'2�� � \�0.�>(A� � �."�(/� I0U}2�� � ]=1.��(A� � �."?)/� I0U~2�� 
!^�1.�b)A� 
!�."�)/
!I0Uv-.! a 4.X�).L**.@l*? @d@p,@
4.X�*.L<+.@e+?@7d�+7p4,2T"p"�P2."-/g"I0U|-�%���2.":-/=&I0U|-��%���2.�p-D�%��."�-4O&I2&0&�
3."�-/+&I0U}-T& �C3."�-/�&I0U|2[&s&�}3."5./n&I0Uv1("BJ�30Uv
��17"ZJ�30Uw0Tv1T"KI�30T|1�%hI�30U1/&wJ0Uw0Tv0Q}/!�J0U|2��"�"D|4.�X.A�"�"�."{./�"I0U}2��"�"E�4.��.A�"�"�."�./�"I0U~2��"�"F45.��.A�"�"�."//�"I0Uv2�"(#Ho5."*//#I0Uw-�%Pb�5."N//�&I0Uw1� �K�50U|0T	y.4�!�K1�!�K60U|0T	l.0Q}1�!�K.60U|0T	q.0Q~1"�KY60U|0T	~.0Qv4�"�K4�%�I9<!F!�6"O-"�-4F!M,�H7;sin8M�/9�"�"�6;__v:M�/;__x:M�/D��"�;.�0D�"��."_04}&I1^!� `70T1�!� x70T1x"I�70U1�$I�70U/�$I0U-G%0�7."�0/�&I0Uw2�&�&�/8."�0/�&I0Uw1p )M\80U�T0T	�/0Q��}4} �K1� �I�80U��}1G%�I�80U01y%�K�80T	�/4�%�I4�&�IE�
7�&-.1iH*y
7�1;m
7�11'GM>90U	�9 0T
�4'�K1*'jMu90Us0T	�.0Q016'I�90U	�.1@'BJ�90U01N'wJ�90Uv0Q|1b'jM�90Us0T	�.0Q11n'I:0U	�.1{'BJ):0U11�'wJG:0Uv0Q|1�'jMq:0Us0T	�.0Q11�'I�:0U	�.1�'BJ�:0U11�'wJ�:0Uv0Q|1�'jM�:0Us0T	�.0Q21�'I;0U	�.1�'BJ%;0U21�'wJC;0Uv0Q|1(jMm;0Us0T	�.0Q31(I�;0U	�.1,(BJ�;0U31:(wJ�;0Uv0Q|1N(jM�;0Us0T	�.0QF1Z(I
<0U	�.1g(BJ!<0UF1u(wJ?<0Uv0Q|1�(jMi<0Us0T	�.0Q<1�(I�<0U	�.1�(BJ�<0U<1�(wJ�<0Uv0Q|1�(jM�<0Us0T	�.0Q51�(I=0U	�.1�(BJ=0U51�(wJ;=0Uv0Q|1�(jMe=0Us0T	�.0Q@1)I�=0U	�.1)BJ�=0U@1&)wJ�=0Uv0Q|1:)jM�=0Us0T	�.0QA1F)I>0U	�.1S)BJ>0UA1a)wJ7>0Uv0Q|1u)jMa>0Us0T	�.0QA1�)I�>0U	�.1�)BJ�>0UA1�)wJ�>0Uv0Q|1�)jM�>0Us0T	�.0Q41�)I�>0U	�.1�)BJ?0U41�)wJ3?0Uv0Q|1�)jM]?0Us0T	�.0Q:1�)I|?0U	�.1*BJ�?0U:1*wJ�?0Uv0Q|1&*jM�?0Us0T	�.0Q=12*I�?0U	�.1?*BJ@0U=1M*wJ/@0Uv0Q|1a*jMY@0Us0T	/0Q81m*Ix@0U	/1z*BJ�@0U81�*wJ�@0Uv0Q|1�*jM�@0Us0T	/0QD1�*I�@0U	/1�*BJ
A0UD1�*wJ+A0Uv0Q|1�*jMUA0Us0T	/0QG1�*ItA0U	/1�*BJ�A0UG1�*wJ�A0Uv0Q|1+jM�A0Us0T	"/0Q61+I�A0U	"/1++BJ	B0U619+wJ'B0Uv0Q|1M+jMQB0Us0T	,/0Q71Y+IpB0U	,/1f+BJ�B0U71t+wJ�B0Uv0Q|1�+jM�B0Us0T	6/0Q91�+I�B0U	6/1�+BJC0U91�+wJ#C0Uv0Q|1�+jMMC0Us0T	=/0Q;1�+IlC0U	=/1�+BJ�C0U;1�+wJ�C0Uv0Q|1�+jM�C0Us0T	E/0Q>1
,I�C0U	E/1,BJD0U>1%,wJD0Uv0Q|19,jMID0Us0T	Q/0Q?1E,IhD0U	Q/1R,BJD0U?1`,wJ�D0Uv0Q|1t,jM�D0Us0T	X/0Q@1�,I�D0U	X/1�,BJ�D0U@1�,wJE0Uv0Q|1�,jMEE0Us0T	c/0QB1�,IdE0U	c/1�,BJ{E0UB1�,wJ�E0Uv0Q|1�,jM�E0Us0T	j/0QC1�,I�E0U	j/1-BJ�E0UC1-wJF0Uv0Q|1%-jMAF0Us0T	�.0QF11-I`F0U	�.1>-BJwF0UF1L-wJ�F0Uv0Q|1`-jM�F0Us0T	t/0QH1l-I�F0U	t/1y-BJ�F0UH1�-wJG0Uv0Q|1�-jM=G0Us0T	}/0QI1�-I\G0U	}/1�-BJsG0UI1�-wJ�G0Uv0Q|1�-jM�G0Us0T	�/0QO1�-I�G0U	�/1�-BJ�G0UO1�-wJH0Uv0Q|1.�M:H0Us0T	�/0Qv/%.�M0Us0T	�/0Q	�/[yH�+�	iH	 : +!
�	�9 F���F2��F}�Fh �FF �F�!W7F�!s7GV�I7H�"�7-IIC#�bKI77H
$"bhI77H�$7�I�HvCb�I�IHO%fb�I-JXF�IH�!�7�I7I{	ObJ�KI&�bBJ�c�c�cMHF
'7ZJiH�(7wJ77H�(b�J777I�#��J7H���JM�H)A�Jb\�cH�
*#7K�KI1b(K7G�+[=K�II@bVKbL�,+HE%>b�K\\-H7��Kb�Kb�JI!
�K7MI�bLy(7H�(:bL77H�(97#L7IZ+M�<L-H;db^LbbbH�nb�Lb�cH�rb�LbO�LcHS
��Lb\-b�cLZ!�7N��M�\�O.b)MH�-(bGM7KH�-�7dMdMb�H�-�b�M7iH-�b�M77Pg-�b7%:;I$>$>I:;
:;I8
	&I
'I:;
:;
:;I8
I!I/&:;:;'I
:;I8
:;<'I:;(
:;:;
:;I.:;' :;I .:;'I !:;I"4:;I#.:;'I $:;I%&4:;I'(.:;'I@�B):;I*4:;I+4:;I
,U-1RUXY.1/��10��
�B
1��121XY31
4��15.1@�B641741819:
:;I8
;4:;I<4:;I=
:;>4:;I
?U@41A1XYB!IC41
D1RUXYE.?:;'I@�BF4:;I?<G.?:;'<H.?:;'I<I.?:;'I<J.?:;'<KL.?:;'I<M.?:;'I<N.?'I4<O.?:;�@'I<P.?:;'I<9	��
/opt/_internal/cpython-3.9.5/include/python3.9/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-CentOS-linux/4.8.2/include/usr/include/bits/usr/include/usr/include/sys/opt/_internal/cpython-3.9.5/include/python3.9/cpython/usr/include/linux/usr/include/netax25/usr/include/netinet/usr/include/netipx/usr/include/net/usr/include/asm-x86_64/usr/include/netpacket/usr/include/arpanetifaces.cobject.hstddef.htypes.hlibio.htypes.hunistd.hstdint.hpyport.hobject.hmethodobject.hdescrobject.hlongintrepr.hlistobject.hmoduleobject.huio.hsockaddr.hsocket.hatalk.hax25.hin.h	ipx.h
socket.hif.htypes.htypes.hnetlink.hrtnetlink.hpacket.h
ifaddrs.hstdio.hboolobject.hpyerrors.hunicodeobject.habstract.hlistobject.hstring.hnetdb.hlongobject.hdictobject.hinet.htupleobject.hstdlib.herrno.hmodsupport.h<built-in>	��
;.E.8��Z:>�t��xt�tvJ��X=�d>��x�|�.jX�<���xJ|����xt	��~��<
�O�~J��xJ	JwJ.�:Z�/IW]'_�YN������}X��^}]SA��Ys=�u��
�Z�:>l,>fTxTY�:�	ȫ��7]ytZkw�!�g���8��.Xt��e�=Z�
��)�~���	��
�ZHLHLk�;M-Yf;0(��Pn�X�K�MKy�K�Y��I
�":>iZ�	X�u���W=Z�:YX)<�t �J��vf�	�Y�V>�s��֓��~��X�z.[5��t�����~��.�o ���t������u����v֑"���}���
��uX�
.�u.��
$�u���
X���wt�;=���=�}��xJ� �X�������
�u�|�
X��u�|x ��JXr��T��Z:L�f&�{��X�.�{X���{��X|���Xn���X|���|J�<�|<��wX����U<+<��{J���<�|<�X�Ot1.�
�Z:>
fY!Y"�K;i�|��I=����}������{.�X��3Z:>�{f�X|���Xn���X|x��
 
<ɆZKL�h�_WY;=v�Wb."�+[g��Cy�h���Y��m��CZB��U�{t>m�*5�L�Y��zt���0�~X���y��t�X�&��|J�;=4K�=�}X�x1(���z.x(|����{t����
.v�
.Y;=jZ�>Y$='='='=,'='='='='='='='='='='=''=	'='='='='='='='='='='='='='([RTA_DSTrtm_familyRTM_NEWADDR_unused2__RTM_MAXRTM_GETROUTE_filenolenfunc__s1_lenfreeifaddrssockaddr_isoadd_to_family__sockaddr_un__PyDict_GetItemStringtp_getattrsq_itemRTM_NEWACTIONnb_addob_refcntmsg_namesq_ass_itemrtm_dst_lensq_inplace_repeattp_as_asyncnb_matrix_multiplynb_lshiftsq_inplace_concattp_is_gc_shortbufnb_powersockaddr_insa_family_ts_nodeinet_ntopam_anextIFF_PROMISC__CONST_SOCKADDR_ARGRTM_NEWADDRLABELPyInit_netifacessq_repeattp_itemsizesq_concatuint16_tinitprocsin_zeroin_port_tPyGetSetDefRT_TABLE_MAINtp_bases__off_tmemcmpzeroesifu_dstaddrIFF_BROADCASTRTM_SETLINKaddress_family_dictstring_from_netmask_lockPyModule_Create2netifaces.cnb_negativesetattrofuncsockaddr_lltp_deallocmsg_namelenIFF_AUTOMEDIA_typeobjectnb_floor_dividenb_inplace_lshiftsa_familyRTA_FLOWpfxbuf_Py_DeallocMSG_PEEKsockaddr_nlMSG_CTRUNCMSG_NOSIGNALmemcpysin6sockaddr_nsprioritynl_pidRTA_SESSIONnb_indextp_richcompareMSG_DONTWAITrtm_protocolm_freesll_family_IO_write_endnb_remainderRTA_PROTOINFOvisitprocs_addrbyte_Py_TrueStructsat_zeroRTA_CACHEINFOnb_inplace_multiplymsg_controlbraddrax25_addresswas_sq_slicePyMemberDefPyExc_OSErrorgatewaysob_type_Py_XDECREFtp_freesin_familygetterPyModuleDefPyVarObject__sockaddr__MSG_RSTnb_andSOCK_RAW__u8tp_callob_itemRTM_NEWQDISCtp_strwas_sq_ass_sliceternaryfuncsin_portRTM_GETQDISCob_basePyTypeObjectsa_dataRTM_DELACTIONRTA_TABLEPyModule_AddIntConstantstring_from_sockaddrsq_contains/tmp/pip-req-build-fl52pudd__sockaddr_in___chaintp_setattrPySequence_Containsifa_dataSOCK_RDMisdefaultsockaddr_unrichcmpfuncunsigned charmp_ass_subscriptRTM_DELTFILTERSOCK_DGRAM__sockaddr_inarp__getsockname_IO_lock_tifndx__RTA_MAXtp_dictoffsetIFF_POINTOPOINTPyNumberMethodsmsg_iovlenPyMethodDeftp_finalizestrncmpm_initu_int16_trta_typemp_subscripttp_clear_Py_DECREFrtm_flagsPyModuleDef_Base__sockaddr_eon__nb_boolIFF_NOTRAILERSsat_portRTM_DELNEIGHtp_initobjobjargprocob_sizeMSG_PROXYattrstp_dictmoduledefinterruptedrecvmsg_IO_write_ptrtp_as_mappingu6_addr8setattrfuncnlmsg_flagsRTA_IIFMSG_WAITALLu_int8_tbinaryfunc__s2_len__errno_locationm_docinterfacesIFF_ALLMULTIbf_getbuffervectorcallfuncgetiterfuncgniaddrssizeargfuncerrorsll_addruint8_tdescrsetfuncrtm_src_lendescrgetfunc__sockaddr_ipx__sanlnb_inplace_addsprintfnb_reserveddeftuple_IO_save_baseiovecMSG_SYNm_indexIFF_NOARPreprfuncsockaddr_x25sin6_flowinfo__pad2RTM_GETTFILTERrtmsgPyList_Appendrtm_typeRTA_PREFSRCsax25_ndigisRT_TABLE_UNSPECPyLong_FromLongPy_hash_tvaluedefaultsRTA_SRCPyObjectnb_xor__SOCKADDR_ARG__socklen_tlladdrRTA_GATEWAYRTM_SETNEIGHTBLslot__ssize_tsanl_from_longobjectIFF_MULTICASTsipx_nodes_netm_traversesin6_addrPyBufferProcsml_flagstp_newIFF_UPm_namegetpagesizeRTA_METRICSfoundPyModuleDef_Slotnb_inplace_true_dividePyObject_SizedestructorPyCFunctionrtm_tossanl_kernelresultbuflenmsg_iov_sbufbindMSG_DONTROUTE_IO_save_endifa_nextsipx_zerotp_delnlmsg_lensipx_typestdouttp_namertm_scopeclosurenlmsg_pidifa_flagsPyModule_AddStringConstantRTM_GETMULTICASTtp_as_sequenceRTM_GETLINKtp_as_buffersizetypenllennb_inplace_andsll_hatypeshort unsigned intrt_class_t__be16rtm_tableSOCK_STREAMRTM_GETRULErtattrtp_allocRTM_NEWNEIGHsuboffsetssendto__off64_tmsg_controllensockaddr_eon_IO_read_basem_clearIFF_SLAVE__u16PyTuple_Pack__sockaddr_iso___IO_buf_endIFF_DEBUGRTM_GETADDRtp_getattroallocfuncm_copy_modetp_methods_IO_write_base__sockaddr_ax25__tp_mromsgbuf__u32closein6_uSOCK_PACKETnb_oripv4_defaultformatunaryfunc_IO_markerPyDict_SetItemRTM_GETNEIGHRT_TABLE_DEFAULTifa_ifunb_floatPyDict_GetItem__sockaddr_dl__u6_addr16PyExc_ValueErrortraverseprocRTM_NEWPREFIXRTM_DELADDRLABELtp_vectorcall_offsetinquiryuint32_tnb_invertml_doc__sockaddr_in6__ml_name__sockaddr_ns__sipx_portatalk_addrtp_as_numberiov_lenPyAsyncMethodstp_weaklistoffsetPyDict_SetItemStringml_methreadonlytp_docgetattrofuncpyfamilySOCK_SEQPACKETPyObject_IsTrueRTA_MP_ALGOsockaddr_inarpsin6_scope_idPySequenceMethodsrtattr_type_tstdinsin_addris_multiu6_addr32tp_weaklistprev_name_IO_buf_basebufferinfonewfunchashfuncgetattrfunc_IO_read_endsipx_network_IO_FILEPyModule_AddObjectin_addr_tIFF_PORTSELnlmsgerrRTM_GETTCLASSPyErr_NoMemoryshapeselftp_hashnl_groupspmsgPyUnicode_FromStringndimssizeobjargprocsat_familytp_vectorcallRTM_NEWTFILTERtp_version_tagsockaddr_ax25ipv6_default__builtin_strcmpgetnameinfoRTM_GETANYCAST__pad1__pad3__pad4__pad5nlmsg_typemallocgetbufferprocnlmsg_seqPyDict_NewRTM_DELROUTEfailure_markers_possetteram_awaitPyList_NewRTM_BASEtp_memberstp_traversePyErr_SetFromErrnobufendmp_lengthsat_addrdef_prioritiesdoublenlmsghdram_aiternb_inplace_xortp_subclassesargsnb_inplace_powertp_setattronl_familyfreefuncnb_multiplym_basenb_true_dividetp_getsetrta_lenbufsizeifa_netmasktp_iternextsq_lengthIFF_MASTERRTM_NEWTCLASSRTM_NEWNEIGHTBLtp_descr_getsll_halentp_itersipx_familysocketnb_inplace_floor_dividebytesstridesifa_addrMSG_OOBtp_basenb_rshiftsin6_familysll_pkttype__sockaddr_x25__ifnamebufbf_releasebufferRTM_GETNEIGHTBLlong long unsigned int_cur_columnreleasebufferprocsax25_callu_int32_tnb_inplace_remainder__socket_typebigaddrMSG_ERRQUEUEMSG_CONFIRMMSG_MOREgetifaddrsm_slots_objectMSG_FINMSG_EORnb_absolute_IO_backup_base_IO_read_ptrPyListObjectinternalRTA_MULTIPATHsanl_lennb_inplace_orm_methodsm_sizetp_reprtp_cachesax25_familysll_protocolPy_ssize_t_old_offsetrouting_msgnb_inplace_rshiftRTA_PRIORITYpyaddrRTA_OIFPyArg_ParseTuplenb_positiveRT_TABLE_LOCALlong long int_flags2PyMappingMethodsprefixsockaddr_atifu_broadaddrgnilensockaddr_in6allocatedtp_flagsRTA_UNSPECIFF_LOOPBACKRTM_GETACTIONbufptrob_digitiov_basenb_subtractperrPyType_TypeGNU C 4.8.2 20140120 (Red Hat 4.8.2-15) -mtune=generic -march=x86-64 -g -O3 -fwrapv -fPICMSG_TRYHARDRT_TABLE_MAXRTM_DELLINKif_indextonameifa_nameIFF_DYNAMICRTM_DELQDISC__sockaddr_at__PyErr_SetStringIFF_RUNNINGRTM_NEWLINKpy_familyiternextfuncsockaddr_dlRTM_GETADDRLABELRTM_DELRULEnb_intMSG_TRUNCaf_to_lensockaddr_ipxtp_descr_setPy_bufferRTM_GETPREFIXRTM_NEWRULEpyifnameshort int_vtable_offsetnb_inplace_matrix_multiplytp_basicsizenb_inplace_subtract_Py_FalseStructsll_ifindexRTM_DELADDRnb_divmodobjobjprocnl_padRTM_NEWROUTEsin6_portRTM_DELTCLASSwwww w(�w���w(��w ��w��w��w��w�U��U�#P#�]��]>0�>�\��0�00�0�S��S��0�>KV��P��V>KV��V��w��w��w��w ��w(��w0��w���w0��w(��w ��w��w��w��w��FUF�V���U���V�T�]���T���]���T�KSP.JUJ�V���U���V.JT;	u�
�����0�o�\��\��]��V��U��v}���V��}~"1�}�S��SS\p
���\_Q_�p
�����p
�����Vwwww 	w(	w0w8�w���w8��w0��w(��w ��w��w��w��
w�U�
�U�LPPP�_����z��_����z�	_	,	��z,	p	_p	4
��z4
s
_s
�
��z[ePe�S��P����{��S��
��{�\W}\}.SP�S�S1�S	,	Sp	4
Ss
�
S��P��\��\��P��
\��P��w��w	4
w4
?
P?
S
ws
�
w^0�^�1���0���1��	0�	,	1�p	4
1�4
s
0�s
�
1�@}PP7P0�V����z��V����z�	V	,	��z,	p	Vp	�	��z4
s
Vs
�
��z0�0���]�9]P�]��0���]�	0�	,	],	p	0�p	4
]4
s
0�s
�
]f�S��S�	S4
s
SW}P��^�0�WUY�UPjU��0��0�tv_��0��	��dfY��	���.s�P�s��s�1�s�	,	s�p	4
s�s
�
s���QP\Q��RPjR�	��@[x $0 $+(�[���z� $0 $+(�
��z� $0 $+(� P �V��V
V!DP��P��P��V1jV��P��T����z1���z@�_��U
_��0���P����z��0�
0�1���zp	�	��z�	4
��zs
�
��z��0��&_��0��
_
0�1K_Ke0�ejPj�_	,	_p	4
_s
�
_��Y>EY��V1>V��U����zj���zp	�	��z�	4
��zs
�
��z��p����v��j�v��p	�	v��s
x
v������zj���zp	4
��zs
�
��zj���zp	�	��z�	4
��zs
�
��zj�v��p	�	v��s
x
v��j���zp	4
��zs
�
��zs�P����zp	z	��z�	
��z��Pp	~	P�	�	P�	�	R�	�	��z�	�	P�	�	��zs
�
P��V�	�	��z�	
V�	
P�	
P�
�
XP&V�
V	,	V&V�
V	,	V&_�
_����z��U����z
4
_
4
_��s��	��z;	p	��zG
s
��z�
�
w�
�
w�
�
w�
�
w �
�
w(�
�
w0�
�
w8�
�w���w8��w0��w(��w �www]w��
�
U�
]�U��
�
T�
�
U�
]�T��
P�w]w�
-0�-�1���V��1���0�V1�F0�U]1��
0��SSF0�F]S-�]��0��2]2C0�CHPH�]6]^p]��]��]U]]-�^��0���
^�
-0�-2P2�0�^U]0�->Q>�V�0��V��0���P��
V�
�0���V��UU]0�-�0�0�U]0�-�
��2
�H�
�
�U]
�-�_�2_H�__U]_��U�
UHqU�
X0�GP��PHnXnq0��
YHnY�
�Qn�QU]Qy1$��Yn�YU]Y_:\:C|�C\�X��|��"\nq_q�\��|���PU]X�
�
QHnQ�
�
Q�
�
rq��
�
R�
�
8��
�
7��
�
T�
�
P�
�
p�HnPX'fX5TX�TU]TGRj�RU]R-�\+GPG�\)
B
PB
�
\�\�\?�]��]6]^p]��]DS]S�^��^R^^�^�^Xf^f�VkzV��U��\��\R\^�\�\��v
�����v
�����w��wRw^�w�w��\R\^�\�\��v
�����wRw^�w�w��P��VRV^�V�V��P'P^iPpvPv�]��P����}��P��]��P�]��\6\��\'6P��P,6P��P��]��\�\��V/
�
]4
C
]C
�
^H
V
^V
�
V[
j
Vj
�
w6Rw
Q
w��P�
P��p��P

V��V��U

V��V��U��wFMQMUwFw`bwbowopwp�w ��w��w��w��P��V{�P��S��P@Ku�@G��O���fp���0P���	,	p	8
x
�
�����0P��1�	,	p	8
x
�
���0���1�	,	p	8
x
�
��>K��1>��j�p	
x
�
�0�
	,		,	0�
�������	!��� U]&0�����
"P�U]&0�
"P�U]�
�
P[ �U]0� �
�
 ��~����� 6`�� '��'6��,6�����6R�
��

����

������FU.symtab.strtab.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.jcr.data.rel.ro.dynamic.got.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str.debug_loc.debug_ranges��$.���o��<8���@��9H���o�
�
vU���o00Pd��(n�
�

x��s���~����0.0.	�@.@.� �44<�P4P4���5 �5��5 �5�6 6�6 6�6 6���7 �7H�(8 (8p��9 �9 ��: �:��:��);0Y;�M&�*(P�=	40���?^�22J��`��XH�@#?	�������
0��
	�
��0.
@.4P4�5 �5 6 6 6 �7 (8 �9 �:  ��*�56 B�W�j��: ��5 �P��5 �������
�3$#��,
4>
�3Q
4d@ �l�9 hv : �*�~�5�6 ��6 �6 ��: �(8 ���1Od ���: ���&=��0.���(AQet����� ���5�: :J[w��: ������ 2AZs� �"�	���/usr/lib/../lib64/crti.ocall_gmon_startcrtstuff.c__JCR_LIST__deregister_tm_clonesregister_tm_clones__do_global_dtors_auxcompleted.6330__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entrynetifaces.cinterfacesstring_from_sockaddr.constprop.2CSWTCH.22gatewayssanl_kernel.13636ipv6_default.13667ipv4_default.13666ifaddrsmoduledefmethods__FRAME_END____JCR_END____dso_handle_DYNAMIC__TMC_END___GLOBAL_OFFSET_TABLE_inet_ntop@@GLIBC_2.2.5PyList_NewPyDict_SetItemStringfree@@GLIBC_2.2.5PyModule_AddIntConstant__errno_location@@GLIBC_2.2.5strncmp@@GLIBC_2.2.5_ITM_deregisterTMCloneTablePyErr_SetFromErrno_edata_Py_DeallocPyInit_netifacesPyErr_NoMemory_finiPyErr_SetStringPyExc_ValueErrorPySequence_Containssendto@@GLIBC_2.2.5close@@GLIBC_2.2.5getnameinfo@@GLIBC_2.2.5PyLong_FromLongmemcmp@@GLIBC_2.2.5PyDict_GetItemmemcpy@@GLIBC_2.2.5PyList_Appendstrcmp@@GLIBC_2.2.5PyExc_OSError_Py_FalseStruct__gmon_start__PyModule_Create2PyDict_GetItemStringPyObject_Sizemalloc@@GLIBC_2.2.5getifaddrs@@GLIBC_2.3_endPyObject_IsTruePyArg_ParseTupleif_indextoname@@GLIBC_2.2.5_Py_TrueStruct__bss_startrecvmsg@@GLIBC_2.2.5freeifaddrs@@GLIBC_2.3PyDict_Newbind@@GLIBC_2.2.5PyUnicode_FromStringPyModule_AddStringConstantPyModule_AddObject_Jv_RegisterClassesPyDict_SetItemgetsockname@@GLIBC_2.2.5getpagesize@@GLIBC_2.2.5sprintf@@GLIBC_2.2.5_ITM_registerTMCloneTable__cxa_finalize@@GLIBC_2.2.5_initPyTuple_Packsocket@@GLIBC_2.2.5PKok\��;�;psutil/_compat.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module which provides compatibility with older Python versions.
This is more future-compatible rather than the opposite (prefer latest
Python 3 way of doing things).
"""

import collections
import contextlib
import errno
import functools
import os
import sys
import types


# fmt: off
__all__ = [
    # constants
    "PY3",
    # builtins
    "long", "range", "super", "unicode", "basestring",
    # literals
    "b",
    # collections module
    "lru_cache",
    # shutil module
    "which", "get_terminal_size",
    # contextlib module
    "redirect_stderr",
    # python 3 exceptions
    "FileNotFoundError", "PermissionError", "ProcessLookupError",
    "InterruptedError", "ChildProcessError", "FileExistsError",
]
# fmt: on


PY3 = sys.version_info[0] >= 3
_SENTINEL = object()

if PY3:
    long = int
    xrange = range
    unicode = str
    basestring = str
    range = range

    def b(s):
        return s.encode("latin-1")

else:
    long = long
    range = xrange
    unicode = unicode
    basestring = basestring

    def b(s):
        return s


# --- builtins


# Python 3 super().
# Taken from "future" package.
# Credit: Ryan Kelly
if PY3:
    super = super
else:
    _builtin_super = super

    def super(type_=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1):
        """Like Python 3 builtin super(). If called without any arguments
        it attempts to infer them at runtime.
        """
        if type_ is _SENTINEL:
            f = sys._getframe(framedepth)
            try:
                # Get the function's first positional argument.
                type_or_obj = f.f_locals[f.f_code.co_varnames[0]]
            except (IndexError, KeyError):
                msg = 'super() used in a function with no args'
                raise RuntimeError(msg)
            try:
                # Get the MRO so we can crawl it.
                mro = type_or_obj.__mro__
            except (AttributeError, RuntimeError):
                try:
                    mro = type_or_obj.__class__.__mro__
                except AttributeError:
                    msg = 'super() used in a non-newstyle class'
                    raise RuntimeError(msg)
            for type_ in mro:
                #  Find the class that owns the currently-executing method.
                for meth in type_.__dict__.values():
                    # Drill down through any wrappers to the underlying func.
                    # This handles e.g. classmethod() and staticmethod().
                    try:
                        while not isinstance(meth, types.FunctionType):
                            if isinstance(meth, property):
                                # Calling __get__ on the property will invoke
                                # user code which might throw exceptions or
                                # have side effects
                                meth = meth.fget
                            else:
                                try:
                                    meth = meth.__func__
                                except AttributeError:
                                    meth = meth.__get__(type_or_obj, type_)
                    except (AttributeError, TypeError):
                        continue
                    if meth.func_code is f.f_code:
                        break  # found
                else:
                    # Not found. Move onto the next class in MRO.
                    continue
                break  # found
            else:
                msg = 'super() called outside a method'
                raise RuntimeError(msg)

        # Dispatch to builtin super().
        if type_or_obj is not _SENTINEL:
            return _builtin_super(type_, type_or_obj)
        return _builtin_super(type_)


# --- exceptions


if PY3:
    FileNotFoundError = FileNotFoundError  # NOQA
    PermissionError = PermissionError  # NOQA
    ProcessLookupError = ProcessLookupError  # NOQA
    InterruptedError = InterruptedError  # NOQA
    ChildProcessError = ChildProcessError  # NOQA
    FileExistsError = FileExistsError  # NOQA
else:
    # https://github.com/PythonCharmers/python-future/blob/exceptions/
    #     src/future/types/exceptions/pep3151.py
    import platform

    def _instance_checking_exception(base_exception=Exception):
        def wrapped(instance_checker):
            class TemporaryClass(base_exception):
                def __init__(self, *args, **kwargs):
                    if len(args) == 1 and isinstance(args[0], TemporaryClass):
                        unwrap_me = args[0]
                        for attr in dir(unwrap_me):
                            if not attr.startswith('__'):
                                setattr(self, attr, getattr(unwrap_me, attr))
                    else:
                        super(TemporaryClass, self).__init__(  # noqa
                            *args, **kwargs
                        )

                class __metaclass__(type):
                    def __instancecheck__(cls, inst):
                        return instance_checker(inst)

                    def __subclasscheck__(cls, classinfo):
                        value = sys.exc_info()[1]
                        return isinstance(value, cls)

            TemporaryClass.__name__ = instance_checker.__name__
            TemporaryClass.__doc__ = instance_checker.__doc__
            return TemporaryClass

        return wrapped

    @_instance_checking_exception(EnvironmentError)
    def FileNotFoundError(inst):
        return getattr(inst, 'errno', _SENTINEL) == errno.ENOENT

    @_instance_checking_exception(EnvironmentError)
    def ProcessLookupError(inst):
        return getattr(inst, 'errno', _SENTINEL) == errno.ESRCH

    @_instance_checking_exception(EnvironmentError)
    def PermissionError(inst):
        return getattr(inst, 'errno', _SENTINEL) in (errno.EACCES, errno.EPERM)

    @_instance_checking_exception(EnvironmentError)
    def InterruptedError(inst):
        return getattr(inst, 'errno', _SENTINEL) == errno.EINTR

    @_instance_checking_exception(EnvironmentError)
    def ChildProcessError(inst):
        return getattr(inst, 'errno', _SENTINEL) == errno.ECHILD

    @_instance_checking_exception(EnvironmentError)
    def FileExistsError(inst):
        return getattr(inst, 'errno', _SENTINEL) == errno.EEXIST

    if platform.python_implementation() != "CPython":
        try:
            raise OSError(errno.EEXIST, "perm")
        except FileExistsError:
            pass
        except OSError:
            msg = (
                "broken or incompatible Python implementation, see: "
                "https://github.com/giampaolo/psutil/issues/1659"
            )
            raise RuntimeError(msg)


# --- stdlib additions


# py 3.2 functools.lru_cache
# Taken from: http://code.activestate.com/recipes/578078
# Credit: Raymond Hettinger
try:
    from functools import lru_cache
except ImportError:
    try:
        from threading import RLock
    except ImportError:
        from dummy_threading import RLock

    _CacheInfo = collections.namedtuple(
        "CacheInfo", ["hits", "misses", "maxsize", "currsize"]
    )

    class _HashedSeq(list):
        __slots__ = ('hashvalue',)

        def __init__(self, tup, hash=hash):
            self[:] = tup
            self.hashvalue = hash(tup)

        def __hash__(self):
            return self.hashvalue

    def _make_key(
        args,
        kwds,
        typed,
        kwd_mark=(_SENTINEL,),
        fasttypes=set((int, str, frozenset, type(None))),  # noqa
        sorted=sorted,
        tuple=tuple,
        type=type,
        len=len,
    ):
        key = args
        if kwds:
            sorted_items = sorted(kwds.items())
            key += kwd_mark
            for item in sorted_items:
                key += item
        if typed:
            key += tuple(type(v) for v in args)
            if kwds:
                key += tuple(type(v) for k, v in sorted_items)
        elif len(key) == 1 and type(key[0]) in fasttypes:
            return key[0]
        return _HashedSeq(key)

    def lru_cache(maxsize=100, typed=False):
        """Least-recently-used cache decorator, see:
        http://docs.python.org/3/library/functools.html#functools.lru_cache.
        """

        def decorating_function(user_function):
            cache = {}
            stats = [0, 0]
            HITS, MISSES = 0, 1
            make_key = _make_key
            cache_get = cache.get
            _len = len
            lock = RLock()
            root = []
            root[:] = [root, root, None, None]
            nonlocal_root = [root]
            PREV, NEXT, KEY, RESULT = 0, 1, 2, 3
            if maxsize == 0:

                def wrapper(*args, **kwds):
                    result = user_function(*args, **kwds)
                    stats[MISSES] += 1
                    return result

            elif maxsize is None:

                def wrapper(*args, **kwds):
                    key = make_key(args, kwds, typed)
                    result = cache_get(key, root)
                    if result is not root:
                        stats[HITS] += 1
                        return result
                    result = user_function(*args, **kwds)
                    cache[key] = result
                    stats[MISSES] += 1
                    return result

            else:

                def wrapper(*args, **kwds):
                    if kwds or typed:
                        key = make_key(args, kwds, typed)
                    else:
                        key = args
                    lock.acquire()
                    try:
                        link = cache_get(key)
                        if link is not None:
                            (root,) = nonlocal_root
                            link_prev, link_next, key, result = link
                            link_prev[NEXT] = link_next
                            link_next[PREV] = link_prev
                            last = root[PREV]
                            last[NEXT] = root[PREV] = link
                            link[PREV] = last
                            link[NEXT] = root
                            stats[HITS] += 1
                            return result
                    finally:
                        lock.release()
                    result = user_function(*args, **kwds)
                    lock.acquire()
                    try:
                        (root,) = nonlocal_root
                        if key in cache:
                            pass
                        elif _len(cache) >= maxsize:
                            oldroot = root
                            oldroot[KEY] = key
                            oldroot[RESULT] = result
                            root = nonlocal_root[0] = oldroot[NEXT]
                            oldkey = root[KEY]
                            root[KEY] = root[RESULT] = None
                            del cache[oldkey]
                            cache[key] = oldroot
                        else:
                            last = root[PREV]
                            link = [last, root, key, result]
                            last[NEXT] = root[PREV] = cache[key] = link
                        stats[MISSES] += 1
                    finally:
                        lock.release()
                    return result

            def cache_info():
                """Report cache statistics."""
                lock.acquire()
                try:
                    return _CacheInfo(
                        stats[HITS], stats[MISSES], maxsize, len(cache)
                    )
                finally:
                    lock.release()

            def cache_clear():
                """Clear the cache and cache statistics."""
                lock.acquire()
                try:
                    cache.clear()
                    root = nonlocal_root[0]
                    root[:] = [root, root, None, None]
                    stats[:] = [0, 0]
                finally:
                    lock.release()

            wrapper.__wrapped__ = user_function
            wrapper.cache_info = cache_info
            wrapper.cache_clear = cache_clear
            return functools.update_wrapper(wrapper, user_function)

        return decorating_function


# python 3.3
try:
    from shutil import which
except ImportError:

    def which(cmd, mode=os.F_OK | os.X_OK, path=None):
        """Given a command, mode, and a PATH string, return the path which
        conforms to the given mode on the PATH, or None if there is no such
        file.

        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
        of os.environ.get("PATH"), or can be overridden with a custom search
        path.
        """

        def _access_check(fn, mode):
            return (
                os.path.exists(fn)
                and os.access(fn, mode)
                and not os.path.isdir(fn)
            )

        if os.path.dirname(cmd):
            if _access_check(cmd, mode):
                return cmd
            return None

        if path is None:
            path = os.environ.get("PATH", os.defpath)
        if not path:
            return None
        path = path.split(os.pathsep)

        if sys.platform == "win32":
            if os.curdir not in path:
                path.insert(0, os.curdir)

            pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
            if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
                files = [cmd]
            else:
                files = [cmd + ext for ext in pathext]
        else:
            files = [cmd]

        seen = set()
        for dir in path:
            normdir = os.path.normcase(dir)
            if normdir not in seen:
                seen.add(normdir)
                for thefile in files:
                    name = os.path.join(dir, thefile)
                    if _access_check(name, mode):
                        return name
        return None


# python 3.3
try:
    from shutil import get_terminal_size
except ImportError:

    def get_terminal_size(fallback=(80, 24)):
        try:
            import fcntl
            import struct
            import termios
        except ImportError:
            return fallback
        else:
            try:
                # This should work on Linux.
                res = struct.unpack(
                    'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234')
                )
                return (res[1], res[0])
            except Exception:  # noqa: BLE001
                return fallback


# python 3.3
try:
    from subprocess import TimeoutExpired as SubprocessTimeoutExpired
except ImportError:

    class SubprocessTimeoutExpired(Exception):
        pass


# python 3.5
try:
    from contextlib import redirect_stderr
except ImportError:

    @contextlib.contextmanager
    def redirect_stderr(new_target):
        original = sys.stderr
        try:
            sys.stderr = new_target
            yield new_target
        finally:
            sys.stderr = original
PKok\͔������psutil/tests/test_misc.pynu�[���#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Miscellaneous tests."""

import ast
import collections
import errno
import json
import os
import pickle
import socket
import stat
import sys

import psutil
import psutil.tests
from psutil import POSIX
from psutil import WINDOWS
from psutil._common import bcat
from psutil._common import cat
from psutil._common import debug
from psutil._common import isfile_strict
from psutil._common import memoize
from psutil._common import memoize_when_activated
from psutil._common import parse_environ_block
from psutil._common import supports_ipv6
from psutil._common import wrap_numbers
from psutil._compat import PY3
from psutil._compat import FileNotFoundError
from psutil._compat import redirect_stderr
from psutil.tests import CI_TESTING
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import PYTHON_EXE
from psutil.tests import PYTHON_EXE_ENV
from psutil.tests import QEMU_USER
from psutil.tests import SCRIPTS_DIR
from psutil.tests import PsutilTestCase
from psutil.tests import mock
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import reload_module
from psutil.tests import sh
from psutil.tests import system_namespace


# ===================================================================
# --- Test classes' repr(), str(), ...
# ===================================================================


class TestSpecialMethods(PsutilTestCase):
    def test_check_pid_range(self):
        with pytest.raises(OverflowError):
            psutil._psplatform.cext.check_pid_range(2**128)
        with pytest.raises(psutil.NoSuchProcess):
            psutil.Process(2**128)

    def test_process__repr__(self, func=repr):
        p = psutil.Process(self.spawn_testproc().pid)
        r = func(p)
        assert "psutil.Process" in r
        assert "pid=%s" % p.pid in r
        assert "name='%s'" % str(p.name()) in r.replace("name=u'", "name='")
        assert "status=" in r
        assert "exitcode=" not in r
        p.terminate()
        p.wait()
        r = func(p)
        assert "status='terminated'" in r
        assert "exitcode=" in r

        with mock.patch.object(
            psutil.Process,
            "name",
            side_effect=psutil.ZombieProcess(os.getpid()),
        ):
            p = psutil.Process()
            r = func(p)
            assert "pid=%s" % p.pid in r
            assert "status='zombie'" in r
            assert "name=" not in r
        with mock.patch.object(
            psutil.Process,
            "name",
            side_effect=psutil.NoSuchProcess(os.getpid()),
        ):
            p = psutil.Process()
            r = func(p)
            assert "pid=%s" % p.pid in r
            assert "terminated" in r
            assert "name=" not in r
        with mock.patch.object(
            psutil.Process,
            "name",
            side_effect=psutil.AccessDenied(os.getpid()),
        ):
            p = psutil.Process()
            r = func(p)
            assert "pid=%s" % p.pid in r
            assert "name=" not in r

    def test_process__str__(self):
        self.test_process__repr__(func=str)

    def test_error__repr__(self):
        assert repr(psutil.Error()) == "psutil.Error()"

    def test_error__str__(self):
        assert str(psutil.Error()) == ""  # noqa

    def test_no_such_process__repr__(self):
        assert (
            repr(psutil.NoSuchProcess(321))
            == "psutil.NoSuchProcess(pid=321, msg='process no longer exists')"
        )
        assert (
            repr(psutil.NoSuchProcess(321, name="name", msg="msg"))
            == "psutil.NoSuchProcess(pid=321, name='name', msg='msg')"
        )

    def test_no_such_process__str__(self):
        assert (
            str(psutil.NoSuchProcess(321))
            == "process no longer exists (pid=321)"
        )
        assert (
            str(psutil.NoSuchProcess(321, name="name", msg="msg"))
            == "msg (pid=321, name='name')"
        )

    def test_zombie_process__repr__(self):
        assert (
            repr(psutil.ZombieProcess(321))
            == 'psutil.ZombieProcess(pid=321, msg="PID still '
            'exists but it\'s a zombie")'
        )
        assert (
            repr(psutil.ZombieProcess(321, name="name", ppid=320, msg="foo"))
            == "psutil.ZombieProcess(pid=321, ppid=320, name='name',"
            " msg='foo')"
        )

    def test_zombie_process__str__(self):
        assert (
            str(psutil.ZombieProcess(321))
            == "PID still exists but it's a zombie (pid=321)"
        )
        assert (
            str(psutil.ZombieProcess(321, name="name", ppid=320, msg="foo"))
            == "foo (pid=321, ppid=320, name='name')"
        )

    def test_access_denied__repr__(self):
        assert repr(psutil.AccessDenied(321)) == "psutil.AccessDenied(pid=321)"
        assert (
            repr(psutil.AccessDenied(321, name="name", msg="msg"))
            == "psutil.AccessDenied(pid=321, name='name', msg='msg')"
        )

    def test_access_denied__str__(self):
        assert str(psutil.AccessDenied(321)) == "(pid=321)"
        assert (
            str(psutil.AccessDenied(321, name="name", msg="msg"))
            == "msg (pid=321, name='name')"
        )

    def test_timeout_expired__repr__(self):
        assert (
            repr(psutil.TimeoutExpired(5))
            == "psutil.TimeoutExpired(seconds=5, msg='timeout after 5"
            " seconds')"
        )
        assert (
            repr(psutil.TimeoutExpired(5, pid=321, name="name"))
            == "psutil.TimeoutExpired(pid=321, name='name', seconds=5, "
            "msg='timeout after 5 seconds')"
        )

    def test_timeout_expired__str__(self):
        assert str(psutil.TimeoutExpired(5)) == "timeout after 5 seconds"
        assert (
            str(psutil.TimeoutExpired(5, pid=321, name="name"))
            == "timeout after 5 seconds (pid=321, name='name')"
        )

    def test_process__eq__(self):
        p1 = psutil.Process()
        p2 = psutil.Process()
        assert p1 == p2
        p2._ident = (0, 0)
        assert p1 != p2
        assert p1 != 'foo'

    def test_process__hash__(self):
        s = set([psutil.Process(), psutil.Process()])
        assert len(s) == 1


# ===================================================================
# --- Misc, generic, corner cases
# ===================================================================


class TestMisc(PsutilTestCase):
    def test__all__(self):
        dir_psutil = dir(psutil)
        for name in dir_psutil:
            if name in (
                'debug',
                'long',
                'tests',
                'test',
                'PermissionError',
                'ProcessLookupError',
            ):
                continue
            if not name.startswith('_'):
                try:
                    __import__(name)
                except ImportError:
                    if name not in psutil.__all__:
                        fun = getattr(psutil, name)
                        if fun is None:
                            continue
                        if (
                            fun.__doc__ is not None
                            and 'deprecated' not in fun.__doc__.lower()
                        ):
                            raise self.fail('%r not in psutil.__all__' % name)

        # Import 'star' will break if __all__ is inconsistent, see:
        # https://github.com/giampaolo/psutil/issues/656
        # Can't do `from psutil import *` as it won't work on python 3
        # so we simply iterate over __all__.
        for name in psutil.__all__:
            assert name in dir_psutil

    def test_version(self):
        assert (
            '.'.join([str(x) for x in psutil.version_info])
            == psutil.__version__
        )

    def test_process_as_dict_no_new_names(self):
        # See https://github.com/giampaolo/psutil/issues/813
        p = psutil.Process()
        p.foo = '1'
        assert 'foo' not in p.as_dict()

    def test_serialization(self):
        def check(ret):
            json.loads(json.dumps(ret))

            a = pickle.dumps(ret)
            b = pickle.loads(a)
            assert ret == b

        # --- process APIs

        proc = psutil.Process()
        check(psutil.Process().as_dict())

        ns = process_namespace(proc)
        for fun, name in ns.iter(ns.getters, clear_cache=True):
            with self.subTest(proc=proc, name=name):
                try:
                    ret = fun()
                except psutil.Error:
                    pass
                else:
                    check(ret)

        # --- system APIs

        ns = system_namespace()
        for fun, name in ns.iter(ns.getters):
            if name in {"win_service_iter", "win_service_get"}:
                continue
            if QEMU_USER and name == "net_if_stats":
                # OSError: [Errno 38] ioctl(SIOCETHTOOL) not implemented
                continue
            with self.subTest(name=name):
                try:
                    ret = fun()
                except psutil.AccessDenied:
                    pass
                else:
                    check(ret)

        # --- exception classes

        b = pickle.loads(
            pickle.dumps(
                psutil.NoSuchProcess(pid=4567, name='name', msg='msg')
            )
        )
        assert isinstance(b, psutil.NoSuchProcess)
        assert b.pid == 4567
        assert b.name == 'name'
        assert b.msg == 'msg'

        b = pickle.loads(
            pickle.dumps(
                psutil.ZombieProcess(pid=4567, name='name', ppid=42, msg='msg')
            )
        )
        assert isinstance(b, psutil.ZombieProcess)
        assert b.pid == 4567
        assert b.ppid == 42
        assert b.name == 'name'
        assert b.msg == 'msg'

        b = pickle.loads(
            pickle.dumps(psutil.AccessDenied(pid=123, name='name', msg='msg'))
        )
        assert isinstance(b, psutil.AccessDenied)
        assert b.pid == 123
        assert b.name == 'name'
        assert b.msg == 'msg'

        b = pickle.loads(
            pickle.dumps(
                psutil.TimeoutExpired(seconds=33, pid=4567, name='name')
            )
        )
        assert isinstance(b, psutil.TimeoutExpired)
        assert b.seconds == 33
        assert b.pid == 4567
        assert b.name == 'name'

    # # XXX: https://github.com/pypa/setuptools/pull/2896
    # @pytest.mark.skipif(APPVEYOR,
    #     reason="temporarily disabled due to setuptools bug"
    # )
    # def test_setup_script(self):
    #     setup_py = os.path.join(ROOT_DIR, 'setup.py')
    #     if CI_TESTING and not os.path.exists(setup_py):
    #         raise pytest.skip("can't find setup.py")
    #     module = import_module_by_path(setup_py)
    #     self.assertRaises(SystemExit, module.setup)
    #     self.assertEqual(module.get_version(), psutil.__version__)

    def test_ad_on_process_creation(self):
        # We are supposed to be able to instantiate Process also in case
        # of zombie processes or access denied.
        with mock.patch.object(
            psutil.Process, '_get_ident', side_effect=psutil.AccessDenied
        ) as meth:
            psutil.Process()
            assert meth.called

        with mock.patch.object(
            psutil.Process, '_get_ident', side_effect=psutil.ZombieProcess(1)
        ) as meth:
            psutil.Process()
            assert meth.called

        with mock.patch.object(
            psutil.Process, '_get_ident', side_effect=ValueError
        ) as meth:
            with pytest.raises(ValueError):
                psutil.Process()
            assert meth.called

        with mock.patch.object(
            psutil.Process, '_get_ident', side_effect=psutil.NoSuchProcess(1)
        ) as meth:
            with self.assertRaises(psutil.NoSuchProcess):
                psutil.Process()
            assert meth.called

    def test_sanity_version_check(self):
        # see: https://github.com/giampaolo/psutil/issues/564
        with mock.patch(
            "psutil._psplatform.cext.version", return_value="0.0.0"
        ):
            with pytest.raises(ImportError) as cm:
                reload_module(psutil)
            assert "version conflict" in str(cm.value).lower()


# ===================================================================
# --- psutil/_common.py utils
# ===================================================================


class TestMemoizeDecorator(PsutilTestCase):
    def setUp(self):
        self.calls = []

    tearDown = setUp

    def run_against(self, obj, expected_retval=None):
        # no args
        for _ in range(2):
            ret = obj()
            assert self.calls == [((), {})]
            if expected_retval is not None:
                assert ret == expected_retval
        # with args
        for _ in range(2):
            ret = obj(1)
            assert self.calls == [((), {}), ((1,), {})]
            if expected_retval is not None:
                assert ret == expected_retval
        # with args + kwargs
        for _ in range(2):
            ret = obj(1, bar=2)
            assert self.calls == [((), {}), ((1,), {}), ((1,), {'bar': 2})]
            if expected_retval is not None:
                assert ret == expected_retval
        # clear cache
        assert len(self.calls) == 3
        obj.cache_clear()
        ret = obj()
        if expected_retval is not None:
            assert ret == expected_retval
        assert len(self.calls) == 4
        # docstring
        assert obj.__doc__ == "My docstring."

    def test_function(self):
        @memoize
        def foo(*args, **kwargs):
            """My docstring."""
            baseclass.calls.append((args, kwargs))
            return 22

        baseclass = self
        self.run_against(foo, expected_retval=22)

    def test_class(self):
        @memoize
        class Foo:
            """My docstring."""

            def __init__(self, *args, **kwargs):
                baseclass.calls.append((args, kwargs))

            def bar(self):
                return 22

        baseclass = self
        self.run_against(Foo, expected_retval=None)
        assert Foo().bar() == 22

    def test_class_singleton(self):
        # @memoize can be used against classes to create singletons
        @memoize
        class Bar:
            def __init__(self, *args, **kwargs):
                pass

        assert Bar() is Bar()
        assert id(Bar()) == id(Bar())
        assert id(Bar(1)) == id(Bar(1))
        assert id(Bar(1, foo=3)) == id(Bar(1, foo=3))
        assert id(Bar(1)) != id(Bar(2))

    def test_staticmethod(self):
        class Foo:
            @staticmethod
            @memoize
            def bar(*args, **kwargs):
                """My docstring."""
                baseclass.calls.append((args, kwargs))
                return 22

        baseclass = self
        self.run_against(Foo().bar, expected_retval=22)

    def test_classmethod(self):
        class Foo:
            @classmethod
            @memoize
            def bar(cls, *args, **kwargs):
                """My docstring."""
                baseclass.calls.append((args, kwargs))
                return 22

        baseclass = self
        self.run_against(Foo().bar, expected_retval=22)

    def test_original(self):
        # This was the original test before I made it dynamic to test it
        # against different types. Keeping it anyway.
        @memoize
        def foo(*args, **kwargs):
            """Foo docstring."""
            calls.append(None)
            return (args, kwargs)

        calls = []
        # no args
        for _ in range(2):
            ret = foo()
            expected = ((), {})
            assert ret == expected
            assert len(calls) == 1
        # with args
        for _ in range(2):
            ret = foo(1)
            expected = ((1,), {})
            assert ret == expected
            assert len(calls) == 2
        # with args + kwargs
        for _ in range(2):
            ret = foo(1, bar=2)
            expected = ((1,), {'bar': 2})
            assert ret == expected
            assert len(calls) == 3
        # clear cache
        foo.cache_clear()
        ret = foo()
        expected = ((), {})
        assert ret == expected
        assert len(calls) == 4
        # docstring
        assert foo.__doc__ == "Foo docstring."


class TestCommonModule(PsutilTestCase):
    def test_memoize_when_activated(self):
        class Foo:
            @memoize_when_activated
            def foo(self):
                calls.append(None)

        f = Foo()
        calls = []
        f.foo()
        f.foo()
        assert len(calls) == 2

        # activate
        calls = []
        f.foo.cache_activate(f)
        f.foo()
        f.foo()
        assert len(calls) == 1

        # deactivate
        calls = []
        f.foo.cache_deactivate(f)
        f.foo()
        f.foo()
        assert len(calls) == 2

    def test_parse_environ_block(self):
        def k(s):
            return s.upper() if WINDOWS else s

        assert parse_environ_block("a=1\0") == {k("a"): "1"}
        assert parse_environ_block("a=1\0b=2\0\0") == {
            k("a"): "1",
            k("b"): "2",
        }
        assert parse_environ_block("a=1\0b=\0\0") == {k("a"): "1", k("b"): ""}
        # ignore everything after \0\0
        assert parse_environ_block("a=1\0b=2\0\0c=3\0") == {
            k("a"): "1",
            k("b"): "2",
        }
        # ignore everything that is not an assignment
        assert parse_environ_block("xxx\0a=1\0") == {k("a"): "1"}
        assert parse_environ_block("a=1\0=b=2\0") == {k("a"): "1"}
        # do not fail if the block is incomplete
        assert parse_environ_block("a=1\0b=2") == {k("a"): "1"}

    def test_supports_ipv6(self):
        self.addCleanup(supports_ipv6.cache_clear)
        if supports_ipv6():
            with mock.patch('psutil._common.socket') as s:
                s.has_ipv6 = False
                supports_ipv6.cache_clear()
                assert not supports_ipv6()

            supports_ipv6.cache_clear()
            with mock.patch(
                'psutil._common.socket.socket', side_effect=socket.error
            ) as s:
                assert not supports_ipv6()
                assert s.called

            supports_ipv6.cache_clear()
            with mock.patch(
                'psutil._common.socket.socket', side_effect=socket.gaierror
            ) as s:
                assert not supports_ipv6()
                supports_ipv6.cache_clear()
                assert s.called

            supports_ipv6.cache_clear()
            with mock.patch(
                'psutil._common.socket.socket.bind',
                side_effect=socket.gaierror,
            ) as s:
                assert not supports_ipv6()
                supports_ipv6.cache_clear()
                assert s.called
        else:
            with pytest.raises(socket.error):
                sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
                try:
                    sock.bind(("::1", 0))
                finally:
                    sock.close()

    def test_isfile_strict(self):
        this_file = os.path.abspath(__file__)
        assert isfile_strict(this_file)
        assert not isfile_strict(os.path.dirname(this_file))
        with mock.patch(
            'psutil._common.os.stat', side_effect=OSError(errno.EPERM, "foo")
        ):
            with pytest.raises(OSError):
                isfile_strict(this_file)
        with mock.patch(
            'psutil._common.os.stat', side_effect=OSError(errno.EACCES, "foo")
        ):
            with pytest.raises(OSError):
                isfile_strict(this_file)
        with mock.patch(
            'psutil._common.os.stat', side_effect=OSError(errno.ENOENT, "foo")
        ):
            assert not isfile_strict(this_file)
        with mock.patch('psutil._common.stat.S_ISREG', return_value=False):
            assert not isfile_strict(this_file)

    def test_debug(self):
        if PY3:
            from io import StringIO
        else:
            from StringIO import StringIO

        with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
            with redirect_stderr(StringIO()) as f:
                debug("hello")
                sys.stderr.flush()
        msg = f.getvalue()
        assert msg.startswith("psutil-debug"), msg
        assert "hello" in msg
        assert __file__.replace('.pyc', '.py') in msg

        # supposed to use repr(exc)
        with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
            with redirect_stderr(StringIO()) as f:
                debug(ValueError("this is an error"))
        msg = f.getvalue()
        assert "ignoring ValueError" in msg
        assert "'this is an error'" in msg

        # supposed to use str(exc), because of extra info about file name
        with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
            with redirect_stderr(StringIO()) as f:
                exc = OSError(2, "no such file")
                exc.filename = "/foo"
                debug(exc)
        msg = f.getvalue()
        assert "no such file" in msg
        assert "/foo" in msg

    def test_cat_bcat(self):
        testfn = self.get_testfn()
        with open(testfn, "w") as f:
            f.write("foo")
        assert cat(testfn) == "foo"
        assert bcat(testfn) == b"foo"
        with pytest.raises(FileNotFoundError):
            cat(testfn + '-invalid')
        with pytest.raises(FileNotFoundError):
            bcat(testfn + '-invalid')
        assert cat(testfn + '-invalid', fallback="bar") == "bar"
        assert bcat(testfn + '-invalid', fallback="bar") == "bar"


# ===================================================================
# --- Tests for wrap_numbers() function.
# ===================================================================


nt = collections.namedtuple('foo', 'a b c')


class TestWrapNumbers(PsutilTestCase):
    def setUp(self):
        wrap_numbers.cache_clear()

    tearDown = setUp

    def test_first_call(self):
        input = {'disk1': nt(5, 5, 5)}
        assert wrap_numbers(input, 'disk_io') == input

    def test_input_hasnt_changed(self):
        input = {'disk1': nt(5, 5, 5)}
        assert wrap_numbers(input, 'disk_io') == input
        assert wrap_numbers(input, 'disk_io') == input

    def test_increase_but_no_wrap(self):
        input = {'disk1': nt(5, 5, 5)}
        assert wrap_numbers(input, 'disk_io') == input
        input = {'disk1': nt(10, 15, 20)}
        assert wrap_numbers(input, 'disk_io') == input
        input = {'disk1': nt(20, 25, 30)}
        assert wrap_numbers(input, 'disk_io') == input
        input = {'disk1': nt(20, 25, 30)}
        assert wrap_numbers(input, 'disk_io') == input

    def test_wrap(self):
        # let's say 100 is the threshold
        input = {'disk1': nt(100, 100, 100)}
        assert wrap_numbers(input, 'disk_io') == input
        # first wrap restarts from 10
        input = {'disk1': nt(100, 100, 10)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 110)}
        # then it remains the same
        input = {'disk1': nt(100, 100, 10)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 110)}
        # then it goes up
        input = {'disk1': nt(100, 100, 90)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 190)}
        # then it wraps again
        input = {'disk1': nt(100, 100, 20)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 210)}
        # and remains the same
        input = {'disk1': nt(100, 100, 20)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(100, 100, 210)}
        # now wrap another num
        input = {'disk1': nt(50, 100, 20)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(150, 100, 210)}
        # and again
        input = {'disk1': nt(40, 100, 20)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(190, 100, 210)}
        # keep it the same
        input = {'disk1': nt(40, 100, 20)}
        assert wrap_numbers(input, 'disk_io') == {'disk1': nt(190, 100, 210)}

    def test_changing_keys(self):
        # Emulate a case where the second call to disk_io()
        # (or whatever) provides a new disk, then the new disk
        # disappears on the third call.
        input = {'disk1': nt(5, 5, 5)}
        assert wrap_numbers(input, 'disk_io') == input
        input = {'disk1': nt(5, 5, 5), 'disk2': nt(7, 7, 7)}
        assert wrap_numbers(input, 'disk_io') == input
        input = {'disk1': nt(8, 8, 8)}
        assert wrap_numbers(input, 'disk_io') == input

    def test_changing_keys_w_wrap(self):
        input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)}
        assert wrap_numbers(input, 'disk_io') == input
        # disk 2 wraps
        input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 10)}
        assert wrap_numbers(input, 'disk_io') == {
            'disk1': nt(50, 50, 50),
            'disk2': nt(100, 100, 110),
        }
        # disk 2 disappears
        input = {'disk1': nt(50, 50, 50)}
        assert wrap_numbers(input, 'disk_io') == input

        # then it appears again; the old wrap is supposed to be
        # gone.
        input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)}
        assert wrap_numbers(input, 'disk_io') == input
        # remains the same
        input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 100)}
        assert wrap_numbers(input, 'disk_io') == input
        # and then wraps again
        input = {'disk1': nt(50, 50, 50), 'disk2': nt(100, 100, 10)}
        assert wrap_numbers(input, 'disk_io') == {
            'disk1': nt(50, 50, 50),
            'disk2': nt(100, 100, 110),
        }

    def test_real_data(self):
        d = {
            'nvme0n1': (300, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048),
            'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8),
            'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28),
            'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348),
        }
        assert wrap_numbers(d, 'disk_io') == d
        assert wrap_numbers(d, 'disk_io') == d
        # decrease this   ↓
        d = {
            'nvme0n1': (100, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048),
            'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8),
            'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28),
            'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348),
        }
        out = wrap_numbers(d, 'disk_io')
        assert out['nvme0n1'][0] == 400

    # --- cache tests

    def test_cache_first_call(self):
        input = {'disk1': nt(5, 5, 5)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        assert cache[1] == {'disk_io': {}}
        assert cache[2] == {'disk_io': {}}

    def test_cache_call_twice(self):
        input = {'disk1': nt(5, 5, 5)}
        wrap_numbers(input, 'disk_io')
        input = {'disk1': nt(10, 10, 10)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        assert cache[1] == {
            'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}
        }
        assert cache[2] == {'disk_io': {}}

    def test_cache_wrap(self):
        # let's say 100 is the threshold
        input = {'disk1': nt(100, 100, 100)}
        wrap_numbers(input, 'disk_io')

        # first wrap restarts from 10
        input = {'disk1': nt(100, 100, 10)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        assert cache[1] == {
            'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100}
        }
        assert cache[2] == {'disk_io': {'disk1': set([('disk1', 2)])}}

        def check_cache_info():
            cache = wrap_numbers.cache_info()
            assert cache[1] == {
                'disk_io': {
                    ('disk1', 0): 0,
                    ('disk1', 1): 0,
                    ('disk1', 2): 100,
                }
            }
            assert cache[2] == {'disk_io': {'disk1': set([('disk1', 2)])}}

        # then it remains the same
        input = {'disk1': nt(100, 100, 10)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        check_cache_info()

        # then it goes up
        input = {'disk1': nt(100, 100, 90)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        check_cache_info()

        # then it wraps again
        input = {'disk1': nt(100, 100, 20)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        assert cache[1] == {
            'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 190}
        }
        assert cache[2] == {'disk_io': {'disk1': set([('disk1', 2)])}}

    def test_cache_changing_keys(self):
        input = {'disk1': nt(5, 5, 5)}
        wrap_numbers(input, 'disk_io')
        input = {'disk1': nt(5, 5, 5), 'disk2': nt(7, 7, 7)}
        wrap_numbers(input, 'disk_io')
        cache = wrap_numbers.cache_info()
        assert cache[0] == {'disk_io': input}
        assert cache[1] == {
            'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}
        }
        assert cache[2] == {'disk_io': {}}

    def test_cache_clear(self):
        input = {'disk1': nt(5, 5, 5)}
        wrap_numbers(input, 'disk_io')
        wrap_numbers(input, 'disk_io')
        wrap_numbers.cache_clear('disk_io')
        assert wrap_numbers.cache_info() == ({}, {}, {})
        wrap_numbers.cache_clear('disk_io')
        wrap_numbers.cache_clear('?!?')

    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_cache_clear_public_apis(self):
        if not psutil.disk_io_counters() or not psutil.net_io_counters():
            raise pytest.skip("no disks or NICs available")
        psutil.disk_io_counters()
        psutil.net_io_counters()
        caches = wrap_numbers.cache_info()
        for cache in caches:
            assert 'psutil.disk_io_counters' in cache
            assert 'psutil.net_io_counters' in cache

        psutil.disk_io_counters.cache_clear()
        caches = wrap_numbers.cache_info()
        for cache in caches:
            assert 'psutil.net_io_counters' in cache
            assert 'psutil.disk_io_counters' not in cache

        psutil.net_io_counters.cache_clear()
        caches = wrap_numbers.cache_info()
        assert caches == ({}, {}, {})


# ===================================================================
# --- Example script tests
# ===================================================================


@pytest.mark.skipif(
    not os.path.exists(SCRIPTS_DIR), reason="can't locate scripts directory"
)
class TestScripts(PsutilTestCase):
    """Tests for scripts in the "scripts" directory."""

    @staticmethod
    def assert_stdout(exe, *args, **kwargs):
        kwargs.setdefault("env", PYTHON_EXE_ENV)
        exe = '%s' % os.path.join(SCRIPTS_DIR, exe)
        cmd = [PYTHON_EXE, exe]
        for arg in args:
            cmd.append(arg)
        try:
            out = sh(cmd, **kwargs).strip()
        except RuntimeError as err:
            if 'AccessDenied' in str(err):
                return str(err)
            else:
                raise
        assert out, out
        return out

    @staticmethod
    def assert_syntax(exe):
        exe = os.path.join(SCRIPTS_DIR, exe)
        with open(exe, encoding="utf8") if PY3 else open(exe) as f:
            src = f.read()
        ast.parse(src)

    def test_coverage(self):
        # make sure all example scripts have a test method defined
        meths = dir(self)
        for name in os.listdir(SCRIPTS_DIR):
            if name.endswith('.py'):
                if 'test_' + os.path.splitext(name)[0] not in meths:
                    # self.assert_stdout(name)
                    raise self.fail(
                        'no test defined for %r script'
                        % os.path.join(SCRIPTS_DIR, name)
                    )

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_executable(self):
        for root, dirs, files in os.walk(SCRIPTS_DIR):
            for file in files:
                if file.endswith('.py'):
                    path = os.path.join(root, file)
                    if not stat.S_IXUSR & os.stat(path)[stat.ST_MODE]:
                        raise self.fail('%r is not executable' % path)

    def test_disk_usage(self):
        self.assert_stdout('disk_usage.py')

    def test_free(self):
        self.assert_stdout('free.py')

    def test_meminfo(self):
        self.assert_stdout('meminfo.py')

    def test_procinfo(self):
        self.assert_stdout('procinfo.py', str(os.getpid()))

    @pytest.mark.skipif(CI_TESTING and not psutil.users(), reason="no users")
    def test_who(self):
        self.assert_stdout('who.py')

    def test_ps(self):
        self.assert_stdout('ps.py')

    def test_pstree(self):
        self.assert_stdout('pstree.py')

    def test_netstat(self):
        self.assert_stdout('netstat.py')

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_ifconfig(self):
        self.assert_stdout('ifconfig.py')

    @pytest.mark.skipif(not HAS_MEMORY_MAPS, reason="not supported")
    def test_pmap(self):
        self.assert_stdout('pmap.py', str(os.getpid()))

    def test_procsmem(self):
        if 'uss' not in psutil.Process().memory_full_info()._fields:
            raise pytest.skip("not supported")
        self.assert_stdout('procsmem.py')

    def test_killall(self):
        self.assert_syntax('killall.py')

    def test_nettop(self):
        self.assert_syntax('nettop.py')

    def test_top(self):
        self.assert_syntax('top.py')

    def test_iotop(self):
        self.assert_syntax('iotop.py')

    def test_pidof(self):
        output = self.assert_stdout('pidof.py', psutil.Process().name())
        assert str(os.getpid()) in output

    @pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
    def test_winservices(self):
        self.assert_stdout('winservices.py')

    def test_cpu_distribution(self):
        self.assert_syntax('cpu_distribution.py')

    @pytest.mark.skipif(not HAS_SENSORS_TEMPERATURES, reason="not supported")
    def test_temperatures(self):
        if not psutil.sensors_temperatures():
            raise pytest.skip("no temperatures")
        self.assert_stdout('temperatures.py')

    @pytest.mark.skipif(not HAS_SENSORS_FANS, reason="not supported")
    def test_fans(self):
        if not psutil.sensors_fans():
            raise pytest.skip("no fans")
        self.assert_stdout('fans.py')

    @pytest.mark.skipif(not HAS_SENSORS_BATTERY, reason="not supported")
    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_battery(self):
        self.assert_stdout('battery.py')

    @pytest.mark.skipif(not HAS_SENSORS_BATTERY, reason="not supported")
    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_sensors(self):
        self.assert_stdout('sensors.py')
PKok\X���N�Npsutil/tests/test_bsd.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# TODO: (FreeBSD) add test for comparing connections with 'sockstat' cmd.


"""Tests specific to all BSD platforms."""


import datetime
import os
import re
import time

import psutil
from psutil import BSD
from psutil import FREEBSD
from psutil import NETBSD
from psutil import OPENBSD
from psutil.tests import HAS_BATTERY
from psutil.tests import TOLERANCE_SYS_MEM
from psutil.tests import PsutilTestCase
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import spawn_testproc
from psutil.tests import terminate
from psutil.tests import which


if BSD:
    from psutil._psutil_posix import getpagesize

    PAGESIZE = getpagesize()
    # muse requires root privileges
    MUSE_AVAILABLE = os.getuid() == 0 and which('muse')
else:
    PAGESIZE = None
    MUSE_AVAILABLE = False


def sysctl(cmdline):
    """Expects a sysctl command with an argument and parse the result
    returning only the value of interest.
    """
    result = sh("sysctl " + cmdline)
    if FREEBSD:
        result = result[result.find(": ") + 2 :]
    elif OPENBSD or NETBSD:
        result = result[result.find("=") + 1 :]
    try:
        return int(result)
    except ValueError:
        return result


def muse(field):
    """Thin wrapper around 'muse' cmdline utility."""
    out = sh('muse')
    for line in out.split('\n'):
        if line.startswith(field):
            break
    else:
        raise ValueError("line not found")
    return int(line.split()[1])


# =====================================================================
# --- All BSD*
# =====================================================================


@pytest.mark.skipif(not BSD, reason="BSD only")
class BSDTestCase(PsutilTestCase):
    """Generic tests common to all BSD variants."""

    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    @pytest.mark.skipif(NETBSD, reason="-o lstart doesn't work on NETBSD")
    def test_process_create_time(self):
        output = sh("ps -o lstart -p %s" % self.pid)
        start_ps = output.replace('STARTED', '').strip()
        start_psutil = psutil.Process(self.pid).create_time()
        start_psutil = time.strftime(
            "%a %b %e %H:%M:%S %Y", time.localtime(start_psutil)
        )
        assert start_ps == start_psutil

    def test_disks(self):
        # test psutil.disk_usage() and psutil.disk_partitions()
        # against "df -a"
        def df(path):
            out = sh('df -k "%s"' % path).strip()
            lines = out.split('\n')
            lines.pop(0)
            line = lines.pop(0)
            dev, total, used, free = line.split()[:4]
            if dev == 'none':
                dev = ''
            total = int(total) * 1024
            used = int(used) * 1024
            free = int(free) * 1024
            return dev, total, used, free

        for part in psutil.disk_partitions(all=False):
            usage = psutil.disk_usage(part.mountpoint)
            dev, total, used, free = df(part.mountpoint)
            assert part.device == dev
            assert usage.total == total
            # 10 MB tolerance
            if abs(usage.free - free) > 10 * 1024 * 1024:
                raise self.fail("psutil=%s, df=%s" % (usage.free, free))
            if abs(usage.used - used) > 10 * 1024 * 1024:
                raise self.fail("psutil=%s, df=%s" % (usage.used, used))

    @pytest.mark.skipif(not which('sysctl'), reason="sysctl cmd not available")
    def test_cpu_count_logical(self):
        syst = sysctl("hw.ncpu")
        assert psutil.cpu_count(logical=True) == syst

    @pytest.mark.skipif(not which('sysctl'), reason="sysctl cmd not available")
    @pytest.mark.skipif(
        NETBSD, reason="skipped on NETBSD"  # we check /proc/meminfo
    )
    def test_virtual_memory_total(self):
        num = sysctl('hw.physmem')
        assert num == psutil.virtual_memory().total

    @pytest.mark.skipif(
        not which('ifconfig'), reason="ifconfig cmd not available"
    )
    def test_net_if_stats(self):
        for name, stats in psutil.net_if_stats().items():
            try:
                out = sh("ifconfig %s" % name)
            except RuntimeError:
                pass
            else:
                assert stats.isup == ('RUNNING' in out)
                if "mtu" in out:
                    assert stats.mtu == int(re.findall(r'mtu (\d+)', out)[0])


# =====================================================================
# --- FreeBSD
# =====================================================================


@pytest.mark.skipif(not FREEBSD, reason="FREEBSD only")
class FreeBSDPsutilTestCase(PsutilTestCase):
    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    @retry_on_failure()
    def test_memory_maps(self):
        out = sh('procstat -v %s' % self.pid)
        maps = psutil.Process(self.pid).memory_maps(grouped=False)
        lines = out.split('\n')[1:]
        while lines:
            line = lines.pop()
            fields = line.split()
            _, start, stop, _perms, res = fields[:5]
            map = maps.pop()
            assert "%s-%s" % (start, stop) == map.addr
            assert int(res) == map.rss
            if not map.path.startswith('['):
                assert fields[10] == map.path

    def test_exe(self):
        out = sh('procstat -b %s' % self.pid)
        assert psutil.Process(self.pid).exe() == out.split('\n')[1].split()[-1]

    def test_cmdline(self):
        out = sh('procstat -c %s' % self.pid)
        assert ' '.join(psutil.Process(self.pid).cmdline()) == ' '.join(
            out.split('\n')[1].split()[2:]
        )

    def test_uids_gids(self):
        out = sh('procstat -s %s' % self.pid)
        euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8]
        p = psutil.Process(self.pid)
        uids = p.uids()
        gids = p.gids()
        assert uids.real == int(ruid)
        assert uids.effective == int(euid)
        assert uids.saved == int(suid)
        assert gids.real == int(rgid)
        assert gids.effective == int(egid)
        assert gids.saved == int(sgid)

    @retry_on_failure()
    def test_ctx_switches(self):
        tested = []
        out = sh('procstat -r %s' % self.pid)
        p = psutil.Process(self.pid)
        for line in out.split('\n'):
            line = line.lower().strip()
            if ' voluntary context' in line:
                pstat_value = int(line.split()[-1])
                psutil_value = p.num_ctx_switches().voluntary
                assert pstat_value == psutil_value
                tested.append(None)
            elif ' involuntary context' in line:
                pstat_value = int(line.split()[-1])
                psutil_value = p.num_ctx_switches().involuntary
                assert pstat_value == psutil_value
                tested.append(None)
        if len(tested) != 2:
            raise RuntimeError("couldn't find lines match in procstat out")

    @retry_on_failure()
    def test_cpu_times(self):
        tested = []
        out = sh('procstat -r %s' % self.pid)
        p = psutil.Process(self.pid)
        for line in out.split('\n'):
            line = line.lower().strip()
            if 'user time' in line:
                pstat_value = float('0.' + line.split()[-1].split('.')[-1])
                psutil_value = p.cpu_times().user
                assert pstat_value == psutil_value
                tested.append(None)
            elif 'system time' in line:
                pstat_value = float('0.' + line.split()[-1].split('.')[-1])
                psutil_value = p.cpu_times().system
                assert pstat_value == psutil_value
                tested.append(None)
        if len(tested) != 2:
            raise RuntimeError("couldn't find lines match in procstat out")


@pytest.mark.skipif(not FREEBSD, reason="FREEBSD only")
class FreeBSDSystemTestCase(PsutilTestCase):
    @staticmethod
    def parse_swapinfo():
        # the last line is always the total
        output = sh("swapinfo -k").splitlines()[-1]
        parts = re.split(r'\s+', output)

        if not parts:
            raise ValueError("Can't parse swapinfo: %s" % output)

        # the size is in 1k units, so multiply by 1024
        total, used, free = (int(p) * 1024 for p in parts[1:4])
        return total, used, free

    def test_cpu_frequency_against_sysctl(self):
        # Currently only cpu 0 is frequency is supported in FreeBSD
        # All other cores use the same frequency.
        sensor = "dev.cpu.0.freq"
        try:
            sysctl_result = int(sysctl(sensor))
        except RuntimeError:
            raise pytest.skip("frequencies not supported by kernel")
        assert psutil.cpu_freq().current == sysctl_result

        sensor = "dev.cpu.0.freq_levels"
        sysctl_result = sysctl(sensor)
        # sysctl returns a string of the format:
        # <freq_level_1>/<voltage_level_1> <freq_level_2>/<voltage_level_2>...
        # Ordered highest available to lowest available.
        max_freq = int(sysctl_result.split()[0].split("/")[0])
        min_freq = int(sysctl_result.split()[-1].split("/")[0])
        assert psutil.cpu_freq().max == max_freq
        assert psutil.cpu_freq().min == min_freq

    # --- virtual_memory(); tests against sysctl

    @retry_on_failure()
    def test_vmem_active(self):
        syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE
        assert abs(psutil.virtual_memory().active - syst) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_inactive(self):
        syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE
        assert abs(psutil.virtual_memory().inactive - syst) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_wired(self):
        syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE
        assert abs(psutil.virtual_memory().wired - syst) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_cached(self):
        syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE
        assert abs(psutil.virtual_memory().cached - syst) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_free(self):
        syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE
        assert abs(psutil.virtual_memory().free - syst) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_buffers(self):
        syst = sysctl("vfs.bufspace")
        assert abs(psutil.virtual_memory().buffers - syst) < TOLERANCE_SYS_MEM

    # --- virtual_memory(); tests against muse

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    def test_muse_vmem_total(self):
        num = muse('Total')
        assert psutil.virtual_memory().total == num

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_active(self):
        num = muse('Active')
        assert abs(psutil.virtual_memory().active - num) < TOLERANCE_SYS_MEM

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_inactive(self):
        num = muse('Inactive')
        assert abs(psutil.virtual_memory().inactive - num) < TOLERANCE_SYS_MEM

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_wired(self):
        num = muse('Wired')
        assert abs(psutil.virtual_memory().wired - num) < TOLERANCE_SYS_MEM

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_cached(self):
        num = muse('Cache')
        assert abs(psutil.virtual_memory().cached - num) < TOLERANCE_SYS_MEM

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_free(self):
        num = muse('Free')
        assert abs(psutil.virtual_memory().free - num) < TOLERANCE_SYS_MEM

    @pytest.mark.skipif(not MUSE_AVAILABLE, reason="muse not installed")
    @retry_on_failure()
    def test_muse_vmem_buffers(self):
        num = muse('Buffer')
        assert abs(psutil.virtual_memory().buffers - num) < TOLERANCE_SYS_MEM

    def test_cpu_stats_ctx_switches(self):
        assert (
            abs(
                psutil.cpu_stats().ctx_switches
                - sysctl('vm.stats.sys.v_swtch')
            )
            < 1000
        )

    def test_cpu_stats_interrupts(self):
        assert (
            abs(psutil.cpu_stats().interrupts - sysctl('vm.stats.sys.v_intr'))
            < 1000
        )

    def test_cpu_stats_soft_interrupts(self):
        assert (
            abs(
                psutil.cpu_stats().soft_interrupts
                - sysctl('vm.stats.sys.v_soft')
            )
            < 1000
        )

    @retry_on_failure()
    def test_cpu_stats_syscalls(self):
        # pretty high tolerance but it looks like it's OK.
        assert (
            abs(psutil.cpu_stats().syscalls - sysctl('vm.stats.sys.v_syscall'))
            < 200000
        )

    # def test_cpu_stats_traps(self):
    #    self.assertAlmostEqual(psutil.cpu_stats().traps,
    #                           sysctl('vm.stats.sys.v_trap'), delta=1000)

    # --- swap memory

    def test_swapmem_free(self):
        _total, _used, free = self.parse_swapinfo()
        assert abs(psutil.swap_memory().free - free) < TOLERANCE_SYS_MEM

    def test_swapmem_used(self):
        _total, used, _free = self.parse_swapinfo()
        assert abs(psutil.swap_memory().used - used) < TOLERANCE_SYS_MEM

    def test_swapmem_total(self):
        total, _used, _free = self.parse_swapinfo()
        assert abs(psutil.swap_memory().total - total) < TOLERANCE_SYS_MEM

    # --- others

    def test_boot_time(self):
        s = sysctl('sysctl kern.boottime')
        s = s[s.find(" sec = ") + 7 :]
        s = s[: s.find(',')]
        btime = int(s)
        assert btime == psutil.boot_time()

    # --- sensors_battery

    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_sensors_battery(self):
        def secs2hours(secs):
            m, _s = divmod(secs, 60)
            h, m = divmod(m, 60)
            return "%d:%02d" % (h, m)

        out = sh("acpiconf -i 0")
        fields = dict(
            [(x.split('\t')[0], x.split('\t')[-1]) for x in out.split("\n")]
        )
        metrics = psutil.sensors_battery()
        percent = int(fields['Remaining capacity:'].replace('%', ''))
        remaining_time = fields['Remaining time:']
        assert metrics.percent == percent
        if remaining_time == 'unknown':
            assert metrics.secsleft == psutil.POWER_TIME_UNLIMITED
        else:
            assert secs2hours(metrics.secsleft) == remaining_time

    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_sensors_battery_against_sysctl(self):
        assert psutil.sensors_battery().percent == sysctl(
            "hw.acpi.battery.life"
        )
        assert psutil.sensors_battery().power_plugged == (
            sysctl("hw.acpi.acline") == 1
        )
        secsleft = psutil.sensors_battery().secsleft
        if secsleft < 0:
            assert sysctl("hw.acpi.battery.time") == -1
        else:
            assert secsleft == sysctl("hw.acpi.battery.time") * 60

    @pytest.mark.skipif(HAS_BATTERY, reason="has battery")
    def test_sensors_battery_no_battery(self):
        # If no battery is present one of these calls is supposed
        # to fail, see:
        # https://github.com/giampaolo/psutil/issues/1074
        with pytest.raises(RuntimeError):
            sysctl("hw.acpi.battery.life")
            sysctl("hw.acpi.battery.time")
            sysctl("hw.acpi.acline")
        assert psutil.sensors_battery() is None

    # --- sensors_temperatures

    def test_sensors_temperatures_against_sysctl(self):
        num_cpus = psutil.cpu_count(True)
        for cpu in range(num_cpus):
            sensor = "dev.cpu.%s.temperature" % cpu
            # sysctl returns a string in the format 46.0C
            try:
                sysctl_result = int(float(sysctl(sensor)[:-1]))
            except RuntimeError:
                raise pytest.skip("temperatures not supported by kernel")
            assert (
                abs(
                    psutil.sensors_temperatures()["coretemp"][cpu].current
                    - sysctl_result
                )
                < 10
            )

            sensor = "dev.cpu.%s.coretemp.tjmax" % cpu
            sysctl_result = int(float(sysctl(sensor)[:-1]))
            assert (
                psutil.sensors_temperatures()["coretemp"][cpu].high
                == sysctl_result
            )


# =====================================================================
# --- OpenBSD
# =====================================================================


@pytest.mark.skipif(not OPENBSD, reason="OPENBSD only")
class OpenBSDTestCase(PsutilTestCase):
    def test_boot_time(self):
        s = sysctl('kern.boottime')
        sys_bt = datetime.datetime.strptime(s, "%a %b %d %H:%M:%S %Y")
        psutil_bt = datetime.datetime.fromtimestamp(psutil.boot_time())
        assert sys_bt == psutil_bt


# =====================================================================
# --- NetBSD
# =====================================================================


@pytest.mark.skipif(not NETBSD, reason="NETBSD only")
class NetBSDTestCase(PsutilTestCase):
    @staticmethod
    def parse_meminfo(look_for):
        with open('/proc/meminfo') as f:
            for line in f:
                if line.startswith(look_for):
                    return int(line.split()[1]) * 1024
        raise ValueError("can't find %s" % look_for)

    # --- virtual mem

    def test_vmem_total(self):
        assert psutil.virtual_memory().total == self.parse_meminfo("MemTotal:")

    def test_vmem_free(self):
        assert (
            abs(psutil.virtual_memory().free - self.parse_meminfo("MemFree:"))
            < TOLERANCE_SYS_MEM
        )

    def test_vmem_buffers(self):
        assert (
            abs(
                psutil.virtual_memory().buffers
                - self.parse_meminfo("Buffers:")
            )
            < TOLERANCE_SYS_MEM
        )

    def test_vmem_shared(self):
        assert (
            abs(
                psutil.virtual_memory().shared
                - self.parse_meminfo("MemShared:")
            )
            < TOLERANCE_SYS_MEM
        )

    def test_vmem_cached(self):
        assert (
            abs(psutil.virtual_memory().cached - self.parse_meminfo("Cached:"))
            < TOLERANCE_SYS_MEM
        )

    # --- swap mem

    def test_swapmem_total(self):
        assert (
            abs(psutil.swap_memory().total - self.parse_meminfo("SwapTotal:"))
            < TOLERANCE_SYS_MEM
        )

    def test_swapmem_free(self):
        assert (
            abs(psutil.swap_memory().free - self.parse_meminfo("SwapFree:"))
            < TOLERANCE_SYS_MEM
        )

    def test_swapmem_used(self):
        smem = psutil.swap_memory()
        assert smem.used == smem.total - smem.free

    # --- others

    def test_cpu_stats_interrupts(self):
        with open('/proc/stat', 'rb') as f:
            for line in f:
                if line.startswith(b'intr'):
                    interrupts = int(line.split()[1])
                    break
            else:
                raise ValueError("couldn't find line")
        assert abs(psutil.cpu_stats().interrupts - interrupts) < 1000

    def test_cpu_stats_ctx_switches(self):
        with open('/proc/stat', 'rb') as f:
            for line in f:
                if line.startswith(b'ctxt'):
                    ctx_switches = int(line.split()[1])
                    break
            else:
                raise ValueError("couldn't find line")
        assert abs(psutil.cpu_stats().ctx_switches - ctx_switches) < 1000
PKok\�;�3<3<psutil/tests/test_memleaks.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for detecting function memory leaks (typically the ones
implemented in C). It does so by calling a function many times and
checking whether process memory usage keeps increasing between
calls or over time.
Note that this may produce false positives (especially on Windows
for some reason).
PyPy appears to be completely unstable for this framework, probably
because of how its JIT handles memory, so tests are skipped.
"""

from __future__ import print_function

import functools
import os
import platform

import psutil
import psutil._common
from psutil import LINUX
from psutil import MACOS
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import ProcessLookupError
from psutil._compat import super
from psutil.tests import HAS_CPU_AFFINITY
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_IONICE
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_PROC_CPU_NUM
from psutil.tests import HAS_PROC_IO_COUNTERS
from psutil.tests import HAS_RLIMIT
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import QEMU_USER
from psutil.tests import TestMemoryLeak
from psutil.tests import create_sockets
from psutil.tests import get_testfn
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import skip_on_access_denied
from psutil.tests import spawn_testproc
from psutil.tests import system_namespace
from psutil.tests import terminate


cext = psutil._psplatform.cext
thisproc = psutil.Process()
FEW_TIMES = 5


def fewtimes_if_linux():
    """Decorator for those Linux functions which are implemented in pure
    Python, and which we want to run faster.
    """

    def decorator(fun):
        @functools.wraps(fun)
        def wrapper(self, *args, **kwargs):
            if LINUX:
                before = self.__class__.times
                try:
                    self.__class__.times = FEW_TIMES
                    return fun(self, *args, **kwargs)
                finally:
                    self.__class__.times = before
            else:
                return fun(self, *args, **kwargs)

        return wrapper

    return decorator


# ===================================================================
# Process class
# ===================================================================


class TestProcessObjectLeaks(TestMemoryLeak):
    """Test leaks of Process class methods."""

    proc = thisproc

    def test_coverage(self):
        ns = process_namespace(None)
        ns.test_class_coverage(self, ns.getters + ns.setters)

    @fewtimes_if_linux()
    def test_name(self):
        self.execute(self.proc.name)

    @fewtimes_if_linux()
    def test_cmdline(self):
        self.execute(self.proc.cmdline)

    @fewtimes_if_linux()
    def test_exe(self):
        self.execute(self.proc.exe)

    @fewtimes_if_linux()
    def test_ppid(self):
        self.execute(self.proc.ppid)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @fewtimes_if_linux()
    def test_uids(self):
        self.execute(self.proc.uids)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @fewtimes_if_linux()
    def test_gids(self):
        self.execute(self.proc.gids)

    @fewtimes_if_linux()
    def test_status(self):
        self.execute(self.proc.status)

    def test_nice(self):
        self.execute(self.proc.nice)

    def test_nice_set(self):
        niceness = thisproc.nice()
        self.execute(lambda: self.proc.nice(niceness))

    @pytest.mark.skipif(not HAS_IONICE, reason="not supported")
    def test_ionice(self):
        self.execute(self.proc.ionice)

    @pytest.mark.skipif(not HAS_IONICE, reason="not supported")
    def test_ionice_set(self):
        if WINDOWS:
            value = thisproc.ionice()
            self.execute(lambda: self.proc.ionice(value))
        else:
            self.execute(lambda: self.proc.ionice(psutil.IOPRIO_CLASS_NONE))
            fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0)
            self.execute_w_exc(OSError, fun)

    @pytest.mark.skipif(not HAS_PROC_IO_COUNTERS, reason="not supported")
    @fewtimes_if_linux()
    def test_io_counters(self):
        self.execute(self.proc.io_counters)

    @pytest.mark.skipif(POSIX, reason="worthless on POSIX")
    def test_username(self):
        # always open 1 handle on Windows (only once)
        psutil.Process().username()
        self.execute(self.proc.username)

    @fewtimes_if_linux()
    def test_create_time(self):
        self.execute(self.proc.create_time)

    @fewtimes_if_linux()
    @skip_on_access_denied(only_if=OPENBSD)
    def test_num_threads(self):
        self.execute(self.proc.num_threads)

    @pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
    def test_num_handles(self):
        self.execute(self.proc.num_handles)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @fewtimes_if_linux()
    def test_num_fds(self):
        self.execute(self.proc.num_fds)

    @fewtimes_if_linux()
    def test_num_ctx_switches(self):
        self.execute(self.proc.num_ctx_switches)

    @fewtimes_if_linux()
    @skip_on_access_denied(only_if=OPENBSD)
    def test_threads(self):
        self.execute(self.proc.threads)

    @fewtimes_if_linux()
    def test_cpu_times(self):
        self.execute(self.proc.cpu_times)

    @fewtimes_if_linux()
    @pytest.mark.skipif(not HAS_PROC_CPU_NUM, reason="not supported")
    def test_cpu_num(self):
        self.execute(self.proc.cpu_num)

    @fewtimes_if_linux()
    def test_memory_info(self):
        self.execute(self.proc.memory_info)

    @fewtimes_if_linux()
    def test_memory_full_info(self):
        self.execute(self.proc.memory_full_info)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @fewtimes_if_linux()
    def test_terminal(self):
        self.execute(self.proc.terminal)

    def test_resume(self):
        times = FEW_TIMES if POSIX else self.times
        self.execute(self.proc.resume, times=times)

    @fewtimes_if_linux()
    def test_cwd(self):
        self.execute(self.proc.cwd)

    @pytest.mark.skipif(not HAS_CPU_AFFINITY, reason="not supported")
    def test_cpu_affinity(self):
        self.execute(self.proc.cpu_affinity)

    @pytest.mark.skipif(not HAS_CPU_AFFINITY, reason="not supported")
    def test_cpu_affinity_set(self):
        affinity = thisproc.cpu_affinity()
        self.execute(lambda: self.proc.cpu_affinity(affinity))
        self.execute_w_exc(ValueError, lambda: self.proc.cpu_affinity([-1]))

    @fewtimes_if_linux()
    def test_open_files(self):
        with open(get_testfn(), 'w'):
            self.execute(self.proc.open_files)

    @pytest.mark.skipif(not HAS_MEMORY_MAPS, reason="not supported")
    @fewtimes_if_linux()
    def test_memory_maps(self):
        self.execute(self.proc.memory_maps)

    @pytest.mark.skipif(not LINUX, reason="LINUX only")
    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit(self):
        self.execute(lambda: self.proc.rlimit(psutil.RLIMIT_NOFILE))

    @pytest.mark.skipif(not LINUX, reason="LINUX only")
    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_set(self):
        limit = thisproc.rlimit(psutil.RLIMIT_NOFILE)
        self.execute(lambda: self.proc.rlimit(psutil.RLIMIT_NOFILE, limit))
        self.execute_w_exc((OSError, ValueError), lambda: self.proc.rlimit(-1))

    @fewtimes_if_linux()
    # Windows implementation is based on a single system-wide
    # function (tested later).
    @pytest.mark.skipif(WINDOWS, reason="worthless on WINDOWS")
    def test_net_connections(self):
        # TODO: UNIX sockets are temporarily implemented by parsing
        # 'pfiles' cmd  output; we don't want that part of the code to
        # be executed.
        with create_sockets():
            kind = 'inet' if SUNOS else 'all'
            self.execute(lambda: self.proc.net_connections(kind))

    @pytest.mark.skipif(not HAS_ENVIRON, reason="not supported")
    def test_environ(self):
        self.execute(self.proc.environ)

    @pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
    def test_proc_info(self):
        self.execute(lambda: cext.proc_info(os.getpid()))


class TestTerminatedProcessLeaks(TestProcessObjectLeaks):
    """Repeat the tests above looking for leaks occurring when dealing
    with terminated processes raising NoSuchProcess exception.
    The C functions are still invoked but will follow different code
    paths. We'll check those code paths.
    """

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.subp = spawn_testproc()
        cls.proc = psutil.Process(cls.subp.pid)
        cls.proc.kill()
        cls.proc.wait()

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        terminate(cls.subp)

    def call(self, fun):
        try:
            fun()
        except psutil.NoSuchProcess:
            pass

    if WINDOWS:

        def test_kill(self):
            self.execute(self.proc.kill)

        def test_terminate(self):
            self.execute(self.proc.terminate)

        def test_suspend(self):
            self.execute(self.proc.suspend)

        def test_resume(self):
            self.execute(self.proc.resume)

        def test_wait(self):
            self.execute(self.proc.wait)

        def test_proc_info(self):
            # test dual implementation
            def call():
                try:
                    return cext.proc_info(self.proc.pid)
                except ProcessLookupError:
                    pass

            self.execute(call)


@pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
class TestProcessDualImplementation(TestMemoryLeak):
    def test_cmdline_peb_true(self):
        self.execute(lambda: cext.proc_cmdline(os.getpid(), use_peb=True))

    def test_cmdline_peb_false(self):
        self.execute(lambda: cext.proc_cmdline(os.getpid(), use_peb=False))


# ===================================================================
# system APIs
# ===================================================================


class TestModuleFunctionsLeaks(TestMemoryLeak):
    """Test leaks of psutil module functions."""

    def test_coverage(self):
        ns = system_namespace()
        ns.test_class_coverage(self, ns.all)

    # --- cpu

    @fewtimes_if_linux()
    def test_cpu_count(self):  # logical
        self.execute(lambda: psutil.cpu_count(logical=True))

    @fewtimes_if_linux()
    def test_cpu_count_cores(self):
        self.execute(lambda: psutil.cpu_count(logical=False))

    @fewtimes_if_linux()
    def test_cpu_times(self):
        self.execute(psutil.cpu_times)

    @fewtimes_if_linux()
    def test_per_cpu_times(self):
        self.execute(lambda: psutil.cpu_times(percpu=True))

    @fewtimes_if_linux()
    def test_cpu_stats(self):
        self.execute(psutil.cpu_stats)

    @fewtimes_if_linux()
    # TODO: remove this once 1892 is fixed
    @pytest.mark.skipif(
        MACOS and platform.machine() == 'arm64', reason="skipped due to #1892"
    )
    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_cpu_freq(self):
        self.execute(psutil.cpu_freq)

    @pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
    def test_getloadavg(self):
        psutil.getloadavg()
        self.execute(psutil.getloadavg)

    # --- mem

    def test_virtual_memory(self):
        self.execute(psutil.virtual_memory)

    # TODO: remove this skip when this gets fixed
    @pytest.mark.skipif(SUNOS, reason="worthless on SUNOS (uses a subprocess)")
    def test_swap_memory(self):
        self.execute(psutil.swap_memory)

    def test_pid_exists(self):
        times = FEW_TIMES if POSIX else self.times
        self.execute(lambda: psutil.pid_exists(os.getpid()), times=times)

    # --- disk

    def test_disk_usage(self):
        times = FEW_TIMES if POSIX else self.times
        self.execute(lambda: psutil.disk_usage('.'), times=times)

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_disk_partitions(self):
        self.execute(psutil.disk_partitions)

    @pytest.mark.skipif(
        LINUX and not os.path.exists('/proc/diskstats'),
        reason="/proc/diskstats not available on this Linux version",
    )
    @fewtimes_if_linux()
    def test_disk_io_counters(self):
        self.execute(lambda: psutil.disk_io_counters(nowrap=False))

    # --- proc

    @fewtimes_if_linux()
    def test_pids(self):
        self.execute(psutil.pids)

    # --- net

    @fewtimes_if_linux()
    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_net_io_counters(self):
        self.execute(lambda: psutil.net_io_counters(nowrap=False))

    @fewtimes_if_linux()
    @pytest.mark.skipif(MACOS and os.getuid() != 0, reason="need root access")
    def test_net_connections(self):
        # always opens and handle on Windows() (once)
        psutil.net_connections(kind='all')
        with create_sockets():
            self.execute(lambda: psutil.net_connections(kind='all'))

    def test_net_if_addrs(self):
        # Note: verified that on Windows this was a false positive.
        tolerance = 80 * 1024 if WINDOWS else self.tolerance
        self.execute(psutil.net_if_addrs, tolerance=tolerance)

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_net_if_stats(self):
        self.execute(psutil.net_if_stats)

    # --- sensors

    @fewtimes_if_linux()
    @pytest.mark.skipif(not HAS_SENSORS_BATTERY, reason="not supported")
    def test_sensors_battery(self):
        self.execute(psutil.sensors_battery)

    @fewtimes_if_linux()
    @pytest.mark.skipif(not HAS_SENSORS_TEMPERATURES, reason="not supported")
    def test_sensors_temperatures(self):
        self.execute(psutil.sensors_temperatures)

    @fewtimes_if_linux()
    @pytest.mark.skipif(not HAS_SENSORS_FANS, reason="not supported")
    def test_sensors_fans(self):
        self.execute(psutil.sensors_fans)

    # --- others

    @fewtimes_if_linux()
    def test_boot_time(self):
        self.execute(psutil.boot_time)

    def test_users(self):
        self.execute(psutil.users)

    def test_set_debug(self):
        self.execute(lambda: psutil._set_debug(False))

    if WINDOWS:

        # --- win services

        def test_win_service_iter(self):
            self.execute(cext.winservice_enumerate)

        def test_win_service_get(self):
            pass

        def test_win_service_get_config(self):
            name = next(psutil.win_service_iter()).name()
            self.execute(lambda: cext.winservice_query_config(name))

        def test_win_service_get_status(self):
            name = next(psutil.win_service_iter()).name()
            self.execute(lambda: cext.winservice_query_status(name))

        def test_win_service_get_description(self):
            name = next(psutil.win_service_iter()).name()
            self.execute(lambda: cext.winservice_query_descr(name))
PKok\���H!1!1psutil/tests/test_contracts.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Contracts tests. These tests mainly check API sanity in terms of
returned types and APIs availability.
Some of these are duplicates of tests test_system.py and test_process.py.
"""

import platform
import signal

import psutil
from psutil import AIX
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import long
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import PYPY
from psutil.tests import QEMU_USER
from psutil.tests import SKIP_SYSCONS
from psutil.tests import PsutilTestCase
from psutil.tests import create_sockets
from psutil.tests import enum
from psutil.tests import is_namedtuple
from psutil.tests import kernel_version
from psutil.tests import pytest


# ===================================================================
# --- APIs availability
# ===================================================================

# Make sure code reflects what doc promises in terms of APIs
# availability.


class TestAvailConstantsAPIs(PsutilTestCase):
    def test_PROCFS_PATH(self):
        assert hasattr(psutil, "PROCFS_PATH") == (LINUX or SUNOS or AIX)

    def test_win_priority(self):
        ae = self.assertEqual
        ae(hasattr(psutil, "ABOVE_NORMAL_PRIORITY_CLASS"), WINDOWS)
        ae(hasattr(psutil, "BELOW_NORMAL_PRIORITY_CLASS"), WINDOWS)
        ae(hasattr(psutil, "HIGH_PRIORITY_CLASS"), WINDOWS)
        ae(hasattr(psutil, "IDLE_PRIORITY_CLASS"), WINDOWS)
        ae(hasattr(psutil, "NORMAL_PRIORITY_CLASS"), WINDOWS)
        ae(hasattr(psutil, "REALTIME_PRIORITY_CLASS"), WINDOWS)

    def test_linux_ioprio_linux(self):
        ae = self.assertEqual
        ae(hasattr(psutil, "IOPRIO_CLASS_NONE"), LINUX)
        ae(hasattr(psutil, "IOPRIO_CLASS_RT"), LINUX)
        ae(hasattr(psutil, "IOPRIO_CLASS_BE"), LINUX)
        ae(hasattr(psutil, "IOPRIO_CLASS_IDLE"), LINUX)

    def test_linux_ioprio_windows(self):
        ae = self.assertEqual
        ae(hasattr(psutil, "IOPRIO_HIGH"), WINDOWS)
        ae(hasattr(psutil, "IOPRIO_NORMAL"), WINDOWS)
        ae(hasattr(psutil, "IOPRIO_LOW"), WINDOWS)
        ae(hasattr(psutil, "IOPRIO_VERYLOW"), WINDOWS)

    @pytest.mark.skipif(
        GITHUB_ACTIONS and LINUX,
        reason="unsupported on GITHUB_ACTIONS + LINUX",
    )
    def test_rlimit(self):
        ae = self.assertEqual
        ae(hasattr(psutil, "RLIM_INFINITY"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_AS"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_CORE"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_CPU"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_DATA"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_FSIZE"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_MEMLOCK"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_NOFILE"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_NPROC"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_RSS"), LINUX or FREEBSD)
        ae(hasattr(psutil, "RLIMIT_STACK"), LINUX or FREEBSD)

        ae(hasattr(psutil, "RLIMIT_LOCKS"), LINUX)
        if POSIX:
            if kernel_version() >= (2, 6, 8):
                ae(hasattr(psutil, "RLIMIT_MSGQUEUE"), LINUX)
            if kernel_version() >= (2, 6, 12):
                ae(hasattr(psutil, "RLIMIT_NICE"), LINUX)
            if kernel_version() >= (2, 6, 12):
                ae(hasattr(psutil, "RLIMIT_RTPRIO"), LINUX)
            if kernel_version() >= (2, 6, 25):
                ae(hasattr(psutil, "RLIMIT_RTTIME"), LINUX)
            if kernel_version() >= (2, 6, 8):
                ae(hasattr(psutil, "RLIMIT_SIGPENDING"), LINUX)

        ae(hasattr(psutil, "RLIMIT_SWAP"), FREEBSD)
        ae(hasattr(psutil, "RLIMIT_SBSIZE"), FREEBSD)
        ae(hasattr(psutil, "RLIMIT_NPTS"), FREEBSD)


class TestAvailSystemAPIs(PsutilTestCase):
    def test_win_service_iter(self):
        assert hasattr(psutil, "win_service_iter") == WINDOWS

    def test_win_service_get(self):
        assert hasattr(psutil, "win_service_get") == WINDOWS

    def test_cpu_freq(self):
        assert hasattr(psutil, "cpu_freq") == (
            LINUX or MACOS or WINDOWS or FREEBSD or OPENBSD
        )

    def test_sensors_temperatures(self):
        assert hasattr(psutil, "sensors_temperatures") == (LINUX or FREEBSD)

    def test_sensors_fans(self):
        assert hasattr(psutil, "sensors_fans") == LINUX

    def test_battery(self):
        assert hasattr(psutil, "sensors_battery") == (
            LINUX or WINDOWS or FREEBSD or MACOS
        )


class TestAvailProcessAPIs(PsutilTestCase):
    def test_environ(self):
        assert hasattr(psutil.Process, "environ") == (
            LINUX
            or MACOS
            or WINDOWS
            or AIX
            or SUNOS
            or FREEBSD
            or OPENBSD
            or NETBSD
        )

    def test_uids(self):
        assert hasattr(psutil.Process, "uids") == POSIX

    def test_gids(self):
        assert hasattr(psutil.Process, "uids") == POSIX

    def test_terminal(self):
        assert hasattr(psutil.Process, "terminal") == POSIX

    def test_ionice(self):
        assert hasattr(psutil.Process, "ionice") == (LINUX or WINDOWS)

    @pytest.mark.skipif(
        GITHUB_ACTIONS and LINUX,
        reason="unsupported on GITHUB_ACTIONS + LINUX",
    )
    def test_rlimit(self):
        assert hasattr(psutil.Process, "rlimit") == (LINUX or FREEBSD)

    def test_io_counters(self):
        hasit = hasattr(psutil.Process, "io_counters")
        assert hasit == (not (MACOS or SUNOS))

    def test_num_fds(self):
        assert hasattr(psutil.Process, "num_fds") == POSIX

    def test_num_handles(self):
        assert hasattr(psutil.Process, "num_handles") == WINDOWS

    def test_cpu_affinity(self):
        assert hasattr(psutil.Process, "cpu_affinity") == (
            LINUX or WINDOWS or FREEBSD
        )

    def test_cpu_num(self):
        assert hasattr(psutil.Process, "cpu_num") == (
            LINUX or FREEBSD or SUNOS
        )

    def test_memory_maps(self):
        hasit = hasattr(psutil.Process, "memory_maps")
        assert hasit == (not (OPENBSD or NETBSD or AIX or MACOS))


# ===================================================================
# --- API types
# ===================================================================


class TestSystemAPITypes(PsutilTestCase):
    """Check the return types of system related APIs.
    Mainly we want to test we never return unicode on Python 2, see:
    https://github.com/giampaolo/psutil/issues/1039.
    """

    @classmethod
    def setUpClass(cls):
        cls.proc = psutil.Process()

    def assert_ntuple_of_nums(self, nt, type_=float, gezero=True):
        assert is_namedtuple(nt)
        for n in nt:
            assert isinstance(n, type_)
            if gezero:
                assert n >= 0

    def test_cpu_times(self):
        self.assert_ntuple_of_nums(psutil.cpu_times())
        for nt in psutil.cpu_times(percpu=True):
            self.assert_ntuple_of_nums(nt)

    def test_cpu_percent(self):
        assert isinstance(psutil.cpu_percent(interval=None), float)
        assert isinstance(psutil.cpu_percent(interval=0.00001), float)

    def test_cpu_times_percent(self):
        self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=None))
        self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=0.0001))

    def test_cpu_count(self):
        assert isinstance(psutil.cpu_count(), int)

    # TODO: remove this once 1892 is fixed
    @pytest.mark.skipif(
        MACOS and platform.machine() == 'arm64', reason="skipped due to #1892"
    )
    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_cpu_freq(self):
        if psutil.cpu_freq() is None:
            raise pytest.skip("cpu_freq() returns None")
        self.assert_ntuple_of_nums(psutil.cpu_freq(), type_=(float, int, long))

    def test_disk_io_counters(self):
        # Duplicate of test_system.py. Keep it anyway.
        for k, v in psutil.disk_io_counters(perdisk=True).items():
            assert isinstance(k, str)
            self.assert_ntuple_of_nums(v, type_=(int, long))

    def test_disk_partitions(self):
        # Duplicate of test_system.py. Keep it anyway.
        for disk in psutil.disk_partitions():
            assert isinstance(disk.device, str)
            assert isinstance(disk.mountpoint, str)
            assert isinstance(disk.fstype, str)
            assert isinstance(disk.opts, str)

    @pytest.mark.skipif(SKIP_SYSCONS, reason="requires root")
    def test_net_connections(self):
        with create_sockets():
            ret = psutil.net_connections('all')
            assert len(ret) == len(set(ret))
            for conn in ret:
                assert is_namedtuple(conn)

    def test_net_if_addrs(self):
        # Duplicate of test_system.py. Keep it anyway.
        for ifname, addrs in psutil.net_if_addrs().items():
            assert isinstance(ifname, str)
            for addr in addrs:
                if enum is not None and not PYPY:
                    assert isinstance(addr.family, enum.IntEnum)
                else:
                    assert isinstance(addr.family, int)
                assert isinstance(addr.address, str)
                assert isinstance(addr.netmask, (str, type(None)))
                assert isinstance(addr.broadcast, (str, type(None)))

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_net_if_stats(self):
        # Duplicate of test_system.py. Keep it anyway.
        for ifname, info in psutil.net_if_stats().items():
            assert isinstance(ifname, str)
            assert isinstance(info.isup, bool)
            if enum is not None:
                assert isinstance(info.duplex, enum.IntEnum)
            else:
                assert isinstance(info.duplex, int)
            assert isinstance(info.speed, int)
            assert isinstance(info.mtu, int)

    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_net_io_counters(self):
        # Duplicate of test_system.py. Keep it anyway.
        for ifname in psutil.net_io_counters(pernic=True):
            assert isinstance(ifname, str)

    @pytest.mark.skipif(not HAS_SENSORS_FANS, reason="not supported")
    def test_sensors_fans(self):
        # Duplicate of test_system.py. Keep it anyway.
        for name, units in psutil.sensors_fans().items():
            assert isinstance(name, str)
            for unit in units:
                assert isinstance(unit.label, str)
                assert isinstance(unit.current, (float, int, type(None)))

    @pytest.mark.skipif(not HAS_SENSORS_TEMPERATURES, reason="not supported")
    def test_sensors_temperatures(self):
        # Duplicate of test_system.py. Keep it anyway.
        for name, units in psutil.sensors_temperatures().items():
            assert isinstance(name, str)
            for unit in units:
                assert isinstance(unit.label, str)
                assert isinstance(unit.current, (float, int, type(None)))
                assert isinstance(unit.high, (float, int, type(None)))
                assert isinstance(unit.critical, (float, int, type(None)))

    def test_boot_time(self):
        # Duplicate of test_system.py. Keep it anyway.
        assert isinstance(psutil.boot_time(), float)

    def test_users(self):
        # Duplicate of test_system.py. Keep it anyway.
        for user in psutil.users():
            assert isinstance(user.name, str)
            assert isinstance(user.terminal, (str, type(None)))
            assert isinstance(user.host, (str, type(None)))
            assert isinstance(user.pid, (int, type(None)))


class TestProcessWaitType(PsutilTestCase):
    @pytest.mark.skipif(not POSIX, reason="not POSIX")
    def test_negative_signal(self):
        p = psutil.Process(self.spawn_testproc().pid)
        p.terminate()
        code = p.wait()
        assert code == -signal.SIGTERM
        if enum is not None:
            assert isinstance(code, enum.IntEnum)
        else:
            assert isinstance(code, int)
PKok\��c�H�H psutil/tests/test_process_all.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Iterate over all process PIDs and for each one of them invoke and
test all psutil.Process() methods.
"""

import enum
import errno
import multiprocessing
import os
import stat
import time
import traceback

import psutil
from psutil import AIX
from psutil import BSD
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import WINDOWS
from psutil._compat import PY3
from psutil._compat import FileNotFoundError
from psutil._compat import long
from psutil._compat import unicode
from psutil.tests import CI_TESTING
from psutil.tests import PYTEST_PARALLEL
from psutil.tests import QEMU_USER
from psutil.tests import VALID_PROC_STATUSES
from psutil.tests import PsutilTestCase
from psutil.tests import check_connection_ntuple
from psutil.tests import create_sockets
from psutil.tests import is_namedtuple
from psutil.tests import is_win_secure_system_proc
from psutil.tests import process_namespace
from psutil.tests import pytest


# Cuts the time in half, but (e.g.) on macOS the process pool stays
# alive after join() (multiprocessing bug?), messing up other tests.
USE_PROC_POOL = LINUX and not CI_TESTING and not PYTEST_PARALLEL


def proc_info(pid):
    tcase = PsutilTestCase()

    def check_exception(exc, proc, name, ppid):
        tcase.assertEqual(exc.pid, pid)
        if exc.name is not None:
            tcase.assertEqual(exc.name, name)
        if isinstance(exc, psutil.ZombieProcess):
            tcase.assertProcessZombie(proc)
            if exc.ppid is not None:
                tcase.assertGreaterEqual(exc.ppid, 0)
                tcase.assertEqual(exc.ppid, ppid)
        elif isinstance(exc, psutil.NoSuchProcess):
            tcase.assertProcessGone(proc)
        str(exc)
        repr(exc)

    def do_wait():
        if pid != 0:
            try:
                proc.wait(0)
            except psutil.Error as exc:
                check_exception(exc, proc, name, ppid)

    try:
        proc = psutil.Process(pid)
    except psutil.NoSuchProcess:
        tcase.assertPidGone(pid)
        return {}
    try:
        d = proc.as_dict(['ppid', 'name'])
    except psutil.NoSuchProcess:
        tcase.assertProcessGone(proc)
    else:
        name, ppid = d['name'], d['ppid']
        info = {'pid': proc.pid}
        ns = process_namespace(proc)
        # We don't use oneshot() because in order not to fool
        # check_exception() in case of NSP.
        for fun, fun_name in ns.iter(ns.getters, clear_cache=False):
            try:
                info[fun_name] = fun()
            except psutil.Error as exc:
                check_exception(exc, proc, name, ppid)
                continue
        do_wait()
        return info


class TestFetchAllProcesses(PsutilTestCase):
    """Test which iterates over all running processes and performs
    some sanity checks against Process API's returned values.
    Uses a process pool to get info about all processes.
    """

    def setUp(self):
        psutil._set_debug(False)
        # Using a pool in a CI env may result in deadlock, see:
        # https://github.com/giampaolo/psutil/issues/2104
        if USE_PROC_POOL:
            self.pool = multiprocessing.Pool()

    def tearDown(self):
        psutil._set_debug(True)
        if USE_PROC_POOL:
            self.pool.terminate()
            self.pool.join()

    def iter_proc_info(self):
        # Fixes "can't pickle <function proc_info>: it's not the
        # same object as test_process_all.proc_info".
        from psutil.tests.test_process_all import proc_info

        if USE_PROC_POOL:
            return self.pool.imap_unordered(proc_info, psutil.pids())
        else:
            ls = []
            for pid in psutil.pids():
                ls.append(proc_info(pid))
            return ls

    def test_all(self):
        failures = []
        for info in self.iter_proc_info():
            for name, value in info.items():
                meth = getattr(self, name)
                try:
                    meth(value, info)
                except Exception:  # noqa: BLE001
                    s = '\n' + '=' * 70 + '\n'
                    s += "FAIL: name=test_%s, pid=%s, ret=%s\ninfo=%s\n" % (
                        name,
                        info['pid'],
                        repr(value),
                        info,
                    )
                    s += '-' * 70
                    s += "\n%s" % traceback.format_exc()
                    s = "\n".join((" " * 4) + i for i in s.splitlines()) + "\n"
                    failures.append(s)
                else:
                    if value not in (0, 0.0, [], None, '', {}):
                        assert value, value
        if failures:
            raise self.fail(''.join(failures))

    def cmdline(self, ret, info):
        assert isinstance(ret, list)
        for part in ret:
            assert isinstance(part, str)

    def exe(self, ret, info):
        assert isinstance(ret, (str, unicode))
        assert ret.strip() == ret
        if ret:
            if WINDOWS and not ret.endswith('.exe'):
                return  # May be "Registry", "MemCompression", ...
            assert os.path.isabs(ret), ret
            # Note: os.stat() may return False even if the file is there
            # hence we skip the test, see:
            # http://stackoverflow.com/questions/3112546/os-path-exists-lies
            if POSIX and os.path.isfile(ret):
                if hasattr(os, 'access') and hasattr(os, "X_OK"):
                    # XXX: may fail on MACOS
                    try:
                        assert os.access(ret, os.X_OK)
                    except AssertionError:
                        if os.path.exists(ret) and not CI_TESTING:
                            raise

    def pid(self, ret, info):
        assert isinstance(ret, int)
        assert ret >= 0

    def ppid(self, ret, info):
        assert isinstance(ret, (int, long))
        assert ret >= 0
        proc_info(ret)

    def name(self, ret, info):
        assert isinstance(ret, (str, unicode))
        if WINDOWS and not ret and is_win_secure_system_proc(info['pid']):
            # https://github.com/giampaolo/psutil/issues/2338
            return
        # on AIX, "<exiting>" processes don't have names
        if not AIX:
            assert ret, repr(ret)

    def create_time(self, ret, info):
        assert isinstance(ret, float)
        try:
            assert ret >= 0
        except AssertionError:
            # XXX
            if OPENBSD and info['status'] == psutil.STATUS_ZOMBIE:
                pass
            else:
                raise
        # this can't be taken for granted on all platforms
        # self.assertGreaterEqual(ret, psutil.boot_time())
        # make sure returned value can be pretty printed
        # with strftime
        time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret))

    def uids(self, ret, info):
        assert is_namedtuple(ret)
        for uid in ret:
            assert isinstance(uid, int)
            assert uid >= 0

    def gids(self, ret, info):
        assert is_namedtuple(ret)
        # note: testing all gids as above seems not to be reliable for
        # gid == 30 (nodoby); not sure why.
        for gid in ret:
            assert isinstance(gid, int)
            if not MACOS and not NETBSD:
                assert gid >= 0

    def username(self, ret, info):
        assert isinstance(ret, str)
        assert ret.strip() == ret
        assert ret.strip()

    def status(self, ret, info):
        assert isinstance(ret, str)
        assert ret, ret
        if QEMU_USER:
            # status does not work under qemu user
            return
        assert ret != '?'  # XXX
        assert ret in VALID_PROC_STATUSES

    def io_counters(self, ret, info):
        assert is_namedtuple(ret)
        for field in ret:
            assert isinstance(field, (int, long))
            if field != -1:
                assert field >= 0

    def ionice(self, ret, info):
        if LINUX:
            assert isinstance(ret.ioclass, int)
            assert isinstance(ret.value, int)
            assert ret.ioclass >= 0
            assert ret.value >= 0
        else:  # Windows, Cygwin
            choices = [
                psutil.IOPRIO_VERYLOW,
                psutil.IOPRIO_LOW,
                psutil.IOPRIO_NORMAL,
                psutil.IOPRIO_HIGH,
            ]
            assert isinstance(ret, int)
            assert ret >= 0
            assert ret in choices

    def num_threads(self, ret, info):
        assert isinstance(ret, int)
        if WINDOWS and ret == 0 and is_win_secure_system_proc(info['pid']):
            # https://github.com/giampaolo/psutil/issues/2338
            return
        assert ret >= 1

    def threads(self, ret, info):
        assert isinstance(ret, list)
        for t in ret:
            assert is_namedtuple(t)
            assert t.id >= 0
            assert t.user_time >= 0
            assert t.system_time >= 0
            for field in t:
                assert isinstance(field, (int, float))

    def cpu_times(self, ret, info):
        assert is_namedtuple(ret)
        for n in ret:
            assert isinstance(n, float)
            assert n >= 0
        # TODO: check ntuple fields

    def cpu_percent(self, ret, info):
        assert isinstance(ret, float)
        assert 0.0 <= ret <= 100.0, ret

    def cpu_num(self, ret, info):
        assert isinstance(ret, int)
        if FREEBSD and ret == -1:
            return
        assert ret >= 0
        if psutil.cpu_count() == 1:
            assert ret == 0
        assert ret in list(range(psutil.cpu_count()))

    def memory_info(self, ret, info):
        assert is_namedtuple(ret)
        for value in ret:
            assert isinstance(value, (int, long))
            assert value >= 0
        if WINDOWS:
            assert ret.peak_wset >= ret.wset
            assert ret.peak_paged_pool >= ret.paged_pool
            assert ret.peak_nonpaged_pool >= ret.nonpaged_pool
            assert ret.peak_pagefile >= ret.pagefile

    def memory_full_info(self, ret, info):
        assert is_namedtuple(ret)
        total = psutil.virtual_memory().total
        for name in ret._fields:
            value = getattr(ret, name)
            assert isinstance(value, (int, long))
            assert value >= 0
            if LINUX or (OSX and name in ('vms', 'data')):
                # On Linux there are processes (e.g. 'goa-daemon') whose
                # VMS is incredibly high for some reason.
                continue
            assert value <= total, name

        if LINUX:
            assert ret.pss >= ret.uss

    def open_files(self, ret, info):
        assert isinstance(ret, list)
        for f in ret:
            assert isinstance(f.fd, int)
            assert isinstance(f.path, str)
            assert f.path.strip() == f.path
            if WINDOWS:
                assert f.fd == -1
            elif LINUX:
                assert isinstance(f.position, int)
                assert isinstance(f.mode, str)
                assert isinstance(f.flags, int)
                assert f.position >= 0
                assert f.mode in ('r', 'w', 'a', 'r+', 'a+')
                assert f.flags > 0
            elif BSD and not f.path:
                # XXX see: https://github.com/giampaolo/psutil/issues/595
                continue
            assert os.path.isabs(f.path), f
            try:
                st = os.stat(f.path)
            except FileNotFoundError:
                pass
            else:
                assert stat.S_ISREG(st.st_mode), f

    def num_fds(self, ret, info):
        assert isinstance(ret, int)
        assert ret >= 0

    def net_connections(self, ret, info):
        with create_sockets():
            assert len(ret) == len(set(ret))
            for conn in ret:
                assert is_namedtuple(conn)
                check_connection_ntuple(conn)

    def cwd(self, ret, info):
        assert isinstance(ret, (str, unicode))
        assert ret.strip() == ret
        if ret:
            assert os.path.isabs(ret), ret
            try:
                st = os.stat(ret)
            except OSError as err:
                if WINDOWS and psutil._psplatform.is_permission_err(err):
                    pass
                # directory has been removed in mean time
                elif err.errno != errno.ENOENT:
                    raise
            else:
                assert stat.S_ISDIR(st.st_mode)

    def memory_percent(self, ret, info):
        assert isinstance(ret, float)
        assert 0 <= ret <= 100, ret

    def is_running(self, ret, info):
        assert isinstance(ret, bool)

    def cpu_affinity(self, ret, info):
        assert isinstance(ret, list)
        assert ret != []
        cpus = list(range(psutil.cpu_count()))
        for n in ret:
            assert isinstance(n, int)
            assert n in cpus

    def terminal(self, ret, info):
        assert isinstance(ret, (str, type(None)))
        if ret is not None:
            assert os.path.isabs(ret), ret
            assert os.path.exists(ret), ret

    def memory_maps(self, ret, info):
        for nt in ret:
            assert isinstance(nt.addr, str)
            assert isinstance(nt.perms, str)
            assert isinstance(nt.path, str)
            for fname in nt._fields:
                value = getattr(nt, fname)
                if fname == 'path':
                    if not value.startswith(("[", "anon_inode:")):
                        assert os.path.isabs(nt.path), nt.path
                        # commented as on Linux we might get
                        # '/foo/bar (deleted)'
                        # assert os.path.exists(nt.path), nt.path
                elif fname == 'addr':
                    assert value, repr(value)
                elif fname == 'perms':
                    if not WINDOWS:
                        assert value, repr(value)
                else:
                    assert isinstance(value, (int, long))
                    assert value >= 0

    def num_handles(self, ret, info):
        assert isinstance(ret, int)
        assert ret >= 0

    def nice(self, ret, info):
        assert isinstance(ret, int)
        if POSIX:
            assert -20 <= ret <= 20, ret
        else:
            priorities = [
                getattr(psutil, x)
                for x in dir(psutil)
                if x.endswith('_PRIORITY_CLASS')
            ]
            assert ret in priorities
            if PY3:
                assert isinstance(ret, enum.IntEnum)
            else:
                assert isinstance(ret, int)

    def num_ctx_switches(self, ret, info):
        assert is_namedtuple(ret)
        for value in ret:
            assert isinstance(value, (int, long))
            assert value >= 0

    def rlimit(self, ret, info):
        assert isinstance(ret, tuple)
        assert len(ret) == 2
        assert ret[0] >= -1
        assert ret[1] >= -1

    def environ(self, ret, info):
        assert isinstance(ret, dict)
        for k, v in ret.items():
            assert isinstance(k, str)
            assert isinstance(v, str)


class TestPidsRange(PsutilTestCase):
    """Given pid_exists() return value for a range of PIDs which may or
    may not exist, make sure that psutil.Process() and psutil.pids()
    agree with pid_exists(). This guarantees that the 3 APIs are all
    consistent with each other. See:
    https://github.com/giampaolo/psutil/issues/2359

    XXX - Note about Windows: it turns out there are some "hidden" PIDs
    which are not returned by psutil.pids() and are also not revealed
    by taskmgr.exe and ProcessHacker, still they can be instantiated by
    psutil.Process() and queried. One of such PIDs is "conhost.exe".
    Running as_dict() for it reveals that some Process() APIs
    erroneously raise NoSuchProcess, so we know we have problem there.
    Let's ignore this for now, since it's quite a corner case (who even
    imagined hidden PIDs existed on Windows?).
    """

    def setUp(self):
        psutil._set_debug(False)

    def tearDown(self):
        psutil._set_debug(True)

    def test_it(self):
        def is_linux_tid(pid):
            try:
                f = open("/proc/%s/status" % pid, "rb")
            except FileNotFoundError:
                return False
            else:
                with f:
                    for line in f:
                        if line.startswith(b"Tgid:"):
                            tgid = int(line.split()[1])
                            # If tgid and pid are different then we're
                            # dealing with a process TID.
                            return tgid != pid
                    raise ValueError("'Tgid' line not found")

        def check(pid):
            # In case of failure retry up to 3 times in order to avoid
            # race conditions, especially when running in a CI
            # environment where PIDs may appear and disappear at any
            # time.
            x = 3
            while True:
                exists = psutil.pid_exists(pid)
                try:
                    if exists:
                        psutil.Process(pid)
                        if not WINDOWS:  # see docstring
                            assert pid in psutil.pids()
                    else:
                        # On OpenBSD thread IDs can be instantiated,
                        # and oneshot() succeeds, but other APIs fail
                        # with EINVAL.
                        if not OPENBSD:
                            with pytest.raises(psutil.NoSuchProcess):
                                psutil.Process(pid)
                        if not WINDOWS:  # see docstring
                            assert pid not in psutil.pids()
                except (psutil.Error, AssertionError):
                    x -= 1
                    if x == 0:
                        raise
                else:
                    return

        for pid in range(1, 3000):
            if LINUX and is_linux_tid(pid):
                # On Linux a TID (thread ID) can be passed to the
                # Process class and is querable like a PID (process
                # ID). Skip it.
                continue
            with self.subTest(pid=pid):
                check(pid)
PKok\Z����psutil/tests/__init__.pynu�[���# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Test utilities."""

from __future__ import print_function

import atexit
import contextlib
import ctypes
import errno
import functools
import gc
import os
import platform
import random
import re
import select
import shlex
import shutil
import signal
import socket
import stat
import subprocess
import sys
import tempfile
import textwrap
import threading
import time
import unittest
import warnings
from socket import AF_INET
from socket import AF_INET6
from socket import SOCK_STREAM


try:
    import pytest
except ImportError:
    pytest = None

import psutil
from psutil import AIX
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import bytes2human
from psutil._common import debug
from psutil._common import memoize
from psutil._common import print_color
from psutil._common import supports_ipv6
from psutil._compat import PY3
from psutil._compat import FileExistsError
from psutil._compat import FileNotFoundError
from psutil._compat import range
from psutil._compat import super
from psutil._compat import unicode
from psutil._compat import which


try:
    from unittest import mock  # py3
except ImportError:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        import mock  # NOQA - requires "pip install mock"

if PY3:
    import enum
else:
    import unittest2 as unittest

    enum = None

if POSIX:
    from psutil._psposix import wait_pid


# fmt: off
__all__ = [
    # constants
    'APPVEYOR', 'DEVNULL', 'GLOBAL_TIMEOUT', 'TOLERANCE_SYS_MEM', 'NO_RETRIES',
    'PYPY', 'PYTHON_EXE', 'PYTHON_EXE_ENV', 'ROOT_DIR', 'SCRIPTS_DIR',
    'TESTFN_PREFIX', 'UNICODE_SUFFIX', 'INVALID_UNICODE_SUFFIX',
    'CI_TESTING', 'VALID_PROC_STATUSES', 'TOLERANCE_DISK_USAGE', 'IS_64BIT',
    "HAS_CPU_AFFINITY", "HAS_CPU_FREQ", "HAS_ENVIRON", "HAS_PROC_IO_COUNTERS",
    "HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT",
    "HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS",
    "HAS_SENSORS_TEMPERATURES", "HAS_NET_CONNECTIONS_UNIX", "MACOS_11PLUS",
    "MACOS_12PLUS", "COVERAGE", 'AARCH64', "QEMU_USER", "PYTEST_PARALLEL",
    # subprocesses
    'pyrun', 'terminate', 'reap_children', 'spawn_testproc', 'spawn_zombie',
    'spawn_children_pair',
    # threads
    'ThreadTask',
    # test utils
    'unittest', 'skip_on_access_denied', 'skip_on_not_implemented',
    'retry_on_failure', 'TestMemoryLeak', 'PsutilTestCase',
    'process_namespace', 'system_namespace', 'print_sysinfo',
    'is_win_secure_system_proc', 'fake_pytest',
    # fs utils
    'chdir', 'safe_rmpath', 'create_py_exe', 'create_c_exe', 'get_testfn',
    # os
    'get_winver', 'kernel_version',
    # sync primitives
    'call_until', 'wait_for_pid', 'wait_for_file',
    # network
    'check_net_address', 'filter_proc_net_connections',
    'get_free_port', 'bind_socket', 'bind_unix_socket', 'tcp_socketpair',
    'unix_socketpair', 'create_sockets',
    # compat
    'reload_module', 'import_module_by_path',
    # others
    'warn', 'copyload_shared_lib', 'is_namedtuple',
]
# fmt: on


# ===================================================================
# --- constants
# ===================================================================

# --- platforms

PYPY = '__pypy__' in sys.builtin_module_names
# whether we're running this test suite on a Continuous Integration service
APPVEYOR = 'APPVEYOR' in os.environ
GITHUB_ACTIONS = 'GITHUB_ACTIONS' in os.environ or 'CIBUILDWHEEL' in os.environ
CI_TESTING = APPVEYOR or GITHUB_ACTIONS
COVERAGE = 'COVERAGE_RUN' in os.environ
PYTEST_PARALLEL = "PYTEST_XDIST_WORKER" in os.environ  # `make test-parallel`
if LINUX and GITHUB_ACTIONS:
    with open('/proc/1/cmdline') as f:
        QEMU_USER = "/bin/qemu-" in f.read()
else:
    QEMU_USER = False
# are we a 64 bit process?
IS_64BIT = sys.maxsize > 2**32
AARCH64 = platform.machine() == "aarch64"


@memoize
def macos_version():
    version_str = platform.mac_ver()[0]
    version = tuple(map(int, version_str.split(".")[:2]))
    if version == (10, 16):
        # When built against an older macOS SDK, Python will report
        # macOS 10.16 instead of the real version.
        version_str = subprocess.check_output(
            [
                sys.executable,
                "-sS",
                "-c",
                "import platform; print(platform.mac_ver()[0])",
            ],
            env={"SYSTEM_VERSION_COMPAT": "0"},
            universal_newlines=True,
        )
        version = tuple(map(int, version_str.split(".")[:2]))
    return version


if MACOS:
    MACOS_11PLUS = macos_version() > (10, 15)
    MACOS_12PLUS = macos_version() >= (12, 0)
else:
    MACOS_11PLUS = False
    MACOS_12PLUS = False


# --- configurable defaults

# how many times retry_on_failure() decorator will retry
NO_RETRIES = 10
# bytes tolerance for system-wide related tests
TOLERANCE_SYS_MEM = 5 * 1024 * 1024  # 5MB
TOLERANCE_DISK_USAGE = 10 * 1024 * 1024  # 10MB
# the timeout used in functions which have to wait
GLOBAL_TIMEOUT = 5
# be more tolerant if we're on CI in order to avoid false positives
if CI_TESTING:
    NO_RETRIES *= 3
    GLOBAL_TIMEOUT *= 3
    TOLERANCE_SYS_MEM *= 4
    TOLERANCE_DISK_USAGE *= 3

# --- file names

# Disambiguate TESTFN for parallel testing.
if os.name == 'java':
    # Jython disallows @ in module names
    TESTFN_PREFIX = '$psutil-%s-' % os.getpid()
else:
    TESTFN_PREFIX = '@psutil-%s-' % os.getpid()
UNICODE_SUFFIX = u"-ƒőő"
# An invalid unicode string.
if PY3:
    INVALID_UNICODE_SUFFIX = b"f\xc0\x80".decode('utf8', 'surrogateescape')
else:
    INVALID_UNICODE_SUFFIX = "f\xc0\x80"
ASCII_FS = sys.getfilesystemencoding().lower() in ('ascii', 'us-ascii')

# --- paths

ROOT_DIR = os.path.realpath(
    os.path.join(os.path.dirname(__file__), '..', '..')
)
SCRIPTS_DIR = os.environ.get(
    "PSUTIL_SCRIPTS_DIR", os.path.join(ROOT_DIR, 'scripts')
)
HERE = os.path.realpath(os.path.dirname(__file__))

# --- support

HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity")
HAS_CPU_FREQ = hasattr(psutil, "cpu_freq")
HAS_ENVIRON = hasattr(psutil.Process, "environ")
HAS_GETLOADAVG = hasattr(psutil, "getloadavg")
HAS_IONICE = hasattr(psutil.Process, "ionice")
HAS_MEMORY_MAPS = hasattr(psutil.Process, "memory_maps")
HAS_NET_CONNECTIONS_UNIX = POSIX and not SUNOS
HAS_NET_IO_COUNTERS = hasattr(psutil, "net_io_counters")
HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num")
HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters")
HAS_RLIMIT = hasattr(psutil.Process, "rlimit")
HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery")
try:
    HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery())
except Exception:  # noqa: BLE001
    HAS_BATTERY = False
HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans")
HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures")
HAS_THREADS = hasattr(psutil.Process, "threads")
SKIP_SYSCONS = (MACOS or AIX) and os.getuid() != 0

# --- misc


def _get_py_exe():
    def attempt(exe):
        try:
            subprocess.check_call(
                [exe, "-V"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
            )
        except subprocess.CalledProcessError:
            return None
        else:
            return exe

    env = os.environ.copy()

    # On Windows, starting with python 3.7, virtual environments use a
    # venv launcher startup process. This does not play well when
    # counting spawned processes, or when relying on the PID of the
    # spawned process to do some checks, e.g. connections check per PID.
    # Let's use the base python in this case.
    base = getattr(sys, "_base_executable", None)
    if WINDOWS and sys.version_info >= (3, 7) and base is not None:
        # We need to set __PYVENV_LAUNCHER__ to sys.executable for the
        # base python executable to know about the environment.
        env["__PYVENV_LAUNCHER__"] = sys.executable
        return base, env
    elif GITHUB_ACTIONS:
        return sys.executable, env
    elif MACOS:
        exe = (
            attempt(sys.executable)
            or attempt(os.path.realpath(sys.executable))
            or attempt(which("python%s.%s" % sys.version_info[:2]))
            or attempt(psutil.Process().exe())
        )
        if not exe:
            raise ValueError("can't find python exe real abspath")
        return exe, env
    else:
        exe = os.path.realpath(sys.executable)
        assert os.path.exists(exe), exe
        return exe, env


PYTHON_EXE, PYTHON_EXE_ENV = _get_py_exe()
DEVNULL = open(os.devnull, 'r+')
atexit.register(DEVNULL.close)

VALID_PROC_STATUSES = [
    getattr(psutil, x) for x in dir(psutil) if x.startswith('STATUS_')
]
AF_UNIX = getattr(socket, "AF_UNIX", object())

_subprocesses_started = set()
_pids_started = set()


# ===================================================================
# --- threads
# ===================================================================


class ThreadTask(threading.Thread):
    """A thread task which does nothing expect staying alive."""

    def __init__(self):
        super().__init__()
        self._running = False
        self._interval = 0.001
        self._flag = threading.Event()

    def __repr__(self):
        name = self.__class__.__name__
        return '<%s running=%s at %#x>' % (name, self._running, id(self))

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, *args, **kwargs):
        self.stop()

    def start(self):
        """Start thread and keep it running until an explicit
        stop() request. Polls for shutdown every 'timeout' seconds.
        """
        if self._running:
            raise ValueError("already started")
        threading.Thread.start(self)
        self._flag.wait()

    def run(self):
        self._running = True
        self._flag.set()
        while self._running:
            time.sleep(self._interval)

    def stop(self):
        """Stop thread execution and and waits until it is stopped."""
        if not self._running:
            raise ValueError("already stopped")
        self._running = False
        self.join()


# ===================================================================
# --- subprocesses
# ===================================================================


def _reap_children_on_err(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        try:
            return fun(*args, **kwargs)
        except Exception:
            reap_children()
            raise

    return wrapper


@_reap_children_on_err
def spawn_testproc(cmd=None, **kwds):
    """Create a python subprocess which does nothing for some secs and
    return it as a subprocess.Popen instance.
    If "cmd" is specified that is used instead of python.
    By default stdin and stdout are redirected to /dev/null.
    It also attempts to make sure the process is in a reasonably
    initialized state.
    The process is registered for cleanup on reap_children().
    """
    kwds.setdefault("stdin", DEVNULL)
    kwds.setdefault("stdout", DEVNULL)
    kwds.setdefault("cwd", os.getcwd())
    kwds.setdefault("env", PYTHON_EXE_ENV)
    if WINDOWS:
        # Prevents the subprocess to open error dialogs. This will also
        # cause stderr to be suppressed, which is suboptimal in order
        # to debug broken tests.
        CREATE_NO_WINDOW = 0x8000000
        kwds.setdefault("creationflags", CREATE_NO_WINDOW)
    if cmd is None:
        testfn = get_testfn(dir=os.getcwd())
        try:
            safe_rmpath(testfn)
            pyline = (
                "import time;"
                + "open(r'%s', 'w').close();" % testfn
                + "[time.sleep(0.1) for x in range(100)];"  # 10 secs
            )
            cmd = [PYTHON_EXE, "-c", pyline]
            sproc = subprocess.Popen(cmd, **kwds)
            _subprocesses_started.add(sproc)
            wait_for_file(testfn, delete=True, empty=True)
        finally:
            safe_rmpath(testfn)
    else:
        sproc = subprocess.Popen(cmd, **kwds)
        _subprocesses_started.add(sproc)
        wait_for_pid(sproc.pid)
    return sproc


@_reap_children_on_err
def spawn_children_pair():
    """Create a subprocess which creates another one as in:
    A (us) -> B (child) -> C (grandchild).
    Return a (child, grandchild) tuple.
    The 2 processes are fully initialized and will live for 60 secs
    and are registered for cleanup on reap_children().
    """
    tfile = None
    testfn = get_testfn(dir=os.getcwd())
    try:
        s = textwrap.dedent("""\
            import subprocess, os, sys, time
            s = "import os, time;"
            s += "f = open('%s', 'w');"
            s += "f.write(str(os.getpid()));"
            s += "f.close();"
            s += "[time.sleep(0.1) for x in range(100 * 6)];"
            p = subprocess.Popen([r'%s', '-c', s])
            p.wait()
            """ % (os.path.basename(testfn), PYTHON_EXE))
        # On Windows if we create a subprocess with CREATE_NO_WINDOW flag
        # set (which is the default) a "conhost.exe" extra process will be
        # spawned as a child. We don't want that.
        if WINDOWS:
            subp, tfile = pyrun(s, creationflags=0)
        else:
            subp, tfile = pyrun(s)
        child = psutil.Process(subp.pid)
        grandchild_pid = int(wait_for_file(testfn, delete=True, empty=False))
        _pids_started.add(grandchild_pid)
        grandchild = psutil.Process(grandchild_pid)
        return (child, grandchild)
    finally:
        safe_rmpath(testfn)
        if tfile is not None:
            safe_rmpath(tfile)


def spawn_zombie():
    """Create a zombie process and return a (parent, zombie) process tuple.
    In order to kill the zombie parent must be terminate()d first, then
    zombie must be wait()ed on.
    """
    assert psutil.POSIX
    unix_file = get_testfn()
    src = textwrap.dedent("""\
        import os, sys, time, socket, contextlib
        child_pid = os.fork()
        if child_pid > 0:
            time.sleep(3000)
        else:
            # this is the zombie process
            s = socket.socket(socket.AF_UNIX)
            with contextlib.closing(s):
                s.connect('%s')
                if sys.version_info < (3, ):
                    pid = str(os.getpid())
                else:
                    pid = bytes(str(os.getpid()), 'ascii')
                s.sendall(pid)
        """ % unix_file)
    tfile = None
    sock = bind_unix_socket(unix_file)
    try:
        sock.settimeout(GLOBAL_TIMEOUT)
        parent, tfile = pyrun(src)
        conn, _ = sock.accept()
        try:
            select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT)
            zpid = int(conn.recv(1024))
            _pids_started.add(zpid)
            zombie = psutil.Process(zpid)
            call_until(lambda: zombie.status() == psutil.STATUS_ZOMBIE)
            return (parent, zombie)
        finally:
            conn.close()
    finally:
        sock.close()
        safe_rmpath(unix_file)
        if tfile is not None:
            safe_rmpath(tfile)


@_reap_children_on_err
def pyrun(src, **kwds):
    """Run python 'src' code string in a separate interpreter.
    Returns a subprocess.Popen instance and the test file where the source
    code was written.
    """
    kwds.setdefault("stdout", None)
    kwds.setdefault("stderr", None)
    srcfile = get_testfn()
    try:
        with open(srcfile, "w") as f:
            f.write(src)
        subp = spawn_testproc([PYTHON_EXE, f.name], **kwds)
        wait_for_pid(subp.pid)
        return (subp, srcfile)
    except Exception:
        safe_rmpath(srcfile)
        raise


@_reap_children_on_err
def sh(cmd, **kwds):
    """Run cmd in a subprocess and return its output.
    raises RuntimeError on error.
    """
    # Prevents subprocess to open error dialogs in case of error.
    flags = 0x8000000 if WINDOWS else 0
    kwds.setdefault("stdout", subprocess.PIPE)
    kwds.setdefault("stderr", subprocess.PIPE)
    kwds.setdefault("universal_newlines", True)
    kwds.setdefault("creationflags", flags)
    if isinstance(cmd, str):
        cmd = shlex.split(cmd)
    p = subprocess.Popen(cmd, **kwds)
    _subprocesses_started.add(p)
    if PY3:
        stdout, stderr = p.communicate(timeout=GLOBAL_TIMEOUT)
    else:
        stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise RuntimeError(stdout + stderr)
    if stderr:
        warn(stderr)
    if stdout.endswith('\n'):
        stdout = stdout[:-1]
    return stdout


def terminate(proc_or_pid, sig=signal.SIGTERM, wait_timeout=GLOBAL_TIMEOUT):
    """Terminate a process and wait() for it.
    Process can be a PID or an instance of psutil.Process(),
    subprocess.Popen() or psutil.Popen().
    If it's a subprocess.Popen() or psutil.Popen() instance also closes
    its stdin / stdout / stderr fds.
    PID is wait()ed even if the process is already gone (kills zombies).
    Does nothing if the process does not exist.
    Return process exit status.
    """

    def wait(proc, timeout):
        if isinstance(proc, subprocess.Popen) and not PY3:
            proc.wait()
        else:
            proc.wait(timeout)
        if WINDOWS and isinstance(proc, subprocess.Popen):
            # Otherwise PID may still hang around.
            try:
                return psutil.Process(proc.pid).wait(timeout)
            except psutil.NoSuchProcess:
                pass

    def sendsig(proc, sig):
        # XXX: otherwise the build hangs for some reason.
        if MACOS and GITHUB_ACTIONS:
            sig = signal.SIGKILL
        # If the process received SIGSTOP, SIGCONT is necessary first,
        # otherwise SIGTERM won't work.
        if POSIX and sig != signal.SIGKILL:
            proc.send_signal(signal.SIGCONT)
        proc.send_signal(sig)

    def term_subprocess_proc(proc, timeout):
        try:
            sendsig(proc, sig)
        except OSError as err:
            if WINDOWS and err.winerror == 6:  # "invalid handle"
                pass
            elif err.errno != errno.ESRCH:
                raise
        return wait(proc, timeout)

    def term_psutil_proc(proc, timeout):
        try:
            sendsig(proc, sig)
        except psutil.NoSuchProcess:
            pass
        return wait(proc, timeout)

    def term_pid(pid, timeout):
        try:
            proc = psutil.Process(pid)
        except psutil.NoSuchProcess:
            # Needed to kill zombies.
            if POSIX:
                return wait_pid(pid, timeout)
        else:
            return term_psutil_proc(proc, timeout)

    def flush_popen(proc):
        if proc.stdout:
            proc.stdout.close()
        if proc.stderr:
            proc.stderr.close()
        # Flushing a BufferedWriter may raise an error.
        if proc.stdin:
            proc.stdin.close()

    p = proc_or_pid
    try:
        if isinstance(p, int):
            return term_pid(p, wait_timeout)
        elif isinstance(p, (psutil.Process, psutil.Popen)):
            return term_psutil_proc(p, wait_timeout)
        elif isinstance(p, subprocess.Popen):
            return term_subprocess_proc(p, wait_timeout)
        else:
            raise TypeError("wrong type %r" % p)
    finally:
        if isinstance(p, (subprocess.Popen, psutil.Popen)):
            flush_popen(p)
        pid = p if isinstance(p, int) else p.pid
        assert not psutil.pid_exists(pid), pid


def reap_children(recursive=False):
    """Terminate and wait() any subprocess started by this test suite
    and any children currently running, ensuring that no processes stick
    around to hog resources.
    If recursive is True it also tries to terminate and wait()
    all grandchildren started by this process.
    """
    # Get the children here before terminating them, as in case of
    # recursive=True we don't want to lose the intermediate reference
    # pointing to the grandchildren.
    children = psutil.Process().children(recursive=recursive)

    # Terminate subprocess.Popen.
    while _subprocesses_started:
        subp = _subprocesses_started.pop()
        terminate(subp)

    # Collect started pids.
    while _pids_started:
        pid = _pids_started.pop()
        terminate(pid)

    # Terminate children.
    if children:
        for p in children:
            terminate(p, wait_timeout=None)
        _, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT)
        for p in alive:
            warn("couldn't terminate process %r; attempting kill()" % p)
            terminate(p, sig=signal.SIGKILL)


# ===================================================================
# --- OS
# ===================================================================


def kernel_version():
    """Return a tuple such as (2, 6, 36)."""
    if not POSIX:
        raise NotImplementedError("not POSIX")
    s = ""
    uname = os.uname()[2]
    for c in uname:
        if c.isdigit() or c == '.':
            s += c
        else:
            break
    if not s:
        raise ValueError("can't parse %r" % uname)
    minor = 0
    micro = 0
    nums = s.split('.')
    major = int(nums[0])
    if len(nums) >= 2:
        minor = int(nums[1])
    if len(nums) >= 3:
        micro = int(nums[2])
    return (major, minor, micro)


def get_winver():
    if not WINDOWS:
        raise NotImplementedError("not WINDOWS")
    wv = sys.getwindowsversion()
    if hasattr(wv, 'service_pack_major'):  # python >= 2.7
        sp = wv.service_pack_major or 0
    else:
        r = re.search(r"\s\d$", wv[4])
        sp = int(r.group(0)) if r else 0
    return (wv[0], wv[1], sp)


# ===================================================================
# --- sync primitives
# ===================================================================


class retry:
    """A retry decorator."""

    def __init__(
        self,
        exception=Exception,
        timeout=None,
        retries=None,
        interval=0.001,
        logfun=None,
    ):
        if timeout and retries:
            raise ValueError("timeout and retries args are mutually exclusive")
        self.exception = exception
        self.timeout = timeout
        self.retries = retries
        self.interval = interval
        self.logfun = logfun

    def __iter__(self):
        if self.timeout:
            stop_at = time.time() + self.timeout
            while time.time() < stop_at:
                yield
        elif self.retries:
            for _ in range(self.retries):
                yield
        else:
            while True:
                yield

    def sleep(self):
        if self.interval is not None:
            time.sleep(self.interval)

    def __call__(self, fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            exc = None
            for _ in self:
                try:
                    return fun(*args, **kwargs)
                except self.exception as _:  # NOQA
                    exc = _
                    if self.logfun is not None:
                        self.logfun(exc)
                    self.sleep()
                    continue
            if PY3:
                raise exc  # noqa: PLE0704
            else:
                raise  # noqa: PLE0704

        # This way the user of the decorated function can change config
        # parameters.
        wrapper.decorator = self
        return wrapper


@retry(
    exception=psutil.NoSuchProcess,
    logfun=None,
    timeout=GLOBAL_TIMEOUT,
    interval=0.001,
)
def wait_for_pid(pid):
    """Wait for pid to show up in the process list then return.
    Used in the test suite to give time the sub process to initialize.
    """
    if pid not in psutil.pids():
        raise psutil.NoSuchProcess(pid)
    psutil.Process(pid)


@retry(
    exception=(FileNotFoundError, AssertionError),
    logfun=None,
    timeout=GLOBAL_TIMEOUT,
    interval=0.001,
)
def wait_for_file(fname, delete=True, empty=False):
    """Wait for a file to be written on disk with some content."""
    with open(fname, "rb") as f:
        data = f.read()
    if not empty:
        assert data
    if delete:
        safe_rmpath(fname)
    return data


@retry(
    exception=AssertionError,
    logfun=None,
    timeout=GLOBAL_TIMEOUT,
    interval=0.001,
)
def call_until(fun):
    """Keep calling function until it evaluates to True."""
    ret = fun()
    assert ret
    return ret


# ===================================================================
# --- fs
# ===================================================================


def safe_rmpath(path):
    """Convenience function for removing temporary test files or dirs."""

    def retry_fun(fun):
        # On Windows it could happen that the file or directory has
        # open handles or references preventing the delete operation
        # to succeed immediately, so we retry for a while. See:
        # https://bugs.python.org/issue33240
        stop_at = time.time() + GLOBAL_TIMEOUT
        while time.time() < stop_at:
            try:
                return fun()
            except FileNotFoundError:
                pass
            except WindowsError as _:
                err = _
                warn("ignoring %s" % (str(err)))
            time.sleep(0.01)
        raise err

    try:
        st = os.stat(path)
        if stat.S_ISDIR(st.st_mode):
            fun = functools.partial(shutil.rmtree, path)
        else:
            fun = functools.partial(os.remove, path)
        if POSIX:
            fun()
        else:
            retry_fun(fun)
    except FileNotFoundError:
        pass


def safe_mkdir(dir):
    """Convenience function for creating a directory."""
    try:
        os.mkdir(dir)
    except FileExistsError:
        pass


@contextlib.contextmanager
def chdir(dirname):
    """Context manager which temporarily changes the current directory."""
    curdir = os.getcwd()
    try:
        os.chdir(dirname)
        yield
    finally:
        os.chdir(curdir)


def create_py_exe(path):
    """Create a Python executable file in the given location."""
    assert not os.path.exists(path), path
    atexit.register(safe_rmpath, path)
    shutil.copyfile(PYTHON_EXE, path)
    if POSIX:
        st = os.stat(path)
        os.chmod(path, st.st_mode | stat.S_IEXEC)
    return path


def create_c_exe(path, c_code=None):
    """Create a compiled C executable in the given location."""
    assert not os.path.exists(path), path
    if not which("gcc"):
        raise pytest.skip("gcc is not installed")
    if c_code is None:
        c_code = textwrap.dedent("""
            #include <unistd.h>
            int main() {
                pause();
                return 1;
            }
            """)
    else:
        assert isinstance(c_code, str), c_code

    atexit.register(safe_rmpath, path)
    with open(get_testfn(suffix='.c'), "w") as f:
        f.write(c_code)
    try:
        subprocess.check_call(["gcc", f.name, "-o", path])
    finally:
        safe_rmpath(f.name)
    return path


def get_testfn(suffix="", dir=None):
    """Return an absolute pathname of a file or dir that did not
    exist at the time this call is made. Also schedule it for safe
    deletion at interpreter exit. It's technically racy but probably
    not really due to the time variant.
    """
    while True:
        name = tempfile.mktemp(prefix=TESTFN_PREFIX, suffix=suffix, dir=dir)
        if not os.path.exists(name):  # also include dirs
            path = os.path.realpath(name)  # needed for OSX
            atexit.register(safe_rmpath, path)
            return path


# ===================================================================
# --- testing
# ===================================================================


class fake_pytest:
    """A class that mimics some basic pytest APIs. This is meant for
    when unit tests are run in production, where pytest may not be
    installed. Still, the user can test psutil installation via:

        $ python3 -m psutil.tests
    """

    @staticmethod
    def main(*args, **kw):  # noqa ARG004
        """Mimics pytest.main(). It has the same effect as running
        `python3 -m unittest -v` from the project root directory.
        """
        suite = unittest.TestLoader().discover(HERE)
        unittest.TextTestRunner(verbosity=2).run(suite)
        warnings.warn(
            "Fake pytest module was used. Test results may be inaccurate.",
            UserWarning,
            stacklevel=1,
        )
        return suite

    @staticmethod
    def raises(exc, match=None):
        """Mimics `pytest.raises`."""

        class ExceptionInfo:
            _exc = None

            @property
            def value(self):
                return self._exc

        @contextlib.contextmanager
        def context(exc, match=None):
            einfo = ExceptionInfo()
            try:
                yield einfo
            except exc as err:
                if match and not re.search(match, str(err)):
                    msg = '"{}" does not match "{}"'.format(match, str(err))
                    raise AssertionError(msg)
                einfo._exc = err
            else:
                raise AssertionError("%r not raised" % exc)

        return context(exc, match=match)

    @staticmethod
    def warns(warning, match=None):
        """Mimics `pytest.warns`."""
        if match:
            return unittest.TestCase().assertWarnsRegex(warning, match)
        return unittest.TestCase().assertWarns(warning)

    @staticmethod
    def skip(reason=""):
        """Mimics `unittest.SkipTest`."""
        raise unittest.SkipTest(reason)

    class mark:

        @staticmethod
        def skipif(condition, reason=""):
            """Mimics `@pytest.mark.skipif` decorator."""
            return unittest.skipIf(condition, reason)

        class xdist_group:
            """Mimics `@pytest.mark.xdist_group` decorator (no-op)."""

            def __init__(self, name=None):
                pass

            def __call__(self, cls_or_meth):
                return cls_or_meth


if pytest is None:
    pytest = fake_pytest


class TestCase(unittest.TestCase):
    # ...otherwise multiprocessing.Pool complains
    if not PY3:

        def runTest(self):
            pass

        @contextlib.contextmanager
        def subTest(self, *args, **kw):
            # fake it for python 2.7
            yield


# monkey patch default unittest.TestCase
unittest.TestCase = TestCase


class PsutilTestCase(TestCase):
    """Test class providing auto-cleanup wrappers on top of process
    test utilities. All test classes should derive from this one, even
    if we use pytest.
    """

    def get_testfn(self, suffix="", dir=None):
        fname = get_testfn(suffix=suffix, dir=dir)
        self.addCleanup(safe_rmpath, fname)
        return fname

    def spawn_testproc(self, *args, **kwds):
        sproc = spawn_testproc(*args, **kwds)
        self.addCleanup(terminate, sproc)
        return sproc

    def spawn_children_pair(self):
        child1, child2 = spawn_children_pair()
        self.addCleanup(terminate, child2)
        self.addCleanup(terminate, child1)  # executed first
        return (child1, child2)

    def spawn_zombie(self):
        parent, zombie = spawn_zombie()
        self.addCleanup(terminate, zombie)
        self.addCleanup(terminate, parent)  # executed first
        return (parent, zombie)

    def pyrun(self, *args, **kwds):
        sproc, srcfile = pyrun(*args, **kwds)
        self.addCleanup(safe_rmpath, srcfile)
        self.addCleanup(terminate, sproc)  # executed first
        return sproc

    def _check_proc_exc(self, proc, exc):
        assert isinstance(exc, psutil.Error)
        assert exc.pid == proc.pid
        assert exc.name == proc._name
        if exc.name:
            assert exc.name
        if isinstance(exc, psutil.ZombieProcess):
            assert exc.ppid == proc._ppid
            if exc.ppid is not None:
                assert exc.ppid >= 0
        str(exc)
        repr(exc)

    def assertPidGone(self, pid):
        with pytest.raises(psutil.NoSuchProcess) as cm:
            try:
                psutil.Process(pid)
            except psutil.ZombieProcess:
                raise AssertionError("wasn't supposed to raise ZombieProcess")
        assert cm.value.pid == pid
        assert cm.value.name is None
        assert not psutil.pid_exists(pid), pid
        assert pid not in psutil.pids()
        assert pid not in [x.pid for x in psutil.process_iter()]

    def assertProcessGone(self, proc):
        self.assertPidGone(proc.pid)
        ns = process_namespace(proc)
        for fun, name in ns.iter(ns.all, clear_cache=True):
            with self.subTest(proc=proc, name=name):
                try:
                    ret = fun()
                except psutil.ZombieProcess:
                    raise
                except psutil.NoSuchProcess as exc:
                    self._check_proc_exc(proc, exc)
                else:
                    msg = "Process.%s() didn't raise NSP and returned %r" % (
                        name,
                        ret,
                    )
                    raise AssertionError(msg)
        proc.wait(timeout=0)  # assert not raise TimeoutExpired

    def assertProcessZombie(self, proc):
        # A zombie process should always be instantiable.
        clone = psutil.Process(proc.pid)
        # Cloned zombie on Open/NetBSD has null creation time, see:
        # https://github.com/giampaolo/psutil/issues/2287
        assert proc == clone
        if not (OPENBSD or NETBSD):
            assert hash(proc) == hash(clone)
        # Its status always be querable.
        assert proc.status() == psutil.STATUS_ZOMBIE
        # It should be considered 'running'.
        assert proc.is_running()
        assert psutil.pid_exists(proc.pid)
        # as_dict() shouldn't crash.
        proc.as_dict()
        # It should show up in pids() and process_iter().
        assert proc.pid in psutil.pids()
        assert proc.pid in [x.pid for x in psutil.process_iter()]
        psutil._pmap = {}
        assert proc.pid in [x.pid for x in psutil.process_iter()]
        # Call all methods.
        ns = process_namespace(proc)
        for fun, name in ns.iter(ns.all, clear_cache=True):
            with self.subTest(proc=proc, name=name):
                try:
                    fun()
                except (psutil.ZombieProcess, psutil.AccessDenied) as exc:
                    self._check_proc_exc(proc, exc)
        if LINUX:
            # https://github.com/giampaolo/psutil/pull/2288
            with pytest.raises(psutil.ZombieProcess) as cm:
                proc.cmdline()
            self._check_proc_exc(proc, cm.value)
            with pytest.raises(psutil.ZombieProcess) as cm:
                proc.exe()
            self._check_proc_exc(proc, cm.value)
            with pytest.raises(psutil.ZombieProcess) as cm:
                proc.memory_maps()
            self._check_proc_exc(proc, cm.value)
        # Zombie cannot be signaled or terminated.
        proc.suspend()
        proc.resume()
        proc.terminate()
        proc.kill()
        assert proc.is_running()
        assert psutil.pid_exists(proc.pid)
        assert proc.pid in psutil.pids()
        assert proc.pid in [x.pid for x in psutil.process_iter()]
        psutil._pmap = {}
        assert proc.pid in [x.pid for x in psutil.process_iter()]

        # Its parent should 'see' it (edit: not true on BSD and MACOS).
        # descendants = [x.pid for x in psutil.Process().children(
        #                recursive=True)]
        # self.assertIn(proc.pid, descendants)

        # __eq__ can't be relied upon because creation time may not be
        # querable.
        # self.assertEqual(proc, psutil.Process(proc.pid))

        # XXX should we also assume ppid() to be usable? Note: this
        # would be an important use case as the only way to get
        # rid of a zombie is to kill its parent.
        # self.assertEqual(proc.ppid(), os.getpid())


@pytest.mark.skipif(PYPY, reason="unreliable on PYPY")
class TestMemoryLeak(PsutilTestCase):
    """Test framework class for detecting function memory leaks,
    typically functions implemented in C which forgot to free() memory
    from the heap. It does so by checking whether the process memory
    usage increased before and after calling the function many times.

    Note that this is hard (probably impossible) to do reliably, due
    to how the OS handles memory, the GC and so on (memory can even
    decrease!). In order to avoid false positives, in case of failure
    (mem > 0) we retry the test for up to 5 times, increasing call
    repetitions each time. If the memory keeps increasing then it's a
    failure.

    If available (Linux, OSX, Windows), USS memory is used for comparison,
    since it's supposed to be more precise, see:
    https://gmpy.dev/blog/2016/real-process-memory-and-environ-in-python
    If not, RSS memory is used. mallinfo() on Linux and _heapwalk() on
    Windows may give even more precision, but at the moment are not
    implemented.

    PyPy appears to be completely unstable for this framework, probably
    because of its JIT, so tests on PYPY are skipped.

    Usage:

        class TestLeaks(psutil.tests.TestMemoryLeak):

            def test_fun(self):
                self.execute(some_function)
    """

    # Configurable class attrs.
    times = 200
    warmup_times = 10
    tolerance = 0  # memory
    retries = 10 if CI_TESTING else 5
    verbose = True
    _thisproc = psutil.Process()
    _psutil_debug_orig = bool(os.getenv('PSUTIL_DEBUG'))

    @classmethod
    def setUpClass(cls):
        psutil._set_debug(False)  # avoid spamming to stderr

    @classmethod
    def tearDownClass(cls):
        psutil._set_debug(cls._psutil_debug_orig)

    def _get_mem(self):
        # USS is the closest thing we have to "real" memory usage and it
        # should be less likely to produce false positives.
        mem = self._thisproc.memory_full_info()
        return getattr(mem, "uss", mem.rss)

    def _get_num_fds(self):
        if POSIX:
            return self._thisproc.num_fds()
        else:
            return self._thisproc.num_handles()

    def _log(self, msg):
        if self.verbose:
            print_color(msg, color="yellow", file=sys.stderr)

    def _check_fds(self, fun):
        """Makes sure num_fds() (POSIX) or num_handles() (Windows) does
        not increase after calling a function.  Used to discover forgotten
        close(2) and CloseHandle syscalls.
        """
        before = self._get_num_fds()
        self.call(fun)
        after = self._get_num_fds()
        diff = after - before
        if diff < 0:
            raise self.fail(
                "negative diff %r (gc probably collected a "
                "resource from a previous test)" % diff
            )
        if diff > 0:
            type_ = "fd" if POSIX else "handle"
            if diff > 1:
                type_ += "s"
            msg = "%s unclosed %s after calling %r" % (diff, type_, fun)
            raise self.fail(msg)

    def _call_ntimes(self, fun, times):
        """Get 2 distinct memory samples, before and after having
        called fun repeatedly, and return the memory difference.
        """
        gc.collect(generation=1)
        mem1 = self._get_mem()
        for x in range(times):
            ret = self.call(fun)
            del x, ret
        gc.collect(generation=1)
        mem2 = self._get_mem()
        assert gc.garbage == []
        diff = mem2 - mem1  # can also be negative
        return diff

    def _check_mem(self, fun, times, retries, tolerance):
        messages = []
        prev_mem = 0
        increase = times
        for idx in range(1, retries + 1):
            mem = self._call_ntimes(fun, times)
            msg = "Run #%s: extra-mem=%s, per-call=%s, calls=%s" % (
                idx,
                bytes2human(mem),
                bytes2human(mem / times),
                times,
            )
            messages.append(msg)
            success = mem <= tolerance or mem <= prev_mem
            if success:
                if idx > 1:
                    self._log(msg)
                return
            else:
                if idx == 1:
                    print()  # NOQA
                self._log(msg)
                times += increase
                prev_mem = mem
        raise self.fail(". ".join(messages))

    # ---

    def call(self, fun):
        return fun()

    def execute(
        self, fun, times=None, warmup_times=None, retries=None, tolerance=None
    ):
        """Test a callable."""
        times = times if times is not None else self.times
        warmup_times = (
            warmup_times if warmup_times is not None else self.warmup_times
        )
        retries = retries if retries is not None else self.retries
        tolerance = tolerance if tolerance is not None else self.tolerance
        try:
            assert times >= 1, "times must be >= 1"
            assert warmup_times >= 0, "warmup_times must be >= 0"
            assert retries >= 0, "retries must be >= 0"
            assert tolerance >= 0, "tolerance must be >= 0"
        except AssertionError as err:
            raise ValueError(str(err))

        self._call_ntimes(fun, warmup_times)  # warm up
        self._check_fds(fun)
        self._check_mem(fun, times=times, retries=retries, tolerance=tolerance)

    def execute_w_exc(self, exc, fun, **kwargs):
        """Convenience method to test a callable while making sure it
        raises an exception on every call.
        """

        def call():
            self.assertRaises(exc, fun)

        self.execute(call, **kwargs)


def print_sysinfo():
    import collections
    import datetime
    import getpass
    import locale
    import pprint

    try:
        import pip
    except ImportError:
        pip = None
    try:
        import wheel
    except ImportError:
        wheel = None

    info = collections.OrderedDict()

    # OS
    if psutil.LINUX and which('lsb_release'):
        info['OS'] = sh('lsb_release -d -s')
    elif psutil.OSX:
        info['OS'] = 'Darwin %s' % platform.mac_ver()[0]
    elif psutil.WINDOWS:
        info['OS'] = "Windows " + ' '.join(map(str, platform.win32_ver()))
        if hasattr(platform, 'win32_edition'):
            info['OS'] += ", " + platform.win32_edition()
    else:
        info['OS'] = "%s %s" % (platform.system(), platform.version())
    info['arch'] = ', '.join(
        list(platform.architecture()) + [platform.machine()]
    )
    if psutil.POSIX:
        info['kernel'] = platform.uname()[2]

    # python
    info['python'] = ', '.join([
        platform.python_implementation(),
        platform.python_version(),
        platform.python_compiler(),
    ])
    info['pip'] = getattr(pip, '__version__', 'not installed')
    if wheel is not None:
        info['pip'] += " (wheel=%s)" % wheel.__version__

    # UNIX
    if psutil.POSIX:
        if which('gcc'):
            out = sh(['gcc', '--version'])
            info['gcc'] = str(out).split('\n')[0]
        else:
            info['gcc'] = 'not installed'
        s = platform.libc_ver()[1]
        if s:
            info['glibc'] = s

    # system
    info['fs-encoding'] = sys.getfilesystemencoding()
    lang = locale.getlocale()
    info['lang'] = '%s, %s' % (lang[0], lang[1])
    info['boot-time'] = datetime.datetime.fromtimestamp(
        psutil.boot_time()
    ).strftime("%Y-%m-%d %H:%M:%S")
    info['time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    info['user'] = getpass.getuser()
    info['home'] = os.path.expanduser("~")
    info['cwd'] = os.getcwd()
    info['pyexe'] = PYTHON_EXE
    info['hostname'] = platform.node()
    info['PID'] = os.getpid()

    # metrics
    info['cpus'] = psutil.cpu_count()
    info['loadavg'] = "%.1f%%, %.1f%%, %.1f%%" % (
        tuple([x / psutil.cpu_count() * 100 for x in psutil.getloadavg()])
    )
    mem = psutil.virtual_memory()
    info['memory'] = "%s%%, used=%s, total=%s" % (
        int(mem.percent),
        bytes2human(mem.used),
        bytes2human(mem.total),
    )
    swap = psutil.swap_memory()
    info['swap'] = "%s%%, used=%s, total=%s" % (
        int(swap.percent),
        bytes2human(swap.used),
        bytes2human(swap.total),
    )
    info['pids'] = len(psutil.pids())
    pinfo = psutil.Process().as_dict()
    pinfo.pop('memory_maps', None)
    info['proc'] = pprint.pformat(pinfo)

    print("=" * 70, file=sys.stderr)  # NOQA
    for k, v in info.items():
        print("%-17s %s" % (k + ':', v), file=sys.stderr)  # NOQA
    print("=" * 70, file=sys.stderr)  # NOQA
    sys.stdout.flush()

    # if WINDOWS:
    #     os.system("tasklist")
    # elif which("ps"):
    #     os.system("ps aux")
    # print("=" * 70, file=sys.stderr)  # NOQA

    sys.stdout.flush()


def is_win_secure_system_proc(pid):
    # see: https://github.com/giampaolo/psutil/issues/2338
    @memoize
    def get_procs():
        ret = {}
        out = sh("tasklist.exe /NH /FO csv")
        for line in out.splitlines()[1:]:
            bits = [x.replace('"', "") for x in line.split(",")]
            name, pid = bits[0], int(bits[1])
            ret[pid] = name
        return ret

    try:
        return get_procs()[pid] == "Secure System"
    except KeyError:
        return False


def _get_eligible_cpu():
    p = psutil.Process()
    if hasattr(p, "cpu_num"):
        return p.cpu_num()
    elif hasattr(p, "cpu_affinity"):
        return random.choice(p.cpu_affinity())
    return 0


class process_namespace:
    """A container that lists all Process class method names + some
    reasonable parameters to be called with. Utility methods (parent(),
    children(), ...) are excluded.

    >>> ns = process_namespace(psutil.Process())
    >>> for fun, name in ns.iter(ns.getters):
    ...    fun()
    """

    utils = [('cpu_percent', (), {}), ('memory_percent', (), {})]

    ignored = [
        ('as_dict', (), {}),
        ('children', (), {'recursive': True}),
        ('connections', (), {}),  # deprecated
        ('is_running', (), {}),
        ('memory_info_ex', (), {}),  # deprecated
        ('oneshot', (), {}),
        ('parent', (), {}),
        ('parents', (), {}),
        ('pid', (), {}),
        ('wait', (0,), {}),
    ]

    getters = [
        ('cmdline', (), {}),
        ('cpu_times', (), {}),
        ('create_time', (), {}),
        ('cwd', (), {}),
        ('exe', (), {}),
        ('memory_full_info', (), {}),
        ('memory_info', (), {}),
        ('name', (), {}),
        ('net_connections', (), {'kind': 'all'}),
        ('nice', (), {}),
        ('num_ctx_switches', (), {}),
        ('num_threads', (), {}),
        ('open_files', (), {}),
        ('ppid', (), {}),
        ('status', (), {}),
        ('threads', (), {}),
        ('username', (), {}),
    ]
    if POSIX:
        getters += [('uids', (), {})]
        getters += [('gids', (), {})]
        getters += [('terminal', (), {})]
        getters += [('num_fds', (), {})]
    if HAS_PROC_IO_COUNTERS:
        getters += [('io_counters', (), {})]
    if HAS_IONICE:
        getters += [('ionice', (), {})]
    if HAS_RLIMIT:
        getters += [('rlimit', (psutil.RLIMIT_NOFILE,), {})]
    if HAS_CPU_AFFINITY:
        getters += [('cpu_affinity', (), {})]
    if HAS_PROC_CPU_NUM:
        getters += [('cpu_num', (), {})]
    if HAS_ENVIRON:
        getters += [('environ', (), {})]
    if WINDOWS:
        getters += [('num_handles', (), {})]
    if HAS_MEMORY_MAPS:
        getters += [('memory_maps', (), {'grouped': False})]

    setters = []
    if POSIX:
        setters += [('nice', (0,), {})]
    else:
        setters += [('nice', (psutil.NORMAL_PRIORITY_CLASS,), {})]
    if HAS_RLIMIT:
        setters += [('rlimit', (psutil.RLIMIT_NOFILE, (1024, 4096)), {})]
    if HAS_IONICE:
        if LINUX:
            setters += [('ionice', (psutil.IOPRIO_CLASS_NONE, 0), {})]
        else:
            setters += [('ionice', (psutil.IOPRIO_NORMAL,), {})]
    if HAS_CPU_AFFINITY:
        setters += [('cpu_affinity', ([_get_eligible_cpu()],), {})]

    killers = [
        ('send_signal', (signal.SIGTERM,), {}),
        ('suspend', (), {}),
        ('resume', (), {}),
        ('terminate', (), {}),
        ('kill', (), {}),
    ]
    if WINDOWS:
        killers += [('send_signal', (signal.CTRL_C_EVENT,), {})]
        killers += [('send_signal', (signal.CTRL_BREAK_EVENT,), {})]

    all = utils + getters + setters + killers

    def __init__(self, proc):
        self._proc = proc

    def iter(self, ls, clear_cache=True):
        """Given a list of tuples yields a set of (fun, fun_name) tuples
        in random order.
        """
        ls = list(ls)
        random.shuffle(ls)
        for fun_name, args, kwds in ls:
            if clear_cache:
                self.clear_cache()
            fun = getattr(self._proc, fun_name)
            fun = functools.partial(fun, *args, **kwds)
            yield (fun, fun_name)

    def clear_cache(self):
        """Clear the cache of a Process instance."""
        self._proc._init(self._proc.pid, _ignore_nsp=True)

    @classmethod
    def test_class_coverage(cls, test_class, ls):
        """Given a TestCase instance and a list of tuples checks that
        the class defines the required test method names.
        """
        for fun_name, _, _ in ls:
            meth_name = 'test_' + fun_name
            if not hasattr(test_class, meth_name):
                msg = "%r class should define a '%s' method" % (
                    test_class.__class__.__name__,
                    meth_name,
                )
                raise AttributeError(msg)

    @classmethod
    def test(cls):
        this = set([x[0] for x in cls.all])
        ignored = set([x[0] for x in cls.ignored])
        klass = set([x for x in dir(psutil.Process) if x[0] != '_'])
        leftout = (this | ignored) ^ klass
        if leftout:
            raise ValueError("uncovered Process class names: %r" % leftout)


class system_namespace:
    """A container that lists all the module-level, system-related APIs.
    Utilities such as cpu_percent() are excluded. Usage:

    >>> ns = system_namespace
    >>> for fun, name in ns.iter(ns.getters):
    ...    fun()
    """

    getters = [
        ('boot_time', (), {}),
        ('cpu_count', (), {'logical': False}),
        ('cpu_count', (), {'logical': True}),
        ('cpu_stats', (), {}),
        ('cpu_times', (), {'percpu': False}),
        ('cpu_times', (), {'percpu': True}),
        ('disk_io_counters', (), {'perdisk': True}),
        ('disk_partitions', (), {'all': True}),
        ('disk_usage', (os.getcwd(),), {}),
        ('net_connections', (), {'kind': 'all'}),
        ('net_if_addrs', (), {}),
        ('net_if_stats', (), {}),
        ('net_io_counters', (), {'pernic': True}),
        ('pid_exists', (os.getpid(),), {}),
        ('pids', (), {}),
        ('swap_memory', (), {}),
        ('users', (), {}),
        ('virtual_memory', (), {}),
    ]
    if HAS_CPU_FREQ:
        if MACOS and platform.machine() == 'arm64':  # skipped due to #1892
            pass
        else:
            getters += [('cpu_freq', (), {'percpu': True})]
    if HAS_GETLOADAVG:
        getters += [('getloadavg', (), {})]
    if HAS_SENSORS_TEMPERATURES:
        getters += [('sensors_temperatures', (), {})]
    if HAS_SENSORS_FANS:
        getters += [('sensors_fans', (), {})]
    if HAS_SENSORS_BATTERY:
        getters += [('sensors_battery', (), {})]
    if WINDOWS:
        getters += [('win_service_iter', (), {})]
        getters += [('win_service_get', ('alg',), {})]

    ignored = [
        ('process_iter', (), {}),
        ('wait_procs', ([psutil.Process()],), {}),
        ('cpu_percent', (), {}),
        ('cpu_times_percent', (), {}),
    ]

    all = getters

    @staticmethod
    def iter(ls):
        """Given a list of tuples yields a set of (fun, fun_name) tuples
        in random order.
        """
        ls = list(ls)
        random.shuffle(ls)
        for fun_name, args, kwds in ls:
            fun = getattr(psutil, fun_name)
            fun = functools.partial(fun, *args, **kwds)
            yield (fun, fun_name)

    test_class_coverage = process_namespace.test_class_coverage


def retry_on_failure(retries=NO_RETRIES):
    """Decorator which runs a test function and retries N times before
    actually failing.
    """

    def logfun(exc):
        print("%r, retrying" % exc, file=sys.stderr)  # NOQA

    return retry(
        exception=AssertionError, timeout=None, retries=retries, logfun=logfun
    )


def skip_on_access_denied(only_if=None):
    """Decorator to Ignore AccessDenied exceptions."""

    def decorator(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            try:
                return fun(*args, **kwargs)
            except psutil.AccessDenied:
                if only_if is not None:
                    if not only_if:
                        raise
                raise pytest.skip("raises AccessDenied")

        return wrapper

    return decorator


def skip_on_not_implemented(only_if=None):
    """Decorator to Ignore NotImplementedError exceptions."""

    def decorator(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            try:
                return fun(*args, **kwargs)
            except NotImplementedError:
                if only_if is not None:
                    if not only_if:
                        raise
                msg = (
                    "%r was skipped because it raised NotImplementedError"
                    % fun.__name__
                )
                raise pytest.skip(msg)

        return wrapper

    return decorator


# ===================================================================
# --- network
# ===================================================================


# XXX: no longer used
def get_free_port(host='127.0.0.1'):
    """Return an unused TCP port. Subject to race conditions."""
    with contextlib.closing(socket.socket()) as sock:
        sock.bind((host, 0))
        return sock.getsockname()[1]


def bind_socket(family=AF_INET, type=SOCK_STREAM, addr=None):
    """Binds a generic socket."""
    if addr is None and family in (AF_INET, AF_INET6):
        addr = ("", 0)
    sock = socket.socket(family, type)
    try:
        if os.name not in ('nt', 'cygwin'):
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind(addr)
        if type == socket.SOCK_STREAM:
            sock.listen(5)
        return sock
    except Exception:
        sock.close()
        raise


def bind_unix_socket(name, type=socket.SOCK_STREAM):
    """Bind a UNIX socket."""
    assert psutil.POSIX
    assert not os.path.exists(name), name
    sock = socket.socket(socket.AF_UNIX, type)
    try:
        sock.bind(name)
        if type == socket.SOCK_STREAM:
            sock.listen(5)
    except Exception:
        sock.close()
        raise
    return sock


def tcp_socketpair(family, addr=("", 0)):
    """Build a pair of TCP sockets connected to each other.
    Return a (server, client) tuple.
    """
    with contextlib.closing(socket.socket(family, SOCK_STREAM)) as ll:
        ll.bind(addr)
        ll.listen(5)
        addr = ll.getsockname()
        c = socket.socket(family, SOCK_STREAM)
        try:
            c.connect(addr)
            caddr = c.getsockname()
            while True:
                a, addr = ll.accept()
                # check that we've got the correct client
                if addr == caddr:
                    return (a, c)
                a.close()
        except OSError:
            c.close()
            raise


def unix_socketpair(name):
    """Build a pair of UNIX sockets connected to each other through
    the same UNIX file name.
    Return a (server, client) tuple.
    """
    assert psutil.POSIX
    server = client = None
    try:
        server = bind_unix_socket(name, type=socket.SOCK_STREAM)
        server.setblocking(0)
        client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        client.setblocking(0)
        client.connect(name)
        # new = server.accept()
    except Exception:
        if server is not None:
            server.close()
        if client is not None:
            client.close()
        raise
    return (server, client)


@contextlib.contextmanager
def create_sockets():
    """Open as many socket families / types as possible."""
    socks = []
    fname1 = fname2 = None
    try:
        socks.append(bind_socket(socket.AF_INET, socket.SOCK_STREAM))
        socks.append(bind_socket(socket.AF_INET, socket.SOCK_DGRAM))
        if supports_ipv6():
            socks.append(bind_socket(socket.AF_INET6, socket.SOCK_STREAM))
            socks.append(bind_socket(socket.AF_INET6, socket.SOCK_DGRAM))
        if POSIX and HAS_NET_CONNECTIONS_UNIX:
            fname1 = get_testfn()
            fname2 = get_testfn()
            s1, s2 = unix_socketpair(fname1)
            s3 = bind_unix_socket(fname2, type=socket.SOCK_DGRAM)
            for s in (s1, s2, s3):
                socks.append(s)
        yield socks
    finally:
        for s in socks:
            s.close()
        for fname in (fname1, fname2):
            if fname is not None:
                safe_rmpath(fname)


def check_net_address(addr, family):
    """Check a net address validity. Supported families are IPv4,
    IPv6 and MAC addresses.
    """
    import ipaddress  # python >= 3.3 / requires "pip install ipaddress"

    if enum and PY3 and not PYPY:
        assert isinstance(family, enum.IntEnum), family
    if family == socket.AF_INET:
        octs = [int(x) for x in addr.split('.')]
        assert len(octs) == 4, addr
        for num in octs:
            assert 0 <= num <= 255, addr
        if not PY3:
            addr = unicode(addr)
        ipaddress.IPv4Address(addr)
    elif family == socket.AF_INET6:
        assert isinstance(addr, str), addr
        if not PY3:
            addr = unicode(addr)
        ipaddress.IPv6Address(addr)
    elif family == psutil.AF_LINK:
        assert re.match(r'([a-fA-F0-9]{2}[:|\-]?){6}', addr) is not None, addr
    else:
        raise ValueError("unknown family %r" % family)


def check_connection_ntuple(conn):
    """Check validity of a connection namedtuple."""

    def check_ntuple(conn):
        has_pid = len(conn) == 7
        assert len(conn) in (6, 7), len(conn)
        assert conn[0] == conn.fd, conn.fd
        assert conn[1] == conn.family, conn.family
        assert conn[2] == conn.type, conn.type
        assert conn[3] == conn.laddr, conn.laddr
        assert conn[4] == conn.raddr, conn.raddr
        assert conn[5] == conn.status, conn.status
        if has_pid:
            assert conn[6] == conn.pid, conn.pid

    def check_family(conn):
        assert conn.family in (AF_INET, AF_INET6, AF_UNIX), conn.family
        if enum is not None:
            assert isinstance(conn.family, enum.IntEnum), conn
        else:
            assert isinstance(conn.family, int), conn
        if conn.family == AF_INET:
            # actually try to bind the local socket; ignore IPv6
            # sockets as their address might be represented as
            # an IPv4-mapped-address (e.g. "::127.0.0.1")
            # and that's rejected by bind()
            s = socket.socket(conn.family, conn.type)
            with contextlib.closing(s):
                try:
                    s.bind((conn.laddr[0], 0))
                except socket.error as err:
                    if err.errno != errno.EADDRNOTAVAIL:
                        raise
        elif conn.family == AF_UNIX:
            assert conn.status == psutil.CONN_NONE, conn.status

    def check_type(conn):
        # SOCK_SEQPACKET may happen in case of AF_UNIX socks
        SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object())
        assert conn.type in (
            socket.SOCK_STREAM,
            socket.SOCK_DGRAM,
            SOCK_SEQPACKET,
        ), conn.type
        if enum is not None:
            assert isinstance(conn.type, enum.IntEnum), conn
        else:
            assert isinstance(conn.type, int), conn
        if conn.type == socket.SOCK_DGRAM:
            assert conn.status == psutil.CONN_NONE, conn.status

    def check_addrs(conn):
        # check IP address and port sanity
        for addr in (conn.laddr, conn.raddr):
            if conn.family in (AF_INET, AF_INET6):
                assert isinstance(addr, tuple), type(addr)
                if not addr:
                    continue
                assert isinstance(addr.port, int), type(addr.port)
                assert 0 <= addr.port <= 65535, addr.port
                check_net_address(addr.ip, conn.family)
            elif conn.family == AF_UNIX:
                assert isinstance(addr, str), type(addr)

    def check_status(conn):
        assert isinstance(conn.status, str), conn.status
        valids = [
            getattr(psutil, x) for x in dir(psutil) if x.startswith('CONN_')
        ]
        assert conn.status in valids, conn.status
        if conn.family in (AF_INET, AF_INET6) and conn.type == SOCK_STREAM:
            assert conn.status != psutil.CONN_NONE, conn.status
        else:
            assert conn.status == psutil.CONN_NONE, conn.status

    check_ntuple(conn)
    check_family(conn)
    check_type(conn)
    check_addrs(conn)
    check_status(conn)


def filter_proc_net_connections(cons):
    """Our process may start with some open UNIX sockets which are not
    initialized by us, invalidating unit tests.
    """
    new = []
    for conn in cons:
        if POSIX and conn.family == socket.AF_UNIX:
            if MACOS and "/syslog" in conn.raddr:
                debug("skipping %s" % str(conn))
                continue
        new.append(conn)
    return new


# ===================================================================
# --- compatibility
# ===================================================================


def reload_module(module):
    """Backport of importlib.reload of Python 3.3+."""
    try:
        import importlib

        if not hasattr(importlib, 'reload'):  # python <=3.3
            raise ImportError
    except ImportError:
        import imp

        return imp.reload(module)
    else:
        return importlib.reload(module)


def import_module_by_path(path):
    name = os.path.splitext(os.path.basename(path))[0]
    if sys.version_info[0] < 3:
        import imp

        return imp.load_source(name, path)
    else:
        import importlib.util

        spec = importlib.util.spec_from_file_location(name, path)
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
        return mod


# ===================================================================
# --- others
# ===================================================================


def warn(msg):
    """Raise a warning msg."""
    warnings.warn(msg, UserWarning, stacklevel=2)


def is_namedtuple(x):
    """Check if object is an instance of namedtuple."""
    t = type(x)
    b = t.__bases__
    if len(b) != 1 or b[0] is not tuple:
        return False
    f = getattr(t, '_fields', None)
    if not isinstance(f, tuple):
        return False
    return all(isinstance(n, str) for n in f)


if POSIX:

    @contextlib.contextmanager
    def copyload_shared_lib(suffix=""):
        """Ctx manager which picks up a random shared CO lib used
        by this process, copies it in another location and loads it
        in memory via ctypes. Return the new absolutized path.
        """
        exe = 'pypy' if PYPY else 'python'
        ext = ".so"
        dst = get_testfn(suffix=suffix + ext)
        libs = [
            x.path
            for x in psutil.Process().memory_maps()
            if os.path.splitext(x.path)[1] == ext and exe in x.path.lower()
        ]
        src = random.choice(libs)
        shutil.copyfile(src, dst)
        try:
            ctypes.CDLL(dst)
            yield dst
        finally:
            safe_rmpath(dst)

else:

    @contextlib.contextmanager
    def copyload_shared_lib(suffix=""):
        """Ctx manager which picks up a random shared DLL lib used
        by this process, copies it in another location and loads it
        in memory via ctypes.
        Return the new absolutized, normcased path.
        """
        from ctypes import WinError
        from ctypes import wintypes

        ext = ".dll"
        dst = get_testfn(suffix=suffix + ext)
        libs = [
            x.path
            for x in psutil.Process().memory_maps()
            if x.path.lower().endswith(ext)
            and 'python' in os.path.basename(x.path).lower()
            and 'wow64' not in x.path.lower()
        ]
        if PYPY and not libs:
            libs = [
                x.path
                for x in psutil.Process().memory_maps()
                if 'pypy' in os.path.basename(x.path).lower()
            ]
        src = random.choice(libs)
        shutil.copyfile(src, dst)
        cfile = None
        try:
            cfile = ctypes.WinDLL(dst)
            yield dst
        finally:
            # Work around OverflowError:
            # - https://ci.appveyor.com/project/giampaolo/psutil/build/1207/
            #       job/o53330pbnri9bcw7
            # - http://bugs.python.org/issue30286
            # - http://stackoverflow.com/questions/23522055
            if cfile is not None:
                FreeLibrary = ctypes.windll.kernel32.FreeLibrary
                FreeLibrary.argtypes = [wintypes.HMODULE]
                ret = FreeLibrary(cfile._handle)
                if ret == 0:
                    WinError()
            safe_rmpath(dst)


# ===================================================================
# --- Exit funs (first is executed last)
# ===================================================================


# this is executed first
@atexit.register
def cleanup_test_procs():
    reap_children(recursive=True)


# atexit module does not execute exit functions in case of SIGTERM, which
# gets sent to test subprocesses, which is a problem if they import this
# module. With this it will. See:
# https://gmpy.dev/blog/2016/how-to-always-execute-exit-functions-in-python
if POSIX:
    signal.signal(signal.SIGTERM, lambda sig, _: sys.exit(sig))
PKok\V�a�SS psutil/tests/test_connections.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for psutil.net_connections() and Process.net_connections() APIs."""

import os
import socket
import textwrap
from contextlib import closing
from socket import AF_INET
from socket import AF_INET6
from socket import SOCK_DGRAM
from socket import SOCK_STREAM

import psutil
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import supports_ipv6
from psutil._compat import PY3
from psutil.tests import AF_UNIX
from psutil.tests import HAS_NET_CONNECTIONS_UNIX
from psutil.tests import SKIP_SYSCONS
from psutil.tests import PsutilTestCase
from psutil.tests import bind_socket
from psutil.tests import bind_unix_socket
from psutil.tests import check_connection_ntuple
from psutil.tests import create_sockets
from psutil.tests import filter_proc_net_connections
from psutil.tests import pytest
from psutil.tests import reap_children
from psutil.tests import retry_on_failure
from psutil.tests import skip_on_access_denied
from psutil.tests import tcp_socketpair
from psutil.tests import unix_socketpair
from psutil.tests import wait_for_file


SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object())


def this_proc_net_connections(kind):
    cons = psutil.Process().net_connections(kind=kind)
    if kind in ("all", "unix"):
        return filter_proc_net_connections(cons)
    return cons


@pytest.mark.xdist_group(name="serial")
class ConnectionTestCase(PsutilTestCase):
    def setUp(self):
        assert this_proc_net_connections(kind='all') == []

    def tearDown(self):
        # Make sure we closed all resources.
        assert this_proc_net_connections(kind='all') == []

    def compare_procsys_connections(self, pid, proc_cons, kind='all'):
        """Given a process PID and its list of connections compare
        those against system-wide connections retrieved via
        psutil.net_connections.
        """
        try:
            sys_cons = psutil.net_connections(kind=kind)
        except psutil.AccessDenied:
            # On MACOS, system-wide connections are retrieved by iterating
            # over all processes
            if MACOS:
                return
            else:
                raise
        # Filter for this proc PID and exlucde PIDs from the tuple.
        sys_cons = [c[:-1] for c in sys_cons if c.pid == pid]
        sys_cons.sort()
        proc_cons.sort()
        assert proc_cons == sys_cons


class TestBasicOperations(ConnectionTestCase):
    @pytest.mark.skipif(SKIP_SYSCONS, reason="requires root")
    def test_system(self):
        with create_sockets():
            for conn in psutil.net_connections(kind='all'):
                check_connection_ntuple(conn)

    def test_process(self):
        with create_sockets():
            for conn in this_proc_net_connections(kind='all'):
                check_connection_ntuple(conn)

    def test_invalid_kind(self):
        with pytest.raises(ValueError):
            this_proc_net_connections(kind='???')
        with pytest.raises(ValueError):
            psutil.net_connections(kind='???')


@pytest.mark.xdist_group(name="serial")
class TestUnconnectedSockets(ConnectionTestCase):
    """Tests sockets which are open but not connected to anything."""

    def get_conn_from_sock(self, sock):
        cons = this_proc_net_connections(kind='all')
        smap = dict([(c.fd, c) for c in cons])
        if NETBSD or FREEBSD:
            # NetBSD opens a UNIX socket to /var/log/run
            # so there may be more connections.
            return smap[sock.fileno()]
        else:
            assert len(cons) == 1
            if cons[0].fd != -1:
                assert smap[sock.fileno()].fd == sock.fileno()
            return cons[0]

    def check_socket(self, sock):
        """Given a socket, makes sure it matches the one obtained
        via psutil. It assumes this process created one connection
        only (the one supposed to be checked).
        """
        conn = self.get_conn_from_sock(sock)
        check_connection_ntuple(conn)

        # fd, family, type
        if conn.fd != -1:
            assert conn.fd == sock.fileno()
        assert conn.family == sock.family
        # see: http://bugs.python.org/issue30204
        assert conn.type == sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)

        # local address
        laddr = sock.getsockname()
        if not laddr and PY3 and isinstance(laddr, bytes):
            # See: http://bugs.python.org/issue30205
            laddr = laddr.decode()
        if sock.family == AF_INET6:
            laddr = laddr[:2]
        assert conn.laddr == laddr

        # XXX Solaris can't retrieve system-wide UNIX sockets
        if sock.family == AF_UNIX and HAS_NET_CONNECTIONS_UNIX:
            cons = this_proc_net_connections(kind='all')
            self.compare_procsys_connections(os.getpid(), cons, kind='all')
        return conn

    def test_tcp_v4(self):
        addr = ("127.0.0.1", 0)
        with closing(bind_socket(AF_INET, SOCK_STREAM, addr=addr)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ()
            assert conn.status == psutil.CONN_LISTEN

    @pytest.mark.skipif(not supports_ipv6(), reason="IPv6 not supported")
    def test_tcp_v6(self):
        addr = ("::1", 0)
        with closing(bind_socket(AF_INET6, SOCK_STREAM, addr=addr)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ()
            assert conn.status == psutil.CONN_LISTEN

    def test_udp_v4(self):
        addr = ("127.0.0.1", 0)
        with closing(bind_socket(AF_INET, SOCK_DGRAM, addr=addr)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ()
            assert conn.status == psutil.CONN_NONE

    @pytest.mark.skipif(not supports_ipv6(), reason="IPv6 not supported")
    def test_udp_v6(self):
        addr = ("::1", 0)
        with closing(bind_socket(AF_INET6, SOCK_DGRAM, addr=addr)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ()
            assert conn.status == psutil.CONN_NONE

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_unix_tcp(self):
        testfn = self.get_testfn()
        with closing(bind_unix_socket(testfn, type=SOCK_STREAM)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ""  # noqa
            assert conn.status == psutil.CONN_NONE

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_unix_udp(self):
        testfn = self.get_testfn()
        with closing(bind_unix_socket(testfn, type=SOCK_STREAM)) as sock:
            conn = self.check_socket(sock)
            assert conn.raddr == ""  # noqa
            assert conn.status == psutil.CONN_NONE


@pytest.mark.xdist_group(name="serial")
class TestConnectedSocket(ConnectionTestCase):
    """Test socket pairs which are actually connected to
    each other.
    """

    # On SunOS, even after we close() it, the server socket stays around
    # in TIME_WAIT state.
    @pytest.mark.skipif(SUNOS, reason="unreliable on SUONS")
    def test_tcp(self):
        addr = ("127.0.0.1", 0)
        assert this_proc_net_connections(kind='tcp4') == []
        server, client = tcp_socketpair(AF_INET, addr=addr)
        try:
            cons = this_proc_net_connections(kind='tcp4')
            assert len(cons) == 2
            assert cons[0].status == psutil.CONN_ESTABLISHED
            assert cons[1].status == psutil.CONN_ESTABLISHED
            # May not be fast enough to change state so it stays
            # commenteed.
            # client.close()
            # cons = this_proc_net_connections(kind='all')
            # self.assertEqual(len(cons), 1)
            # self.assertEqual(cons[0].status, psutil.CONN_CLOSE_WAIT)
        finally:
            server.close()
            client.close()

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_unix(self):
        testfn = self.get_testfn()
        server, client = unix_socketpair(testfn)
        try:
            cons = this_proc_net_connections(kind='unix')
            assert not (cons[0].laddr and cons[0].raddr), cons
            assert not (cons[1].laddr and cons[1].raddr), cons
            if NETBSD or FREEBSD:
                # On NetBSD creating a UNIX socket will cause
                # a UNIX connection to  /var/run/log.
                cons = [c for c in cons if c.raddr != '/var/run/log']
            assert len(cons) == 2
            if LINUX or FREEBSD or SUNOS or OPENBSD:
                # remote path is never set
                assert cons[0].raddr == ""  # noqa
                assert cons[1].raddr == ""  # noqa
                # one local address should though
                assert testfn == (cons[0].laddr or cons[1].laddr)
            else:
                # On other systems either the laddr or raddr
                # of both peers are set.
                assert (cons[0].laddr or cons[1].laddr) == testfn
        finally:
            server.close()
            client.close()


class TestFilters(ConnectionTestCase):
    def test_filters(self):
        def check(kind, families, types):
            for conn in this_proc_net_connections(kind=kind):
                assert conn.family in families
                assert conn.type in types
            if not SKIP_SYSCONS:
                for conn in psutil.net_connections(kind=kind):
                    assert conn.family in families
                    assert conn.type in types

        with create_sockets():
            check(
                'all',
                [AF_INET, AF_INET6, AF_UNIX],
                [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET],
            )
            check('inet', [AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM])
            check('inet4', [AF_INET], [SOCK_STREAM, SOCK_DGRAM])
            check('tcp', [AF_INET, AF_INET6], [SOCK_STREAM])
            check('tcp4', [AF_INET], [SOCK_STREAM])
            check('tcp6', [AF_INET6], [SOCK_STREAM])
            check('udp', [AF_INET, AF_INET6], [SOCK_DGRAM])
            check('udp4', [AF_INET], [SOCK_DGRAM])
            check('udp6', [AF_INET6], [SOCK_DGRAM])
            if HAS_NET_CONNECTIONS_UNIX:
                check(
                    'unix',
                    [AF_UNIX],
                    [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET],
                )

    @skip_on_access_denied(only_if=MACOS)
    def test_combos(self):
        reap_children()

        def check_conn(proc, conn, family, type, laddr, raddr, status, kinds):
            all_kinds = (
                "all",
                "inet",
                "inet4",
                "inet6",
                "tcp",
                "tcp4",
                "tcp6",
                "udp",
                "udp4",
                "udp6",
            )
            check_connection_ntuple(conn)
            assert conn.family == family
            assert conn.type == type
            assert conn.laddr == laddr
            assert conn.raddr == raddr
            assert conn.status == status
            for kind in all_kinds:
                cons = proc.net_connections(kind=kind)
                if kind in kinds:
                    assert cons != []
                else:
                    assert cons == []
            # compare against system-wide connections
            # XXX Solaris can't retrieve system-wide UNIX
            # sockets.
            if HAS_NET_CONNECTIONS_UNIX:
                self.compare_procsys_connections(proc.pid, [conn])

        tcp_template = textwrap.dedent("""
            import socket, time
            s = socket.socket({family}, socket.SOCK_STREAM)
            s.bind(('{addr}', 0))
            s.listen(5)
            with open('{testfn}', 'w') as f:
                f.write(str(s.getsockname()[:2]))
            [time.sleep(0.1) for x in range(100)]
            """)

        udp_template = textwrap.dedent("""
            import socket, time
            s = socket.socket({family}, socket.SOCK_DGRAM)
            s.bind(('{addr}', 0))
            with open('{testfn}', 'w') as f:
                f.write(str(s.getsockname()[:2]))
            [time.sleep(0.1) for x in range(100)]
            """)

        # must be relative on Windows
        testfile = os.path.basename(self.get_testfn(dir=os.getcwd()))
        tcp4_template = tcp_template.format(
            family=int(AF_INET), addr="127.0.0.1", testfn=testfile
        )
        udp4_template = udp_template.format(
            family=int(AF_INET), addr="127.0.0.1", testfn=testfile
        )
        tcp6_template = tcp_template.format(
            family=int(AF_INET6), addr="::1", testfn=testfile
        )
        udp6_template = udp_template.format(
            family=int(AF_INET6), addr="::1", testfn=testfile
        )

        # launch various subprocess instantiating a socket of various
        # families and types to enrich psutil results
        tcp4_proc = self.pyrun(tcp4_template)
        tcp4_addr = eval(wait_for_file(testfile, delete=True))  # noqa
        udp4_proc = self.pyrun(udp4_template)
        udp4_addr = eval(wait_for_file(testfile, delete=True))  # noqa
        if supports_ipv6():
            tcp6_proc = self.pyrun(tcp6_template)
            tcp6_addr = eval(wait_for_file(testfile, delete=True))  # noqa
            udp6_proc = self.pyrun(udp6_template)
            udp6_addr = eval(wait_for_file(testfile, delete=True))  # noqa
        else:
            tcp6_proc = None
            udp6_proc = None
            tcp6_addr = None
            udp6_addr = None

        for p in psutil.Process().children():
            cons = p.net_connections()
            assert len(cons) == 1
            for conn in cons:
                # TCP v4
                if p.pid == tcp4_proc.pid:
                    check_conn(
                        p,
                        conn,
                        AF_INET,
                        SOCK_STREAM,
                        tcp4_addr,
                        (),
                        psutil.CONN_LISTEN,
                        ("all", "inet", "inet4", "tcp", "tcp4"),
                    )
                # UDP v4
                elif p.pid == udp4_proc.pid:
                    check_conn(
                        p,
                        conn,
                        AF_INET,
                        SOCK_DGRAM,
                        udp4_addr,
                        (),
                        psutil.CONN_NONE,
                        ("all", "inet", "inet4", "udp", "udp4"),
                    )
                # TCP v6
                elif p.pid == getattr(tcp6_proc, "pid", None):
                    check_conn(
                        p,
                        conn,
                        AF_INET6,
                        SOCK_STREAM,
                        tcp6_addr,
                        (),
                        psutil.CONN_LISTEN,
                        ("all", "inet", "inet6", "tcp", "tcp6"),
                    )
                # UDP v6
                elif p.pid == getattr(udp6_proc, "pid", None):
                    check_conn(
                        p,
                        conn,
                        AF_INET6,
                        SOCK_DGRAM,
                        udp6_addr,
                        (),
                        psutil.CONN_NONE,
                        ("all", "inet", "inet6", "udp", "udp6"),
                    )

    def test_count(self):
        with create_sockets():
            # tcp
            cons = this_proc_net_connections(kind='tcp')
            assert len(cons) == (2 if supports_ipv6() else 1)
            for conn in cons:
                assert conn.family in (AF_INET, AF_INET6)
                assert conn.type == SOCK_STREAM
            # tcp4
            cons = this_proc_net_connections(kind='tcp4')
            assert len(cons) == 1
            assert cons[0].family == AF_INET
            assert cons[0].type == SOCK_STREAM
            # tcp6
            if supports_ipv6():
                cons = this_proc_net_connections(kind='tcp6')
                assert len(cons) == 1
                assert cons[0].family == AF_INET6
                assert cons[0].type == SOCK_STREAM
            # udp
            cons = this_proc_net_connections(kind='udp')
            assert len(cons) == (2 if supports_ipv6() else 1)
            for conn in cons:
                assert conn.family in (AF_INET, AF_INET6)
                assert conn.type == SOCK_DGRAM
            # udp4
            cons = this_proc_net_connections(kind='udp4')
            assert len(cons) == 1
            assert cons[0].family == AF_INET
            assert cons[0].type == SOCK_DGRAM
            # udp6
            if supports_ipv6():
                cons = this_proc_net_connections(kind='udp6')
                assert len(cons) == 1
                assert cons[0].family == AF_INET6
                assert cons[0].type == SOCK_DGRAM
            # inet
            cons = this_proc_net_connections(kind='inet')
            assert len(cons) == (4 if supports_ipv6() else 2)
            for conn in cons:
                assert conn.family in (AF_INET, AF_INET6)
                assert conn.type in (SOCK_STREAM, SOCK_DGRAM)
            # inet6
            if supports_ipv6():
                cons = this_proc_net_connections(kind='inet6')
                assert len(cons) == 2
                for conn in cons:
                    assert conn.family == AF_INET6
                    assert conn.type in (SOCK_STREAM, SOCK_DGRAM)
            # Skipped on BSD becayse by default the Python process
            # creates a UNIX socket to '/var/run/log'.
            if HAS_NET_CONNECTIONS_UNIX and not (FREEBSD or NETBSD):
                cons = this_proc_net_connections(kind='unix')
                assert len(cons) == 3
                for conn in cons:
                    assert conn.family == AF_UNIX
                    assert conn.type in (SOCK_STREAM, SOCK_DGRAM)


@pytest.mark.skipif(SKIP_SYSCONS, reason="requires root")
class TestSystemWideConnections(ConnectionTestCase):
    """Tests for net_connections()."""

    def test_it(self):
        def check(cons, families, types_):
            for conn in cons:
                assert conn.family in families
                if conn.family != AF_UNIX:
                    assert conn.type in types_
                check_connection_ntuple(conn)

        with create_sockets():
            from psutil._common import conn_tmap

            for kind, groups in conn_tmap.items():
                # XXX: SunOS does not retrieve UNIX sockets.
                if kind == 'unix' and not HAS_NET_CONNECTIONS_UNIX:
                    continue
                families, types_ = groups
                cons = psutil.net_connections(kind)
                assert len(cons) == len(set(cons))
                check(cons, families, types_)

    @retry_on_failure()
    def test_multi_sockets_procs(self):
        # Creates multiple sub processes, each creating different
        # sockets. For each process check that proc.net_connections()
        # and psutil.net_connections() return the same results.
        # This is done mainly to check whether net_connections()'s
        # pid is properly set, see:
        # https://github.com/giampaolo/psutil/issues/1013
        with create_sockets() as socks:
            expected = len(socks)
        pids = []
        times = 10
        fnames = []
        for _ in range(times):
            fname = self.get_testfn()
            fnames.append(fname)
            src = textwrap.dedent("""\
                import time, os
                from psutil.tests import create_sockets
                with create_sockets():
                    with open(r'%s', 'w') as f:
                        f.write("hello")
                    [time.sleep(0.1) for x in range(100)]
                """ % fname)
            sproc = self.pyrun(src)
            pids.append(sproc.pid)

        # sync
        for fname in fnames:
            wait_for_file(fname)

        syscons = [
            x for x in psutil.net_connections(kind='all') if x.pid in pids
        ]
        for pid in pids:
            assert len([x for x in syscons if x.pid == pid]) == expected
            p = psutil.Process(pid)
            assert len(p.net_connections('all')) == expected


class TestMisc(PsutilTestCase):
    def test_net_connection_constants(self):
        ints = []
        strs = []
        for name in dir(psutil):
            if name.startswith('CONN_'):
                num = getattr(psutil, name)
                str_ = str(num)
                assert str_.isupper(), str_
                assert str not in strs
                assert num not in ints
                ints.append(num)
                strs.append(str_)
        if SUNOS:
            psutil.CONN_IDLE  # noqa
            psutil.CONN_BOUND  # noqa
        if WINDOWS:
            psutil.CONN_DELETE_TCB  # noqa
PKok\�TZn�n�psutil/tests/test_process.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for psutil.Process class."""

import collections
import errno
import getpass
import itertools
import os
import signal
import socket
import stat
import string
import subprocess
import sys
import textwrap
import time
import types

import psutil
from psutil import AIX
from psutil import BSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import open_text
from psutil._compat import PY3
from psutil._compat import FileNotFoundError
from psutil._compat import long
from psutil._compat import redirect_stderr
from psutil._compat import super
from psutil.tests import APPVEYOR
from psutil.tests import CI_TESTING
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import GLOBAL_TIMEOUT
from psutil.tests import HAS_CPU_AFFINITY
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_IONICE
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_PROC_CPU_NUM
from psutil.tests import HAS_PROC_IO_COUNTERS
from psutil.tests import HAS_RLIMIT
from psutil.tests import HAS_THREADS
from psutil.tests import MACOS_11PLUS
from psutil.tests import PYPY
from psutil.tests import PYTHON_EXE
from psutil.tests import PYTHON_EXE_ENV
from psutil.tests import QEMU_USER
from psutil.tests import PsutilTestCase
from psutil.tests import ThreadTask
from psutil.tests import call_until
from psutil.tests import copyload_shared_lib
from psutil.tests import create_c_exe
from psutil.tests import create_py_exe
from psutil.tests import mock
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import reap_children
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import skip_on_access_denied
from psutil.tests import skip_on_not_implemented
from psutil.tests import wait_for_pid


# ===================================================================
# --- psutil.Process class tests
# ===================================================================


class TestProcess(PsutilTestCase):
    """Tests for psutil.Process class."""

    def spawn_psproc(self, *args, **kwargs):
        sproc = self.spawn_testproc(*args, **kwargs)
        try:
            return psutil.Process(sproc.pid)
        except psutil.NoSuchProcess:
            self.assertPidGone(sproc.pid)
            raise

    # ---

    def test_pid(self):
        p = psutil.Process()
        assert p.pid == os.getpid()
        with pytest.raises(AttributeError):
            p.pid = 33

    def test_kill(self):
        p = self.spawn_psproc()
        p.kill()
        code = p.wait()
        if WINDOWS:
            assert code == signal.SIGTERM
        else:
            assert code == -signal.SIGKILL
        self.assertProcessGone(p)

    def test_terminate(self):
        p = self.spawn_psproc()
        p.terminate()
        code = p.wait()
        if WINDOWS:
            assert code == signal.SIGTERM
        else:
            assert code == -signal.SIGTERM
        self.assertProcessGone(p)

    def test_send_signal(self):
        sig = signal.SIGKILL if POSIX else signal.SIGTERM
        p = self.spawn_psproc()
        p.send_signal(sig)
        code = p.wait()
        if WINDOWS:
            assert code == sig
        else:
            assert code == -sig
        self.assertProcessGone(p)

    @pytest.mark.skipif(not POSIX, reason="not POSIX")
    def test_send_signal_mocked(self):
        sig = signal.SIGTERM
        p = self.spawn_psproc()
        with mock.patch(
            'psutil.os.kill', side_effect=OSError(errno.ESRCH, "")
        ):
            with pytest.raises(psutil.NoSuchProcess):
                p.send_signal(sig)

        p = self.spawn_psproc()
        with mock.patch(
            'psutil.os.kill', side_effect=OSError(errno.EPERM, "")
        ):
            with pytest.raises(psutil.AccessDenied):
                p.send_signal(sig)

    def test_wait_exited(self):
        # Test waitpid() + WIFEXITED -> WEXITSTATUS.
        # normal return, same as exit(0)
        cmd = [PYTHON_EXE, "-c", "pass"]
        p = self.spawn_psproc(cmd)
        code = p.wait()
        assert code == 0
        self.assertProcessGone(p)
        # exit(1), implicit in case of error
        cmd = [PYTHON_EXE, "-c", "1 / 0"]
        p = self.spawn_psproc(cmd, stderr=subprocess.PIPE)
        code = p.wait()
        assert code == 1
        self.assertProcessGone(p)
        # via sys.exit()
        cmd = [PYTHON_EXE, "-c", "import sys; sys.exit(5);"]
        p = self.spawn_psproc(cmd)
        code = p.wait()
        assert code == 5
        self.assertProcessGone(p)
        # via os._exit()
        cmd = [PYTHON_EXE, "-c", "import os; os._exit(5);"]
        p = self.spawn_psproc(cmd)
        code = p.wait()
        assert code == 5
        self.assertProcessGone(p)

    @pytest.mark.skipif(NETBSD, reason="fails on NETBSD")
    def test_wait_stopped(self):
        p = self.spawn_psproc()
        if POSIX:
            # Test waitpid() + WIFSTOPPED and WIFCONTINUED.
            # Note: if a process is stopped it ignores SIGTERM.
            p.send_signal(signal.SIGSTOP)
            with pytest.raises(psutil.TimeoutExpired):
                p.wait(timeout=0.001)
            p.send_signal(signal.SIGCONT)
            with pytest.raises(psutil.TimeoutExpired):
                p.wait(timeout=0.001)
            p.send_signal(signal.SIGTERM)
            assert p.wait() == -signal.SIGTERM
            assert p.wait() == -signal.SIGTERM
        else:
            p.suspend()
            with pytest.raises(psutil.TimeoutExpired):
                p.wait(timeout=0.001)
            p.resume()
            with pytest.raises(psutil.TimeoutExpired):
                p.wait(timeout=0.001)
            p.terminate()
            assert p.wait() == signal.SIGTERM
            assert p.wait() == signal.SIGTERM

    def test_wait_non_children(self):
        # Test wait() against a process which is not our direct
        # child.
        child, grandchild = self.spawn_children_pair()
        with pytest.raises(psutil.TimeoutExpired):
            child.wait(0.01)
        with pytest.raises(psutil.TimeoutExpired):
            grandchild.wait(0.01)
        # We also terminate the direct child otherwise the
        # grandchild will hang until the parent is gone.
        child.terminate()
        grandchild.terminate()
        child_ret = child.wait()
        grandchild_ret = grandchild.wait()
        if POSIX:
            assert child_ret == -signal.SIGTERM
            # For processes which are not our children we're supposed
            # to get None.
            assert grandchild_ret is None
        else:
            assert child_ret == signal.SIGTERM
            assert child_ret == signal.SIGTERM

    def test_wait_timeout(self):
        p = self.spawn_psproc()
        p.name()
        with pytest.raises(psutil.TimeoutExpired):
            p.wait(0.01)
        with pytest.raises(psutil.TimeoutExpired):
            p.wait(0)
        with pytest.raises(ValueError):
            p.wait(-1)

    def test_wait_timeout_nonblocking(self):
        p = self.spawn_psproc()
        with pytest.raises(psutil.TimeoutExpired):
            p.wait(0)
        p.kill()
        stop_at = time.time() + GLOBAL_TIMEOUT
        while time.time() < stop_at:
            try:
                code = p.wait(0)
                break
            except psutil.TimeoutExpired:
                pass
        else:
            raise self.fail('timeout')
        if POSIX:
            assert code == -signal.SIGKILL
        else:
            assert code == signal.SIGTERM
        self.assertProcessGone(p)

    def test_cpu_percent(self):
        p = psutil.Process()
        p.cpu_percent(interval=0.001)
        p.cpu_percent(interval=0.001)
        for _ in range(100):
            percent = p.cpu_percent(interval=None)
            assert isinstance(percent, float)
            assert percent >= 0.0
        with pytest.raises(ValueError):
            p.cpu_percent(interval=-1)

    def test_cpu_percent_numcpus_none(self):
        # See: https://github.com/giampaolo/psutil/issues/1087
        with mock.patch('psutil.cpu_count', return_value=None) as m:
            psutil.Process().cpu_percent()
            assert m.called

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_cpu_times(self):
        times = psutil.Process().cpu_times()
        assert times.user >= 0.0, times
        assert times.system >= 0.0, times
        assert times.children_user >= 0.0, times
        assert times.children_system >= 0.0, times
        if LINUX:
            assert times.iowait >= 0.0, times
        # make sure returned values can be pretty printed with strftime
        for name in times._fields:
            time.strftime("%H:%M:%S", time.localtime(getattr(times, name)))

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_cpu_times_2(self):
        user_time, kernel_time = psutil.Process().cpu_times()[:2]
        utime, ktime = os.times()[:2]

        # Use os.times()[:2] as base values to compare our results
        # using a tolerance  of +/- 0.1 seconds.
        # It will fail if the difference between the values is > 0.1s.
        if (max([user_time, utime]) - min([user_time, utime])) > 0.1:
            raise self.fail("expected: %s, found: %s" % (utime, user_time))

        if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1:
            raise self.fail("expected: %s, found: %s" % (ktime, kernel_time))

    @pytest.mark.skipif(not HAS_PROC_CPU_NUM, reason="not supported")
    def test_cpu_num(self):
        p = psutil.Process()
        num = p.cpu_num()
        assert num >= 0
        if psutil.cpu_count() == 1:
            assert num == 0
        assert p.cpu_num() in range(psutil.cpu_count())

    def test_create_time(self):
        p = self.spawn_psproc()
        now = time.time()
        create_time = p.create_time()

        # Use time.time() as base value to compare our result using a
        # tolerance of +/- 1 second.
        # It will fail if the difference between the values is > 2s.
        difference = abs(create_time - now)
        if difference > 2:
            raise self.fail(
                "expected: %s, found: %s, difference: %s"
                % (now, create_time, difference)
            )

        # make sure returned value can be pretty printed with strftime
        time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time()))

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_terminal(self):
        terminal = psutil.Process().terminal()
        if terminal is not None:
            try:
                tty = os.path.realpath(sh('tty'))
            except RuntimeError:
                # Note: happens if pytest is run without the `-s` opt.
                raise pytest.skip("can't rely on `tty` CLI")
            else:
                assert terminal == tty

    @pytest.mark.skipif(not HAS_PROC_IO_COUNTERS, reason="not supported")
    @skip_on_not_implemented(only_if=LINUX)
    def test_io_counters(self):
        p = psutil.Process()
        # test reads
        io1 = p.io_counters()
        with open(PYTHON_EXE, 'rb') as f:
            f.read()
        io2 = p.io_counters()
        if not BSD and not AIX:
            assert io2.read_count > io1.read_count
            assert io2.write_count == io1.write_count
            if LINUX:
                assert io2.read_chars > io1.read_chars
                assert io2.write_chars == io1.write_chars
        else:
            assert io2.read_bytes >= io1.read_bytes
            assert io2.write_bytes >= io1.write_bytes

        # test writes
        io1 = p.io_counters()
        with open(self.get_testfn(), 'wb') as f:
            if PY3:
                f.write(bytes("x" * 1000000, 'ascii'))
            else:
                f.write("x" * 1000000)
        io2 = p.io_counters()
        assert io2.write_count >= io1.write_count
        assert io2.write_bytes >= io1.write_bytes
        assert io2.read_count >= io1.read_count
        assert io2.read_bytes >= io1.read_bytes
        if LINUX:
            assert io2.write_chars > io1.write_chars
            assert io2.read_chars >= io1.read_chars

        # sanity check
        for i in range(len(io2)):
            if BSD and i >= 2:
                # On BSD read_bytes and write_bytes are always set to -1.
                continue
            assert io2[i] >= 0
            assert io2[i] >= 0

    @pytest.mark.skipif(not HAS_IONICE, reason="not supported")
    @pytest.mark.skipif(not LINUX, reason="linux only")
    def test_ionice_linux(self):
        def cleanup(init):
            ioclass, value = init
            if ioclass == psutil.IOPRIO_CLASS_NONE:
                value = 0
            p.ionice(ioclass, value)

        p = psutil.Process()
        if not CI_TESTING:
            assert p.ionice()[0] == psutil.IOPRIO_CLASS_NONE
        assert psutil.IOPRIO_CLASS_NONE == 0
        assert psutil.IOPRIO_CLASS_RT == 1  # high
        assert psutil.IOPRIO_CLASS_BE == 2  # normal
        assert psutil.IOPRIO_CLASS_IDLE == 3  # low
        init = p.ionice()
        self.addCleanup(cleanup, init)

        # low
        p.ionice(psutil.IOPRIO_CLASS_IDLE)
        assert tuple(p.ionice()) == (psutil.IOPRIO_CLASS_IDLE, 0)
        with pytest.raises(ValueError):  # accepts no value
            p.ionice(psutil.IOPRIO_CLASS_IDLE, value=7)
        # normal
        p.ionice(psutil.IOPRIO_CLASS_BE)
        assert tuple(p.ionice()) == (psutil.IOPRIO_CLASS_BE, 0)
        p.ionice(psutil.IOPRIO_CLASS_BE, value=7)
        assert tuple(p.ionice()) == (psutil.IOPRIO_CLASS_BE, 7)
        with pytest.raises(ValueError):
            p.ionice(psutil.IOPRIO_CLASS_BE, value=8)
        try:
            p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
        except psutil.AccessDenied:
            pass
        # errs
        with pytest.raises(ValueError, match="ioclass accepts no value"):
            p.ionice(psutil.IOPRIO_CLASS_NONE, 1)
        with pytest.raises(ValueError, match="ioclass accepts no value"):
            p.ionice(psutil.IOPRIO_CLASS_IDLE, 1)
        with pytest.raises(
            ValueError, match="'ioclass' argument must be specified"
        ):
            p.ionice(value=1)

    @pytest.mark.skipif(not HAS_IONICE, reason="not supported")
    @pytest.mark.skipif(
        not WINDOWS, reason="not supported on this win version"
    )
    def test_ionice_win(self):
        p = psutil.Process()
        if not CI_TESTING:
            assert p.ionice() == psutil.IOPRIO_NORMAL
        init = p.ionice()
        self.addCleanup(p.ionice, init)

        # base
        p.ionice(psutil.IOPRIO_VERYLOW)
        assert p.ionice() == psutil.IOPRIO_VERYLOW
        p.ionice(psutil.IOPRIO_LOW)
        assert p.ionice() == psutil.IOPRIO_LOW
        try:
            p.ionice(psutil.IOPRIO_HIGH)
        except psutil.AccessDenied:
            pass
        else:
            assert p.ionice() == psutil.IOPRIO_HIGH
        # errs
        with pytest.raises(
            TypeError, match="value argument not accepted on Windows"
        ):
            p.ionice(psutil.IOPRIO_NORMAL, value=1)
        with pytest.raises(ValueError, match="is not a valid priority"):
            p.ionice(psutil.IOPRIO_HIGH + 1)

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_get(self):
        import resource

        p = psutil.Process(os.getpid())
        names = [x for x in dir(psutil) if x.startswith('RLIMIT')]
        assert names, names
        for name in names:
            value = getattr(psutil, name)
            assert value >= 0
            if name in dir(resource):
                assert value == getattr(resource, name)
                # XXX - On PyPy RLIMIT_INFINITY returned by
                # resource.getrlimit() is reported as a very big long
                # number instead of -1. It looks like a bug with PyPy.
                if PYPY:
                    continue
                assert p.rlimit(value) == resource.getrlimit(value)
            else:
                ret = p.rlimit(value)
                assert len(ret) == 2
                assert ret[0] >= -1
                assert ret[1] >= -1

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_set(self):
        p = self.spawn_psproc()
        p.rlimit(psutil.RLIMIT_NOFILE, (5, 5))
        assert p.rlimit(psutil.RLIMIT_NOFILE) == (5, 5)
        # If pid is 0 prlimit() applies to the calling process and
        # we don't want that.
        if LINUX:
            with pytest.raises(ValueError, match="can't use prlimit"):
                psutil._psplatform.Process(0).rlimit(0)
        with pytest.raises(ValueError):
            p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5))

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit(self):
        p = psutil.Process()
        testfn = self.get_testfn()
        soft, hard = p.rlimit(psutil.RLIMIT_FSIZE)
        try:
            p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard))
            with open(testfn, "wb") as f:
                f.write(b"X" * 1024)
            # write() or flush() doesn't always cause the exception
            # but close() will.
            with pytest.raises(IOError) as exc:
                with open(testfn, "wb") as f:
                    f.write(b"X" * 1025)
            assert (exc.value.errno if PY3 else exc.value[0]) == errno.EFBIG
        finally:
            p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard))
            assert p.rlimit(psutil.RLIMIT_FSIZE) == (soft, hard)

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_infinity(self):
        # First set a limit, then re-set it by specifying INFINITY
        # and assume we overridden the previous limit.
        p = psutil.Process()
        soft, hard = p.rlimit(psutil.RLIMIT_FSIZE)
        try:
            p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard))
            p.rlimit(psutil.RLIMIT_FSIZE, (psutil.RLIM_INFINITY, hard))
            with open(self.get_testfn(), "wb") as f:
                f.write(b"X" * 2048)
        finally:
            p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard))
            assert p.rlimit(psutil.RLIMIT_FSIZE) == (soft, hard)

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_infinity_value(self):
        # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really
        # big number on a platform with large file support.  On these
        # platforms we need to test that the get/setrlimit functions
        # properly convert the number to a C long long and that the
        # conversion doesn't raise an error.
        p = psutil.Process()
        soft, hard = p.rlimit(psutil.RLIMIT_FSIZE)
        assert hard == psutil.RLIM_INFINITY
        p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard))

    def test_num_threads(self):
        # on certain platforms such as Linux we might test for exact
        # thread number, since we always have with 1 thread per process,
        # but this does not apply across all platforms (MACOS, Windows)
        p = psutil.Process()
        if OPENBSD:
            try:
                step1 = p.num_threads()
            except psutil.AccessDenied:
                raise pytest.skip("on OpenBSD this requires root access")
        else:
            step1 = p.num_threads()

        with ThreadTask():
            step2 = p.num_threads()
            assert step2 == step1 + 1

    @pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
    def test_num_handles(self):
        # a better test is done later into test/_windows.py
        p = psutil.Process()
        assert p.num_handles() > 0

    @pytest.mark.skipif(not HAS_THREADS, reason="not supported")
    def test_threads(self):
        p = psutil.Process()
        if OPENBSD:
            try:
                step1 = p.threads()
            except psutil.AccessDenied:
                raise pytest.skip("on OpenBSD this requires root access")
        else:
            step1 = p.threads()

        with ThreadTask():
            step2 = p.threads()
            assert len(step2) == len(step1) + 1
            athread = step2[0]
            # test named tuple
            assert athread.id == athread[0]
            assert athread.user_time == athread[1]
            assert athread.system_time == athread[2]

    @retry_on_failure()
    @skip_on_access_denied(only_if=MACOS)
    @pytest.mark.skipif(not HAS_THREADS, reason="not supported")
    def test_threads_2(self):
        p = self.spawn_psproc()
        if OPENBSD:
            try:
                p.threads()
            except psutil.AccessDenied:
                raise pytest.skip("on OpenBSD this requires root access")
        assert (
            abs(p.cpu_times().user - sum([x.user_time for x in p.threads()]))
            < 0.1
        )
        assert (
            abs(
                p.cpu_times().system
                - sum([x.system_time for x in p.threads()])
            )
            < 0.1
        )

    @retry_on_failure()
    def test_memory_info(self):
        p = psutil.Process()

        # step 1 - get a base value to compare our results
        rss1, vms1 = p.memory_info()[:2]
        percent1 = p.memory_percent()
        assert rss1 > 0
        assert vms1 > 0

        # step 2 - allocate some memory
        memarr = [None] * 1500000

        rss2, vms2 = p.memory_info()[:2]
        percent2 = p.memory_percent()

        # step 3 - make sure that the memory usage bumped up
        assert rss2 > rss1
        assert vms2 >= vms1  # vms might be equal
        assert percent2 > percent1
        del memarr

        if WINDOWS:
            mem = p.memory_info()
            assert mem.rss == mem.wset
            assert mem.vms == mem.pagefile

        mem = p.memory_info()
        for name in mem._fields:
            assert getattr(mem, name) >= 0

    def test_memory_full_info(self):
        p = psutil.Process()
        total = psutil.virtual_memory().total
        mem = p.memory_full_info()
        for name in mem._fields:
            value = getattr(mem, name)
            assert value >= 0
            if name == 'vms' and OSX or LINUX:
                continue
            assert value <= total
        if LINUX or WINDOWS or MACOS:
            assert mem.uss >= 0
        if LINUX:
            assert mem.pss >= 0
            assert mem.swap >= 0

    @pytest.mark.skipif(not HAS_MEMORY_MAPS, reason="not supported")
    def test_memory_maps(self):
        p = psutil.Process()
        maps = p.memory_maps()
        assert len(maps) == len(set(maps))
        ext_maps = p.memory_maps(grouped=False)

        for nt in maps:
            if not nt.path.startswith('['):
                if QEMU_USER and "/bin/qemu-" in nt.path:
                    continue
                assert os.path.isabs(nt.path), nt.path
                if POSIX:
                    try:
                        assert os.path.exists(nt.path) or os.path.islink(
                            nt.path
                        ), nt.path
                    except AssertionError:
                        if not LINUX:
                            raise
                        else:
                            # https://github.com/giampaolo/psutil/issues/759
                            with open_text('/proc/self/smaps') as f:
                                data = f.read()
                            if "%s (deleted)" % nt.path not in data:
                                raise
                else:
                    # XXX - On Windows we have this strange behavior with
                    # 64 bit dlls: they are visible via explorer but cannot
                    # be accessed via os.stat() (wtf?).
                    if '64' not in os.path.basename(nt.path):
                        try:
                            st = os.stat(nt.path)
                        except FileNotFoundError:
                            pass
                        else:
                            assert stat.S_ISREG(st.st_mode), nt.path
        for nt in ext_maps:
            for fname in nt._fields:
                value = getattr(nt, fname)
                if fname == 'path':
                    continue
                if fname in ('addr', 'perms'):
                    assert value, value
                else:
                    assert isinstance(value, (int, long))
                    assert value >= 0, value

    @pytest.mark.skipif(not HAS_MEMORY_MAPS, reason="not supported")
    def test_memory_maps_lists_lib(self):
        # Make sure a newly loaded shared lib is listed.
        p = psutil.Process()
        with copyload_shared_lib() as path:

            def normpath(p):
                return os.path.realpath(os.path.normcase(p))

            libpaths = [normpath(x.path) for x in p.memory_maps()]
            assert normpath(path) in libpaths

    def test_memory_percent(self):
        p = psutil.Process()
        p.memory_percent()
        with pytest.raises(ValueError):
            p.memory_percent(memtype="?!?")
        if LINUX or MACOS or WINDOWS:
            p.memory_percent(memtype='uss')

    def test_is_running(self):
        p = self.spawn_psproc()
        assert p.is_running()
        assert p.is_running()
        p.kill()
        p.wait()
        assert not p.is_running()
        assert not p.is_running()

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_exe(self):
        p = self.spawn_psproc()
        exe = p.exe()
        try:
            assert exe == PYTHON_EXE
        except AssertionError:
            if WINDOWS and len(exe) == len(PYTHON_EXE):
                # on Windows we don't care about case sensitivity
                normcase = os.path.normcase
                assert normcase(exe) == normcase(PYTHON_EXE)
            else:
                # certain platforms such as BSD are more accurate returning:
                # "/usr/local/bin/python2.7"
                # ...instead of:
                # "/usr/local/bin/python"
                # We do not want to consider this difference in accuracy
                # an error.
                ver = "%s.%s" % (sys.version_info[0], sys.version_info[1])
                try:
                    assert exe.replace(ver, '') == PYTHON_EXE.replace(ver, '')
                except AssertionError:
                    # Typically MACOS. Really not sure what to do here.
                    pass

        out = sh([exe, "-c", "import os; print('hey')"])
        assert out == 'hey'

    def test_cmdline(self):
        cmdline = [
            PYTHON_EXE,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        p = self.spawn_psproc(cmdline)

        if NETBSD and p.cmdline() == []:
            # https://github.com/giampaolo/psutil/issues/2250
            raise pytest.skip("OPENBSD: returned EBUSY")

        # XXX - most of the times the underlying sysctl() call on Net
        # and Open BSD returns a truncated string.
        # Also /proc/pid/cmdline behaves the same so it looks
        # like this is a kernel bug.
        # XXX - AIX truncates long arguments in /proc/pid/cmdline
        if NETBSD or OPENBSD or AIX:
            assert p.cmdline()[0] == PYTHON_EXE
        else:
            if MACOS and CI_TESTING:
                pyexe = p.cmdline()[0]
                if pyexe != PYTHON_EXE:
                    assert ' '.join(p.cmdline()[1:]) == ' '.join(cmdline[1:])
                    return
            if QEMU_USER:
                assert ' '.join(p.cmdline()[2:]) == ' '.join(cmdline)
                return
            assert ' '.join(p.cmdline()) == ' '.join(cmdline)

    @pytest.mark.skipif(PYPY, reason="broken on PYPY")
    def test_long_cmdline(self):
        cmdline = [PYTHON_EXE]
        cmdline.extend(["-v"] * 50)
        cmdline.extend(
            ["-c", "import time; [time.sleep(0.1) for x in range(100)]"]
        )
        p = self.spawn_psproc(cmdline)
        if OPENBSD:
            # XXX: for some reason the test process may turn into a
            # zombie (don't know why).
            try:
                assert p.cmdline() == cmdline
            except psutil.ZombieProcess:
                raise pytest.skip("OPENBSD: process turned into zombie")
        elif QEMU_USER:
            assert p.cmdline()[2:] == cmdline
        else:
            ret = p.cmdline()
            if NETBSD and ret == []:
                # https://github.com/giampaolo/psutil/issues/2250
                raise pytest.skip("OPENBSD: returned EBUSY")
            assert ret == cmdline

    def test_name(self):
        p = self.spawn_psproc()
        name = p.name().lower()
        pyexe = os.path.basename(os.path.realpath(sys.executable)).lower()
        assert pyexe.startswith(name), (pyexe, name)

    @pytest.mark.skipif(PYPY or QEMU_USER, reason="unreliable on PYPY")
    @pytest.mark.skipif(QEMU_USER, reason="unreliable on QEMU user")
    def test_long_name(self):
        pyexe = create_py_exe(self.get_testfn(suffix=string.digits * 2))
        cmdline = [
            pyexe,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        p = self.spawn_psproc(cmdline)
        if OPENBSD:
            # XXX: for some reason the test process may turn into a
            # zombie (don't know why). Because the name() is long, all
            # UNIX kernels truncate it to 15 chars, so internally psutil
            # tries to guess the full name() from the cmdline(). But the
            # cmdline() of a zombie on OpenBSD fails (internally), so we
            # just compare the first 15 chars. Full explanation:
            # https://github.com/giampaolo/psutil/issues/2239
            try:
                assert p.name() == os.path.basename(pyexe)
            except AssertionError:
                if p.status() == psutil.STATUS_ZOMBIE:
                    assert os.path.basename(pyexe).startswith(p.name())
                else:
                    raise
        else:
            assert p.name() == os.path.basename(pyexe)

    # XXX
    @pytest.mark.skipif(SUNOS, reason="broken on SUNOS")
    @pytest.mark.skipif(AIX, reason="broken on AIX")
    @pytest.mark.skipif(PYPY, reason="broken on PYPY")
    @pytest.mark.skipif(QEMU_USER, reason="broken on QEMU user")
    def test_prog_w_funky_name(self):
        # Test that name(), exe() and cmdline() correctly handle programs
        # with funky chars such as spaces and ")", see:
        # https://github.com/giampaolo/psutil/issues/628
        pyexe = create_py_exe(self.get_testfn(suffix='foo bar )'))
        cmdline = [
            pyexe,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        p = self.spawn_psproc(cmdline)
        assert p.cmdline() == cmdline
        assert p.name() == os.path.basename(pyexe)
        assert os.path.normcase(p.exe()) == os.path.normcase(pyexe)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_uids(self):
        p = psutil.Process()
        real, effective, _saved = p.uids()
        # os.getuid() refers to "real" uid
        assert real == os.getuid()
        # os.geteuid() refers to "effective" uid
        assert effective == os.geteuid()
        # No such thing as os.getsuid() ("saved" uid), but starting
        # from python 2.7 we have os.getresuid() which returns all
        # of them.
        if hasattr(os, "getresuid"):
            assert os.getresuid() == p.uids()

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_gids(self):
        p = psutil.Process()
        real, effective, _saved = p.gids()
        # os.getuid() refers to "real" uid
        assert real == os.getgid()
        # os.geteuid() refers to "effective" uid
        assert effective == os.getegid()
        # No such thing as os.getsgid() ("saved" gid), but starting
        # from python 2.7 we have os.getresgid() which returns all
        # of them.
        if hasattr(os, "getresuid"):
            assert os.getresgid() == p.gids()

    def test_nice(self):
        def cleanup(init):
            try:
                p.nice(init)
            except psutil.AccessDenied:
                pass

        p = psutil.Process()
        with pytest.raises(TypeError):
            p.nice("str")
        init = p.nice()
        self.addCleanup(cleanup, init)

        if WINDOWS:
            highest_prio = None
            for prio in [
                psutil.IDLE_PRIORITY_CLASS,
                psutil.BELOW_NORMAL_PRIORITY_CLASS,
                psutil.NORMAL_PRIORITY_CLASS,
                psutil.ABOVE_NORMAL_PRIORITY_CLASS,
                psutil.HIGH_PRIORITY_CLASS,
                psutil.REALTIME_PRIORITY_CLASS,
            ]:
                with self.subTest(prio=prio):
                    try:
                        p.nice(prio)
                    except psutil.AccessDenied:
                        pass
                    else:
                        new_prio = p.nice()
                        # The OS may limit our maximum priority,
                        # even if the function succeeds. For higher
                        # priorities, we match either the expected
                        # value or the highest so far.
                        if prio in (
                            psutil.ABOVE_NORMAL_PRIORITY_CLASS,
                            psutil.HIGH_PRIORITY_CLASS,
                            psutil.REALTIME_PRIORITY_CLASS,
                        ):
                            if new_prio == prio or highest_prio is None:
                                highest_prio = prio
                                assert new_prio == highest_prio
                        else:
                            assert new_prio == prio
        else:
            try:
                if hasattr(os, "getpriority"):
                    assert (
                        os.getpriority(os.PRIO_PROCESS, os.getpid())
                        == p.nice()
                    )
                p.nice(1)
                assert p.nice() == 1
                if hasattr(os, "getpriority"):
                    assert (
                        os.getpriority(os.PRIO_PROCESS, os.getpid())
                        == p.nice()
                    )
                # XXX - going back to previous nice value raises
                # AccessDenied on MACOS
                if not MACOS:
                    p.nice(0)
                    assert p.nice() == 0
            except psutil.AccessDenied:
                pass

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_status(self):
        p = psutil.Process()
        assert p.status() == psutil.STATUS_RUNNING

    def test_username(self):
        p = self.spawn_psproc()
        username = p.username()
        if WINDOWS:
            domain, username = username.split('\\')
            getpass_user = getpass.getuser()
            if getpass_user.endswith('$'):
                # When running as a service account (most likely to be
                # NetworkService), these user name calculations don't produce
                # the same result, causing the test to fail.
                raise pytest.skip('running as service account')
            assert username == getpass_user
            if 'USERDOMAIN' in os.environ:
                assert domain == os.environ['USERDOMAIN']
        else:
            assert username == getpass.getuser()

    def test_cwd(self):
        p = self.spawn_psproc()
        assert p.cwd() == os.getcwd()

    def test_cwd_2(self):
        cmd = [
            PYTHON_EXE,
            "-c",
            (
                "import os, time; os.chdir('..'); [time.sleep(0.1) for x in"
                " range(100)]"
            ),
        ]
        p = self.spawn_psproc(cmd)
        call_until(lambda: p.cwd() == os.path.dirname(os.getcwd()))

    @pytest.mark.skipif(not HAS_CPU_AFFINITY, reason="not supported")
    def test_cpu_affinity(self):
        p = psutil.Process()
        initial = p.cpu_affinity()
        assert initial, initial
        self.addCleanup(p.cpu_affinity, initial)

        if hasattr(os, "sched_getaffinity"):
            assert initial == list(os.sched_getaffinity(p.pid))
        assert len(initial) == len(set(initial))

        all_cpus = list(range(len(psutil.cpu_percent(percpu=True))))
        for n in all_cpus:
            p.cpu_affinity([n])
            assert p.cpu_affinity() == [n]
            if hasattr(os, "sched_getaffinity"):
                assert p.cpu_affinity() == list(os.sched_getaffinity(p.pid))
            # also test num_cpu()
            if hasattr(p, "num_cpu"):
                assert p.cpu_affinity()[0] == p.num_cpu()

        # [] is an alias for "all eligible CPUs"; on Linux this may
        # not be equal to all available CPUs, see:
        # https://github.com/giampaolo/psutil/issues/956
        p.cpu_affinity([])
        if LINUX:
            assert p.cpu_affinity() == p._proc._get_eligible_cpus()
        else:
            assert p.cpu_affinity() == all_cpus
        if hasattr(os, "sched_getaffinity"):
            assert p.cpu_affinity() == list(os.sched_getaffinity(p.pid))

        with pytest.raises(TypeError):
            p.cpu_affinity(1)
        p.cpu_affinity(initial)
        # it should work with all iterables, not only lists
        p.cpu_affinity(set(all_cpus))
        p.cpu_affinity(tuple(all_cpus))

    @pytest.mark.skipif(not HAS_CPU_AFFINITY, reason="not supported")
    def test_cpu_affinity_errs(self):
        p = self.spawn_psproc()
        invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10]
        with pytest.raises(ValueError):
            p.cpu_affinity(invalid_cpu)
        with pytest.raises(ValueError):
            p.cpu_affinity(range(10000, 11000))
        with pytest.raises(TypeError):
            p.cpu_affinity([0, "1"])
        with pytest.raises(ValueError):
            p.cpu_affinity([0, -1])

    @pytest.mark.skipif(not HAS_CPU_AFFINITY, reason="not supported")
    def test_cpu_affinity_all_combinations(self):
        p = psutil.Process()
        initial = p.cpu_affinity()
        assert initial, initial
        self.addCleanup(p.cpu_affinity, initial)

        # All possible CPU set combinations.
        if len(initial) > 12:
            initial = initial[:12]  # ...otherwise it will take forever
        combos = []
        for i in range(len(initial) + 1):
            for subset in itertools.combinations(initial, i):
                if subset:
                    combos.append(list(subset))

        for combo in combos:
            p.cpu_affinity(combo)
            assert sorted(p.cpu_affinity()) == sorted(combo)

    # TODO: #595
    @pytest.mark.skipif(BSD, reason="broken on BSD")
    # can't find any process file on Appveyor
    @pytest.mark.skipif(APPVEYOR, reason="unreliable on APPVEYOR")
    def test_open_files(self):
        p = psutil.Process()
        testfn = self.get_testfn()
        files = p.open_files()
        assert testfn not in files
        with open(testfn, 'wb') as f:
            f.write(b'x' * 1024)
            f.flush()
            # give the kernel some time to see the new file
            call_until(lambda: len(p.open_files()) != len(files))
            files = p.open_files()
            filenames = [os.path.normcase(x.path) for x in files]
            assert os.path.normcase(testfn) in filenames
            if LINUX:
                for file in files:
                    if file.path == testfn:
                        assert file.position == 1024
        for file in files:
            assert os.path.isfile(file.path), file

        # another process
        cmdline = (
            "import time; f = open(r'%s', 'r'); [time.sleep(0.1) for x in"
            " range(100)];" % testfn
        )
        p = self.spawn_psproc([PYTHON_EXE, "-c", cmdline])

        for x in range(100):
            filenames = [os.path.normcase(x.path) for x in p.open_files()]
            if testfn in filenames:
                break
            time.sleep(0.01)
        else:
            assert os.path.normcase(testfn) in filenames
        for file in filenames:
            assert os.path.isfile(file), file

    # TODO: #595
    @pytest.mark.skipif(BSD, reason="broken on BSD")
    # can't find any process file on Appveyor
    @pytest.mark.skipif(APPVEYOR, reason="unreliable on APPVEYOR")
    def test_open_files_2(self):
        # test fd and path fields
        p = psutil.Process()
        normcase = os.path.normcase
        testfn = self.get_testfn()
        with open(testfn, 'w') as fileobj:
            for file in p.open_files():
                if (
                    normcase(file.path) == normcase(fileobj.name)
                    or file.fd == fileobj.fileno()
                ):
                    break
            else:
                raise self.fail(
                    "no file found; files=%s" % (repr(p.open_files()))
                )
            assert normcase(file.path) == normcase(fileobj.name)
            if WINDOWS:
                assert file.fd == -1
            else:
                assert file.fd == fileobj.fileno()
            # test positions
            ntuple = p.open_files()[0]
            assert ntuple[0] == ntuple.path
            assert ntuple[1] == ntuple.fd
            # test file is gone
            assert fileobj.name not in p.open_files()

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_num_fds(self):
        p = psutil.Process()
        testfn = self.get_testfn()
        start = p.num_fds()
        file = open(testfn, 'w')
        self.addCleanup(file.close)
        assert p.num_fds() == start + 1
        sock = socket.socket()
        self.addCleanup(sock.close)
        assert p.num_fds() == start + 2
        file.close()
        sock.close()
        assert p.num_fds() == start

    @skip_on_not_implemented(only_if=LINUX)
    @pytest.mark.skipif(
        OPENBSD or NETBSD, reason="not reliable on OPENBSD & NETBSD"
    )
    def test_num_ctx_switches(self):
        p = psutil.Process()
        before = sum(p.num_ctx_switches())
        for _ in range(2):
            time.sleep(0.05)  # this shall ensure a context switch happens
            after = sum(p.num_ctx_switches())
            if after > before:
                return
        raise self.fail("num ctx switches still the same after 2 iterations")

    def test_ppid(self):
        p = psutil.Process()
        if hasattr(os, 'getppid'):
            assert p.ppid() == os.getppid()
        p = self.spawn_psproc()
        assert p.ppid() == os.getpid()

    def test_parent(self):
        p = self.spawn_psproc()
        assert p.parent().pid == os.getpid()

        lowest_pid = psutil.pids()[0]
        assert psutil.Process(lowest_pid).parent() is None

    def test_parent_multi(self):
        parent = psutil.Process()
        child, grandchild = self.spawn_children_pair()
        assert grandchild.parent() == child
        assert child.parent() == parent

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    @retry_on_failure()
    def test_parents(self):
        parent = psutil.Process()
        assert parent.parents()
        child, grandchild = self.spawn_children_pair()
        assert child.parents()[0] == parent
        assert grandchild.parents()[0] == child
        assert grandchild.parents()[1] == parent

    def test_children(self):
        parent = psutil.Process()
        assert parent.children() == []
        assert parent.children(recursive=True) == []
        # On Windows we set the flag to 0 in order to cancel out the
        # CREATE_NO_WINDOW flag (enabled by default) which creates
        # an extra "conhost.exe" child.
        child = self.spawn_psproc(creationflags=0)
        children1 = parent.children()
        children2 = parent.children(recursive=True)
        for children in (children1, children2):
            assert len(children) == 1
            assert children[0].pid == child.pid
            assert children[0].ppid() == parent.pid

    def test_children_recursive(self):
        # Test children() against two sub processes, p1 and p2, where
        # p1 (our child) spawned p2 (our grandchild).
        parent = psutil.Process()
        child, grandchild = self.spawn_children_pair()
        assert parent.children() == [child]
        assert parent.children(recursive=True) == [child, grandchild]
        # If the intermediate process is gone there's no way for
        # children() to recursively find it.
        child.terminate()
        child.wait()
        assert parent.children(recursive=True) == []

    def test_children_duplicates(self):
        # find the process which has the highest number of children
        table = collections.defaultdict(int)
        for p in psutil.process_iter():
            try:
                table[p.ppid()] += 1
            except psutil.Error:
                pass
        # this is the one, now let's make sure there are no duplicates
        pid = sorted(table.items(), key=lambda x: x[1])[-1][0]
        if LINUX and pid == 0:
            raise pytest.skip("PID 0")
        p = psutil.Process(pid)
        try:
            c = p.children(recursive=True)
        except psutil.AccessDenied:  # windows
            pass
        else:
            assert len(c) == len(set(c))

    def test_parents_and_children(self):
        parent = psutil.Process()
        child, grandchild = self.spawn_children_pair()
        # forward
        children = parent.children(recursive=True)
        assert len(children) == 2
        assert children[0] == child
        assert children[1] == grandchild
        # backward
        parents = grandchild.parents()
        assert parents[0] == child
        assert parents[1] == parent

    def test_suspend_resume(self):
        p = self.spawn_psproc()
        p.suspend()
        for _ in range(100):
            if p.status() == psutil.STATUS_STOPPED:
                break
            time.sleep(0.01)
        p.resume()
        assert p.status() != psutil.STATUS_STOPPED

    def test_invalid_pid(self):
        with pytest.raises(TypeError):
            psutil.Process("1")
        with pytest.raises(ValueError):
            psutil.Process(-1)

    def test_as_dict(self):
        p = psutil.Process()
        d = p.as_dict(attrs=['exe', 'name'])
        assert sorted(d.keys()) == ['exe', 'name']

        p = psutil.Process(min(psutil.pids()))
        d = p.as_dict(attrs=['net_connections'], ad_value='foo')
        if not isinstance(d['net_connections'], list):
            assert d['net_connections'] == 'foo'

        # Test ad_value is set on AccessDenied.
        with mock.patch(
            'psutil.Process.nice', create=True, side_effect=psutil.AccessDenied
        ):
            assert p.as_dict(attrs=["nice"], ad_value=1) == {"nice": 1}

        # Test that NoSuchProcess bubbles up.
        with mock.patch(
            'psutil.Process.nice',
            create=True,
            side_effect=psutil.NoSuchProcess(p.pid, "name"),
        ):
            with pytest.raises(psutil.NoSuchProcess):
                p.as_dict(attrs=["nice"])

        # Test that ZombieProcess is swallowed.
        with mock.patch(
            'psutil.Process.nice',
            create=True,
            side_effect=psutil.ZombieProcess(p.pid, "name"),
        ):
            assert p.as_dict(attrs=["nice"], ad_value="foo") == {"nice": "foo"}

        # By default APIs raising NotImplementedError are
        # supposed to be skipped.
        with mock.patch(
            'psutil.Process.nice', create=True, side_effect=NotImplementedError
        ):
            d = p.as_dict()
            assert 'nice' not in list(d.keys())
            # ...unless the user explicitly asked for some attr.
            with pytest.raises(NotImplementedError):
                p.as_dict(attrs=["nice"])

        # errors
        with pytest.raises(TypeError):
            p.as_dict('name')
        with pytest.raises(ValueError):
            p.as_dict(['foo'])
        with pytest.raises(ValueError):
            p.as_dict(['foo', 'bar'])

    def test_oneshot(self):
        p = psutil.Process()
        with mock.patch("psutil._psplatform.Process.cpu_times") as m:
            with p.oneshot():
                p.cpu_times()
                p.cpu_times()
            assert m.call_count == 1

        with mock.patch("psutil._psplatform.Process.cpu_times") as m:
            p.cpu_times()
            p.cpu_times()
        assert m.call_count == 2

    def test_oneshot_twice(self):
        # Test the case where the ctx manager is __enter__ed twice.
        # The second __enter__ is supposed to resut in a NOOP.
        p = psutil.Process()
        with mock.patch("psutil._psplatform.Process.cpu_times") as m1:
            with mock.patch("psutil._psplatform.Process.oneshot_enter") as m2:
                with p.oneshot():
                    p.cpu_times()
                    p.cpu_times()
                    with p.oneshot():
                        p.cpu_times()
                        p.cpu_times()
                assert m1.call_count == 1
                assert m2.call_count == 1

        with mock.patch("psutil._psplatform.Process.cpu_times") as m:
            p.cpu_times()
            p.cpu_times()
        assert m.call_count == 2

    def test_oneshot_cache(self):
        # Make sure oneshot() cache is nonglobal. Instead it's
        # supposed to be bound to the Process instance, see:
        # https://github.com/giampaolo/psutil/issues/1373
        p1, p2 = self.spawn_children_pair()
        p1_ppid = p1.ppid()
        p2_ppid = p2.ppid()
        assert p1_ppid != p2_ppid
        with p1.oneshot():
            assert p1.ppid() == p1_ppid
            assert p2.ppid() == p2_ppid
        with p2.oneshot():
            assert p1.ppid() == p1_ppid
            assert p2.ppid() == p2_ppid

    def test_halfway_terminated_process(self):
        # Test that NoSuchProcess exception gets raised in case the
        # process dies after we create the Process object.
        # Example:
        # >>> proc = Process(1234)
        # >>> time.sleep(2)  # time-consuming task, process dies in meantime
        # >>> proc.name()
        # Refers to Issue #15
        def assert_raises_nsp(fun, fun_name):
            try:
                ret = fun()
            except psutil.ZombieProcess:  # differentiate from NSP
                raise
            except psutil.NoSuchProcess:
                pass
            except psutil.AccessDenied:
                if OPENBSD and fun_name in ('threads', 'num_threads'):
                    return
                raise
            else:
                # NtQuerySystemInformation succeeds even if process is gone.
                if WINDOWS and fun_name in ('exe', 'name'):
                    return
                raise self.fail(
                    "%r didn't raise NSP and returned %r instead" % (fun, ret)
                )

        p = self.spawn_psproc()
        p.terminate()
        p.wait()
        if WINDOWS:  # XXX
            call_until(lambda: p.pid not in psutil.pids())
        self.assertProcessGone(p)

        ns = process_namespace(p)
        for fun, name in ns.iter(ns.all):
            assert_raises_nsp(fun, name)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_zombie_process(self):
        _parent, zombie = self.spawn_zombie()
        self.assertProcessZombie(zombie)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_zombie_process_is_running_w_exc(self):
        # Emulate a case where internally is_running() raises
        # ZombieProcess.
        p = psutil.Process()
        with mock.patch(
            "psutil.Process", side_effect=psutil.ZombieProcess(0)
        ) as m:
            assert p.is_running()
            assert m.called

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_zombie_process_status_w_exc(self):
        # Emulate a case where internally status() raises
        # ZombieProcess.
        p = psutil.Process()
        with mock.patch(
            "psutil._psplatform.Process.status",
            side_effect=psutil.ZombieProcess(0),
        ) as m:
            assert p.status() == psutil.STATUS_ZOMBIE
            assert m.called

    def test_reused_pid(self):
        # Emulate a case where PID has been reused by another process.
        if PY3:
            from io import StringIO
        else:
            from StringIO import StringIO

        subp = self.spawn_testproc()
        p = psutil.Process(subp.pid)
        p._ident = (p.pid, p.create_time() + 100)

        list(psutil.process_iter())
        assert p.pid in psutil._pmap
        assert not p.is_running()

        # make sure is_running() removed PID from process_iter()
        # internal cache
        with mock.patch.object(psutil._common, "PSUTIL_DEBUG", True):
            with redirect_stderr(StringIO()) as f:
                list(psutil.process_iter())
        assert (
            "refreshing Process instance for reused PID %s" % p.pid
            in f.getvalue()
        )
        assert p.pid not in psutil._pmap

        assert p != psutil.Process(subp.pid)
        msg = "process no longer exists and its PID has been reused"
        ns = process_namespace(p)
        for fun, name in ns.iter(ns.setters + ns.killers, clear_cache=False):
            with self.subTest(name=name):
                with pytest.raises(psutil.NoSuchProcess, match=msg):
                    fun()

        assert "terminated + PID reused" in str(p)
        assert "terminated + PID reused" in repr(p)

        with pytest.raises(psutil.NoSuchProcess, match=msg):
            p.ppid()
        with pytest.raises(psutil.NoSuchProcess, match=msg):
            p.parent()
        with pytest.raises(psutil.NoSuchProcess, match=msg):
            p.parents()
        with pytest.raises(psutil.NoSuchProcess, match=msg):
            p.children()

    def test_pid_0(self):
        # Process(0) is supposed to work on all platforms except Linux
        if 0 not in psutil.pids():
            with pytest.raises(psutil.NoSuchProcess):
                psutil.Process(0)
            # These 2 are a contradiction, but "ps" says PID 1's parent
            # is PID 0.
            assert not psutil.pid_exists(0)
            assert psutil.Process(1).ppid() == 0
            return

        p = psutil.Process(0)
        exc = psutil.AccessDenied if WINDOWS else ValueError
        with pytest.raises(exc):
            p.wait()
        with pytest.raises(exc):
            p.terminate()
        with pytest.raises(exc):
            p.suspend()
        with pytest.raises(exc):
            p.resume()
        with pytest.raises(exc):
            p.kill()
        with pytest.raises(exc):
            p.send_signal(signal.SIGTERM)

        # test all methods
        ns = process_namespace(p)
        for fun, name in ns.iter(ns.getters + ns.setters):
            try:
                ret = fun()
            except psutil.AccessDenied:
                pass
            else:
                if name in ("uids", "gids"):
                    assert ret.real == 0
                elif name == "username":
                    user = 'NT AUTHORITY\\SYSTEM' if WINDOWS else 'root'
                    assert p.username() == user
                elif name == "name":
                    assert name, name

        if not OPENBSD:
            assert 0 in psutil.pids()
            assert psutil.pid_exists(0)

    @pytest.mark.skipif(not HAS_ENVIRON, reason="not supported")
    def test_environ(self):
        def clean_dict(d):
            exclude = ["PLAT", "HOME", "PYTEST_CURRENT_TEST", "PYTEST_VERSION"]
            if MACOS:
                exclude.extend([
                    "__CF_USER_TEXT_ENCODING",
                    "VERSIONER_PYTHON_PREFER_32_BIT",
                    "VERSIONER_PYTHON_VERSION",
                    "VERSIONER_PYTHON_VERSION",
                ])
            for name in exclude:
                d.pop(name, None)
            return dict([
                (
                    k.replace("\r", "").replace("\n", ""),
                    v.replace("\r", "").replace("\n", ""),
                )
                for k, v in d.items()
            ])

        self.maxDiff = None
        p = psutil.Process()
        d1 = clean_dict(p.environ())
        d2 = clean_dict(os.environ.copy())
        if not OSX and GITHUB_ACTIONS:
            assert d1 == d2

    @pytest.mark.skipif(not HAS_ENVIRON, reason="not supported")
    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @pytest.mark.skipif(
        MACOS_11PLUS,
        reason="macOS 11+ can't get another process environment, issue #2084",
    )
    @pytest.mark.skipif(
        NETBSD, reason="sometimes fails on `assert is_running()`"
    )
    def test_weird_environ(self):
        # environment variables can contain values without an equals sign
        code = textwrap.dedent("""
            #include <unistd.h>
            #include <fcntl.h>

            char * const argv[] = {"cat", 0};
            char * const envp[] = {"A=1", "X", "C=3", 0};

            int main(void) {
                // Close stderr on exec so parent can wait for the
                // execve to finish.
                if (fcntl(2, F_SETFD, FD_CLOEXEC) != 0)
                    return 0;
                return execve("/bin/cat", argv, envp);
            }
            """)
        cexe = create_c_exe(self.get_testfn(), c_code=code)
        sproc = self.spawn_testproc(
            [cexe], stdin=subprocess.PIPE, stderr=subprocess.PIPE
        )
        p = psutil.Process(sproc.pid)
        wait_for_pid(p.pid)
        assert p.is_running()
        # Wait for process to exec or exit.
        assert sproc.stderr.read() == b""
        if MACOS and CI_TESTING:
            try:
                env = p.environ()
            except psutil.AccessDenied:
                # XXX: fails sometimes with:
                # PermissionError from 'sysctl(KERN_PROCARGS2) -> EIO'
                return
        else:
            env = p.environ()
        assert env == {"A": "1", "C": "3"}
        sproc.communicate()
        assert sproc.returncode == 0


# ===================================================================
# --- Limited user tests
# ===================================================================


if POSIX and os.getuid() == 0:

    class LimitedUserTestCase(TestProcess):
        """Repeat the previous tests by using a limited user.
        Executed only on UNIX and only if the user who run the test script
        is root.
        """

        # the uid/gid the test suite runs under
        if hasattr(os, 'getuid'):
            PROCESS_UID = os.getuid()
            PROCESS_GID = os.getgid()

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # re-define all existent test methods in order to
            # ignore AccessDenied exceptions
            for attr in [x for x in dir(self) if x.startswith('test')]:
                meth = getattr(self, attr)

                def test_(self):
                    try:
                        meth()  # noqa
                    except psutil.AccessDenied:
                        pass

                setattr(self, attr, types.MethodType(test_, self))

        def setUp(self):
            super().setUp()
            os.setegid(1000)
            os.seteuid(1000)

        def tearDown(self):
            os.setegid(self.PROCESS_UID)
            os.seteuid(self.PROCESS_GID)
            super().tearDown()

        def test_nice(self):
            try:
                psutil.Process().nice(-1)
            except psutil.AccessDenied:
                pass
            else:
                raise self.fail("exception not raised")

        @pytest.mark.skipif(True, reason="causes problem as root")
        def test_zombie_process(self):
            pass


# ===================================================================
# --- psutil.Popen tests
# ===================================================================


class TestPopen(PsutilTestCase):
    """Tests for psutil.Popen class."""

    @classmethod
    def tearDownClass(cls):
        reap_children()

    def test_misc(self):
        # XXX this test causes a ResourceWarning on Python 3 because
        # psutil.__subproc instance doesn't get properly freed.
        # Not sure what to do though.
        cmd = [
            PYTHON_EXE,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)];",
        ]
        with psutil.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=PYTHON_EXE_ENV,
        ) as proc:
            proc.name()
            proc.cpu_times()
            proc.stdin  # noqa
            assert dir(proc)
            with pytest.raises(AttributeError):
                proc.foo  # noqa
            proc.terminate()
        if POSIX:
            assert proc.wait(5) == -signal.SIGTERM
        else:
            assert proc.wait(5) == signal.SIGTERM

    def test_ctx_manager(self):
        with psutil.Popen(
            [PYTHON_EXE, "-V"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            stdin=subprocess.PIPE,
            env=PYTHON_EXE_ENV,
        ) as proc:
            proc.communicate()
        assert proc.stdout.closed
        assert proc.stderr.closed
        assert proc.stdin.closed
        assert proc.returncode == 0

    def test_kill_terminate(self):
        # subprocess.Popen()'s terminate(), kill() and send_signal() do
        # not raise exception after the process is gone. psutil.Popen
        # diverges from that.
        cmd = [
            PYTHON_EXE,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)];",
        ]
        with psutil.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=PYTHON_EXE_ENV,
        ) as proc:
            proc.terminate()
            proc.wait()
            with pytest.raises(psutil.NoSuchProcess):
                proc.terminate()
            with pytest.raises(psutil.NoSuchProcess):
                proc.kill()
            with pytest.raises(psutil.NoSuchProcess):
                proc.send_signal(signal.SIGTERM)
            if WINDOWS:
                with pytest.raises(psutil.NoSuchProcess):
                    proc.send_signal(signal.CTRL_C_EVENT)
                with pytest.raises(psutil.NoSuchProcess):
                    proc.send_signal(signal.CTRL_BREAK_EVENT)
PKok\���O�O�psutil/tests/test_system.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for system APIS."""

import contextlib
import datetime
import errno
import os
import platform
import pprint
import shutil
import signal
import socket
import sys
import time

import psutil
from psutil import AIX
from psutil import BSD
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import PY3
from psutil._compat import FileNotFoundError
from psutil._compat import long
from psutil.tests import ASCII_FS
from psutil.tests import CI_TESTING
from psutil.tests import DEVNULL
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import GLOBAL_TIMEOUT
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_GETLOADAVG
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import IS_64BIT
from psutil.tests import MACOS_12PLUS
from psutil.tests import PYPY
from psutil.tests import QEMU_USER
from psutil.tests import UNICODE_SUFFIX
from psutil.tests import PsutilTestCase
from psutil.tests import check_net_address
from psutil.tests import enum
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import retry_on_failure


# ===================================================================
# --- System-related API tests
# ===================================================================


class TestProcessIter(PsutilTestCase):
    def test_pid_presence(self):
        assert os.getpid() in [x.pid for x in psutil.process_iter()]
        sproc = self.spawn_testproc()
        assert sproc.pid in [x.pid for x in psutil.process_iter()]
        p = psutil.Process(sproc.pid)
        p.kill()
        p.wait()
        assert sproc.pid not in [x.pid for x in psutil.process_iter()]

    def test_no_duplicates(self):
        ls = [x for x in psutil.process_iter()]
        assert sorted(ls, key=lambda x: x.pid) == sorted(
            set(ls), key=lambda x: x.pid
        )

    def test_emulate_nsp(self):
        list(psutil.process_iter())  # populate cache
        for x in range(2):
            with mock.patch(
                'psutil.Process.as_dict',
                side_effect=psutil.NoSuchProcess(os.getpid()),
            ):
                assert list(psutil.process_iter(attrs=["cpu_times"])) == []
            psutil.process_iter.cache_clear()  # repeat test without cache

    def test_emulate_access_denied(self):
        list(psutil.process_iter())  # populate cache
        for x in range(2):
            with mock.patch(
                'psutil.Process.as_dict',
                side_effect=psutil.AccessDenied(os.getpid()),
            ):
                with pytest.raises(psutil.AccessDenied):
                    list(psutil.process_iter(attrs=["cpu_times"]))
            psutil.process_iter.cache_clear()  # repeat test without cache

    def test_attrs(self):
        for p in psutil.process_iter(attrs=['pid']):
            assert list(p.info.keys()) == ['pid']
        # yield again
        for p in psutil.process_iter(attrs=['pid']):
            assert list(p.info.keys()) == ['pid']
        with pytest.raises(ValueError):
            list(psutil.process_iter(attrs=['foo']))
        with mock.patch(
            "psutil._psplatform.Process.cpu_times",
            side_effect=psutil.AccessDenied(0, ""),
        ) as m:
            for p in psutil.process_iter(attrs=["pid", "cpu_times"]):
                assert p.info['cpu_times'] is None
                assert p.info['pid'] >= 0
            assert m.called
        with mock.patch(
            "psutil._psplatform.Process.cpu_times",
            side_effect=psutil.AccessDenied(0, ""),
        ) as m:
            flag = object()
            for p in psutil.process_iter(
                attrs=["pid", "cpu_times"], ad_value=flag
            ):
                assert p.info['cpu_times'] is flag
                assert p.info['pid'] >= 0
            assert m.called

    def test_cache_clear(self):
        list(psutil.process_iter())  # populate cache
        assert psutil._pmap
        psutil.process_iter.cache_clear()
        assert not psutil._pmap


class TestProcessAPIs(PsutilTestCase):
    @pytest.mark.skipif(
        PYPY and WINDOWS,
        reason="spawn_testproc() unreliable on PYPY + WINDOWS",
    )
    def test_wait_procs(self):
        def callback(p):
            pids.append(p.pid)

        pids = []
        sproc1 = self.spawn_testproc()
        sproc2 = self.spawn_testproc()
        sproc3 = self.spawn_testproc()
        procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
        with pytest.raises(ValueError):
            psutil.wait_procs(procs, timeout=-1)
        with pytest.raises(TypeError):
            psutil.wait_procs(procs, callback=1)
        t = time.time()
        gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback)

        assert time.time() - t < 0.5
        assert gone == []
        assert len(alive) == 3
        assert pids == []
        for p in alive:
            assert not hasattr(p, 'returncode')

        @retry_on_failure(30)
        def test_1(procs, callback):
            gone, alive = psutil.wait_procs(
                procs, timeout=0.03, callback=callback
            )
            assert len(gone) == 1
            assert len(alive) == 2
            return gone, alive

        sproc3.terminate()
        gone, alive = test_1(procs, callback)
        assert sproc3.pid in [x.pid for x in gone]
        if POSIX:
            assert gone.pop().returncode == -signal.SIGTERM
        else:
            assert gone.pop().returncode == 1
        assert pids == [sproc3.pid]
        for p in alive:
            assert not hasattr(p, 'returncode')

        @retry_on_failure(30)
        def test_2(procs, callback):
            gone, alive = psutil.wait_procs(
                procs, timeout=0.03, callback=callback
            )
            assert len(gone) == 3
            assert len(alive) == 0
            return gone, alive

        sproc1.terminate()
        sproc2.terminate()
        gone, alive = test_2(procs, callback)
        assert set(pids) == set([sproc1.pid, sproc2.pid, sproc3.pid])
        for p in gone:
            assert hasattr(p, 'returncode')

    @pytest.mark.skipif(
        PYPY and WINDOWS,
        reason="spawn_testproc() unreliable on PYPY + WINDOWS",
    )
    def test_wait_procs_no_timeout(self):
        sproc1 = self.spawn_testproc()
        sproc2 = self.spawn_testproc()
        sproc3 = self.spawn_testproc()
        procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)]
        for p in procs:
            p.terminate()
        psutil.wait_procs(procs)

    def test_pid_exists(self):
        sproc = self.spawn_testproc()
        assert psutil.pid_exists(sproc.pid)
        p = psutil.Process(sproc.pid)
        p.kill()
        p.wait()
        assert not psutil.pid_exists(sproc.pid)
        assert not psutil.pid_exists(-1)
        assert psutil.pid_exists(0) == (0 in psutil.pids())

    def test_pid_exists_2(self):
        pids = psutil.pids()
        for pid in pids:
            try:
                assert psutil.pid_exists(pid)
            except AssertionError:
                # in case the process disappeared in meantime fail only
                # if it is no longer in psutil.pids()
                time.sleep(0.1)
                assert pid not in psutil.pids()
        pids = range(max(pids) + 15000, max(pids) + 16000)
        for pid in pids:
            assert not psutil.pid_exists(pid)


class TestMiscAPIs(PsutilTestCase):
    def test_boot_time(self):
        bt = psutil.boot_time()
        assert isinstance(bt, float)
        assert bt > 0
        assert bt < time.time()

    @pytest.mark.skipif(
        CI_TESTING and not psutil.users(), reason="unreliable on CI"
    )
    def test_users(self):
        users = psutil.users()
        assert users != []
        for user in users:
            with self.subTest(user=user):
                assert user.name
                assert isinstance(user.name, str)
                assert isinstance(user.terminal, (str, type(None)))
                if user.host is not None:
                    assert isinstance(user.host, (str, type(None)))
                user.terminal  # noqa
                user.host  # noqa
                assert user.started > 0.0
                datetime.datetime.fromtimestamp(user.started)
                if WINDOWS or OPENBSD:
                    assert user.pid is None
                else:
                    psutil.Process(user.pid)

    def test_test(self):
        # test for psutil.test() function
        stdout = sys.stdout
        sys.stdout = DEVNULL
        try:
            psutil.test()
        finally:
            sys.stdout = stdout

    def test_os_constants(self):
        names = [
            "POSIX",
            "WINDOWS",
            "LINUX",
            "MACOS",
            "FREEBSD",
            "OPENBSD",
            "NETBSD",
            "BSD",
            "SUNOS",
        ]
        for name in names:
            assert isinstance(getattr(psutil, name), bool), name

        if os.name == 'posix':
            assert psutil.POSIX
            assert not psutil.WINDOWS
            names.remove("POSIX")
            if "linux" in sys.platform.lower():
                assert psutil.LINUX
                names.remove("LINUX")
            elif "bsd" in sys.platform.lower():
                assert psutil.BSD
                assert [psutil.FREEBSD, psutil.OPENBSD, psutil.NETBSD].count(
                    True
                ) == 1
                names.remove("BSD")
                names.remove("FREEBSD")
                names.remove("OPENBSD")
                names.remove("NETBSD")
            elif (
                "sunos" in sys.platform.lower()
                or "solaris" in sys.platform.lower()
            ):
                assert psutil.SUNOS
                names.remove("SUNOS")
            elif "darwin" in sys.platform.lower():
                assert psutil.MACOS
                names.remove("MACOS")
        else:
            assert psutil.WINDOWS
            assert not psutil.POSIX
            names.remove("WINDOWS")

        # assert all other constants are set to False
        for name in names:
            assert not getattr(psutil, name), name


class TestMemoryAPIs(PsutilTestCase):
    def test_virtual_memory(self):
        mem = psutil.virtual_memory()
        assert mem.total > 0, mem
        assert mem.available > 0, mem
        assert 0 <= mem.percent <= 100, mem
        assert mem.used > 0, mem
        assert mem.free >= 0, mem
        for name in mem._fields:
            value = getattr(mem, name)
            if name != 'percent':
                assert isinstance(value, (int, long))
            if name != 'total':
                if not value >= 0:
                    raise self.fail("%r < 0 (%s)" % (name, value))
                if value > mem.total:
                    raise self.fail(
                        "%r > total (total=%s, %s=%s)"
                        % (name, mem.total, name, value)
                    )

    def test_swap_memory(self):
        mem = psutil.swap_memory()
        assert mem._fields == (
            'total',
            'used',
            'free',
            'percent',
            'sin',
            'sout',
        )

        assert mem.total >= 0, mem
        assert mem.used >= 0, mem
        if mem.total > 0:
            # likely a system with no swap partition
            assert mem.free > 0, mem
        else:
            assert mem.free == 0, mem
        assert 0 <= mem.percent <= 100, mem
        assert mem.sin >= 0, mem
        assert mem.sout >= 0, mem


class TestCpuAPIs(PsutilTestCase):
    def test_cpu_count_logical(self):
        logical = psutil.cpu_count()
        assert logical is not None
        assert logical == len(psutil.cpu_times(percpu=True))
        assert logical >= 1

        if os.path.exists("/proc/cpuinfo"):
            with open("/proc/cpuinfo") as fd:
                cpuinfo_data = fd.read()
            if "physical id" not in cpuinfo_data:
                raise pytest.skip("cpuinfo doesn't include physical id")

    def test_cpu_count_cores(self):
        logical = psutil.cpu_count()
        cores = psutil.cpu_count(logical=False)
        if cores is None:
            raise pytest.skip("cpu_count_cores() is None")
        if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1):  # <= Vista
            assert cores is None
        else:
            assert cores >= 1
            assert logical >= cores

    def test_cpu_count_none(self):
        # https://github.com/giampaolo/psutil/issues/1085
        for val in (-1, 0, None):
            with mock.patch(
                'psutil._psplatform.cpu_count_logical', return_value=val
            ) as m:
                assert psutil.cpu_count() is None
                assert m.called
            with mock.patch(
                'psutil._psplatform.cpu_count_cores', return_value=val
            ) as m:
                assert psutil.cpu_count(logical=False) is None
                assert m.called

    def test_cpu_times(self):
        # Check type, value >= 0, str().
        total = 0
        times = psutil.cpu_times()
        sum(times)
        for cp_time in times:
            assert isinstance(cp_time, float)
            assert cp_time >= 0.0
            total += cp_time
        assert round(abs(total - sum(times)), 6) == 0
        str(times)
        # CPU times are always supposed to increase over time
        # or at least remain the same and that's because time
        # cannot go backwards.
        # Surprisingly sometimes this might not be the case (at
        # least on Windows and Linux), see:
        # https://github.com/giampaolo/psutil/issues/392
        # https://github.com/giampaolo/psutil/issues/645
        # if not WINDOWS:
        #     last = psutil.cpu_times()
        #     for x in range(100):
        #         new = psutil.cpu_times()
        #         for field in new._fields:
        #             new_t = getattr(new, field)
        #             last_t = getattr(last, field)
        #             self.assertGreaterEqual(new_t, last_t,
        #                                     msg="%s %s" % (new_t, last_t))
        #         last = new

    def test_cpu_times_time_increases(self):
        # Make sure time increases between calls.
        t1 = sum(psutil.cpu_times())
        stop_at = time.time() + GLOBAL_TIMEOUT
        while time.time() < stop_at:
            t2 = sum(psutil.cpu_times())
            if t2 > t1:
                return
        raise self.fail("time remained the same")

    def test_per_cpu_times(self):
        # Check type, value >= 0, str().
        for times in psutil.cpu_times(percpu=True):
            total = 0
            sum(times)
            for cp_time in times:
                assert isinstance(cp_time, float)
                assert cp_time >= 0.0
                total += cp_time
            assert round(abs(total - sum(times)), 6) == 0
            str(times)
        assert len(psutil.cpu_times(percpu=True)[0]) == len(
            psutil.cpu_times(percpu=False)
        )

        # Note: in theory CPU times are always supposed to increase over
        # time or remain the same but never go backwards. In practice
        # sometimes this is not the case.
        # This issue seemd to be afflict Windows:
        # https://github.com/giampaolo/psutil/issues/392
        # ...but it turns out also Linux (rarely) behaves the same.
        # last = psutil.cpu_times(percpu=True)
        # for x in range(100):
        #     new = psutil.cpu_times(percpu=True)
        #     for index in range(len(new)):
        #         newcpu = new[index]
        #         lastcpu = last[index]
        #         for field in newcpu._fields:
        #             new_t = getattr(newcpu, field)
        #             last_t = getattr(lastcpu, field)
        #             self.assertGreaterEqual(
        #                 new_t, last_t, msg="%s %s" % (lastcpu, newcpu))
        #     last = new

    def test_per_cpu_times_2(self):
        # Simulate some work load then make sure time have increased
        # between calls.
        tot1 = psutil.cpu_times(percpu=True)
        giveup_at = time.time() + GLOBAL_TIMEOUT
        while True:
            if time.time() >= giveup_at:
                return self.fail("timeout")
            tot2 = psutil.cpu_times(percpu=True)
            for t1, t2 in zip(tot1, tot2):
                t1, t2 = psutil._cpu_busy_time(t1), psutil._cpu_busy_time(t2)
                difference = t2 - t1
                if difference >= 0.05:
                    return

    @pytest.mark.skipif(
        CI_TESTING and OPENBSD, reason="unreliable on OPENBSD + CI"
    )
    def test_cpu_times_comparison(self):
        # Make sure the sum of all per cpu times is almost equal to
        # base "one cpu" times. On OpenBSD the sum of per-CPUs is
        # higher for some reason.
        base = psutil.cpu_times()
        per_cpu = psutil.cpu_times(percpu=True)
        summed_values = base._make([sum(num) for num in zip(*per_cpu)])
        for field in base._fields:
            with self.subTest(field=field, base=base, per_cpu=per_cpu):
                assert (
                    abs(getattr(base, field) - getattr(summed_values, field))
                    < 1
                )

    def _test_cpu_percent(self, percent, last_ret, new_ret):
        try:
            assert isinstance(percent, float)
            assert percent >= 0.0
            assert percent is not -0.0
            assert percent <= 100.0 * psutil.cpu_count()
        except AssertionError as err:
            raise AssertionError(
                "\n%s\nlast=%s\nnew=%s"
                % (err, pprint.pformat(last_ret), pprint.pformat(new_ret))
            )

    def test_cpu_percent(self):
        last = psutil.cpu_percent(interval=0.001)
        for _ in range(100):
            new = psutil.cpu_percent(interval=None)
            self._test_cpu_percent(new, last, new)
            last = new
        with pytest.raises(ValueError):
            psutil.cpu_percent(interval=-1)

    def test_per_cpu_percent(self):
        last = psutil.cpu_percent(interval=0.001, percpu=True)
        assert len(last) == psutil.cpu_count()
        for _ in range(100):
            new = psutil.cpu_percent(interval=None, percpu=True)
            for percent in new:
                self._test_cpu_percent(percent, last, new)
            last = new
        with pytest.raises(ValueError):
            psutil.cpu_percent(interval=-1, percpu=True)

    def test_cpu_times_percent(self):
        last = psutil.cpu_times_percent(interval=0.001)
        for _ in range(100):
            new = psutil.cpu_times_percent(interval=None)
            for percent in new:
                self._test_cpu_percent(percent, last, new)
            self._test_cpu_percent(sum(new), last, new)
            last = new
        with pytest.raises(ValueError):
            psutil.cpu_times_percent(interval=-1)

    def test_per_cpu_times_percent(self):
        last = psutil.cpu_times_percent(interval=0.001, percpu=True)
        assert len(last) == psutil.cpu_count()
        for _ in range(100):
            new = psutil.cpu_times_percent(interval=None, percpu=True)
            for cpu in new:
                for percent in cpu:
                    self._test_cpu_percent(percent, last, new)
                self._test_cpu_percent(sum(cpu), last, new)
            last = new

    def test_per_cpu_times_percent_negative(self):
        # see: https://github.com/giampaolo/psutil/issues/645
        psutil.cpu_times_percent(percpu=True)
        zero_times = [
            x._make([0 for x in range(len(x._fields))])
            for x in psutil.cpu_times(percpu=True)
        ]
        with mock.patch('psutil.cpu_times', return_value=zero_times):
            for cpu in psutil.cpu_times_percent(percpu=True):
                for percent in cpu:
                    self._test_cpu_percent(percent, None, None)

    def test_cpu_stats(self):
        # Tested more extensively in per-platform test modules.
        infos = psutil.cpu_stats()
        assert infos._fields == (
            'ctx_switches',
            'interrupts',
            'soft_interrupts',
            'syscalls',
        )
        for name in infos._fields:
            value = getattr(infos, name)
            assert value >= 0
            # on AIX, ctx_switches is always 0
            if not AIX and name in ('ctx_switches', 'interrupts'):
                assert value > 0

    # TODO: remove this once 1892 is fixed
    @pytest.mark.skipif(
        MACOS and platform.machine() == 'arm64', reason="skipped due to #1892"
    )
    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_cpu_freq(self):
        def check_ls(ls):
            for nt in ls:
                assert nt._fields == ('current', 'min', 'max')
                if nt.max != 0.0:
                    assert nt.current <= nt.max
                for name in nt._fields:
                    value = getattr(nt, name)
                    assert isinstance(value, (int, long, float))
                    assert value >= 0

        ls = psutil.cpu_freq(percpu=True)
        if FREEBSD and not ls:
            raise pytest.skip("returns empty list on FreeBSD")

        assert ls, ls
        check_ls([psutil.cpu_freq(percpu=False)])

        if LINUX:
            assert len(ls) == psutil.cpu_count()

    @pytest.mark.skipif(not HAS_GETLOADAVG, reason="not supported")
    def test_getloadavg(self):
        loadavg = psutil.getloadavg()
        assert len(loadavg) == 3
        for load in loadavg:
            assert isinstance(load, float)
            assert load >= 0.0


class TestDiskAPIs(PsutilTestCase):
    @pytest.mark.skipif(
        PYPY and not IS_64BIT, reason="unreliable on PYPY32 + 32BIT"
    )
    def test_disk_usage(self):
        usage = psutil.disk_usage(os.getcwd())
        assert usage._fields == ('total', 'used', 'free', 'percent')

        assert usage.total > 0, usage
        assert usage.used > 0, usage
        assert usage.free > 0, usage
        assert usage.total > usage.used, usage
        assert usage.total > usage.free, usage
        assert 0 <= usage.percent <= 100, usage.percent
        if hasattr(shutil, 'disk_usage'):
            # py >= 3.3, see: http://bugs.python.org/issue12442
            shutil_usage = shutil.disk_usage(os.getcwd())
            tolerance = 5 * 1024 * 1024  # 5MB
            assert usage.total == shutil_usage.total
            assert abs(usage.free - shutil_usage.free) < tolerance
            if not MACOS_12PLUS:
                # see https://github.com/giampaolo/psutil/issues/2147
                assert abs(usage.used - shutil_usage.used) < tolerance

        # if path does not exist OSError ENOENT is expected across
        # all platforms
        fname = self.get_testfn()
        with pytest.raises(FileNotFoundError):
            psutil.disk_usage(fname)

    @pytest.mark.skipif(not ASCII_FS, reason="not an ASCII fs")
    def test_disk_usage_unicode(self):
        # See: https://github.com/giampaolo/psutil/issues/416
        with pytest.raises(UnicodeEncodeError):
            psutil.disk_usage(UNICODE_SUFFIX)

    def test_disk_usage_bytes(self):
        psutil.disk_usage(b'.')

    def test_disk_partitions(self):
        def check_ntuple(nt):
            assert isinstance(nt.device, str)
            assert isinstance(nt.mountpoint, str)
            assert isinstance(nt.fstype, str)
            assert isinstance(nt.opts, str)

        # all = False
        ls = psutil.disk_partitions(all=False)
        assert ls
        for disk in ls:
            check_ntuple(disk)
            if WINDOWS and 'cdrom' in disk.opts:
                continue
            if not POSIX:
                assert os.path.exists(disk.device), disk
            else:
                # we cannot make any assumption about this, see:
                # http://goo.gl/p9c43
                disk.device  # noqa
            # on modern systems mount points can also be files
            assert os.path.exists(disk.mountpoint), disk
            assert disk.fstype, disk

        # all = True
        ls = psutil.disk_partitions(all=True)
        assert ls
        for disk in psutil.disk_partitions(all=True):
            check_ntuple(disk)
            if not WINDOWS and disk.mountpoint:
                try:
                    os.stat(disk.mountpoint)
                except OSError as err:
                    if GITHUB_ACTIONS and MACOS and err.errno == errno.EIO:
                        continue
                    # http://mail.python.org/pipermail/python-dev/
                    #     2012-June/120787.html
                    if err.errno not in (errno.EPERM, errno.EACCES):
                        raise
                else:
                    assert os.path.exists(disk.mountpoint), disk

        # ---

        def find_mount_point(path):
            path = os.path.abspath(path)
            while not os.path.ismount(path):
                path = os.path.dirname(path)
            return path.lower()

        mount = find_mount_point(__file__)
        mounts = [
            x.mountpoint.lower()
            for x in psutil.disk_partitions(all=True)
            if x.mountpoint
        ]
        assert mount in mounts

    @pytest.mark.skipif(
        LINUX and not os.path.exists('/proc/diskstats'),
        reason="/proc/diskstats not available on this linux version",
    )
    @pytest.mark.skipif(
        CI_TESTING and not psutil.disk_io_counters(), reason="unreliable on CI"
    )  # no visible disks
    def test_disk_io_counters(self):
        def check_ntuple(nt):
            assert nt[0] == nt.read_count
            assert nt[1] == nt.write_count
            assert nt[2] == nt.read_bytes
            assert nt[3] == nt.write_bytes
            if not (OPENBSD or NETBSD):
                assert nt[4] == nt.read_time
                assert nt[5] == nt.write_time
                if LINUX:
                    assert nt[6] == nt.read_merged_count
                    assert nt[7] == nt.write_merged_count
                    assert nt[8] == nt.busy_time
                elif FREEBSD:
                    assert nt[6] == nt.busy_time
            for name in nt._fields:
                assert getattr(nt, name) >= 0, nt

        ret = psutil.disk_io_counters(perdisk=False)
        assert ret is not None, "no disks on this system?"
        check_ntuple(ret)
        ret = psutil.disk_io_counters(perdisk=True)
        # make sure there are no duplicates
        assert len(ret) == len(set(ret))
        for key in ret:
            assert key, key
            check_ntuple(ret[key])

    def test_disk_io_counters_no_disks(self):
        # Emulate a case where no disks are installed, see:
        # https://github.com/giampaolo/psutil/issues/1062
        with mock.patch(
            'psutil._psplatform.disk_io_counters', return_value={}
        ) as m:
            assert psutil.disk_io_counters(perdisk=False) is None
            assert psutil.disk_io_counters(perdisk=True) == {}
            assert m.called


class TestNetAPIs(PsutilTestCase):
    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_net_io_counters(self):
        def check_ntuple(nt):
            assert nt[0] == nt.bytes_sent
            assert nt[1] == nt.bytes_recv
            assert nt[2] == nt.packets_sent
            assert nt[3] == nt.packets_recv
            assert nt[4] == nt.errin
            assert nt[5] == nt.errout
            assert nt[6] == nt.dropin
            assert nt[7] == nt.dropout
            assert nt.bytes_sent >= 0, nt
            assert nt.bytes_recv >= 0, nt
            assert nt.packets_sent >= 0, nt
            assert nt.packets_recv >= 0, nt
            assert nt.errin >= 0, nt
            assert nt.errout >= 0, nt
            assert nt.dropin >= 0, nt
            assert nt.dropout >= 0, nt

        ret = psutil.net_io_counters(pernic=False)
        check_ntuple(ret)
        ret = psutil.net_io_counters(pernic=True)
        assert ret != []
        for key in ret:
            assert key
            assert isinstance(key, str)
            check_ntuple(ret[key])

    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_net_io_counters_no_nics(self):
        # Emulate a case where no NICs are installed, see:
        # https://github.com/giampaolo/psutil/issues/1062
        with mock.patch(
            'psutil._psplatform.net_io_counters', return_value={}
        ) as m:
            assert psutil.net_io_counters(pernic=False) is None
            assert psutil.net_io_counters(pernic=True) == {}
            assert m.called

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_net_if_addrs(self):
        nics = psutil.net_if_addrs()
        assert nics, nics

        nic_stats = psutil.net_if_stats()

        # Not reliable on all platforms (net_if_addrs() reports more
        # interfaces).
        # self.assertEqual(sorted(nics.keys()),
        #                  sorted(psutil.net_io_counters(pernic=True).keys()))

        families = set([socket.AF_INET, socket.AF_INET6, psutil.AF_LINK])
        for nic, addrs in nics.items():
            assert isinstance(nic, str)
            assert len(set(addrs)) == len(addrs)
            for addr in addrs:
                assert isinstance(addr.family, int)
                assert isinstance(addr.address, str)
                assert isinstance(addr.netmask, (str, type(None)))
                assert isinstance(addr.broadcast, (str, type(None)))
                assert addr.family in families
                if PY3 and not PYPY:
                    assert isinstance(addr.family, enum.IntEnum)
                if nic_stats[nic].isup:
                    # Do not test binding to addresses of interfaces
                    # that are down
                    if addr.family == socket.AF_INET:
                        s = socket.socket(addr.family)
                        with contextlib.closing(s):
                            s.bind((addr.address, 0))
                    elif addr.family == socket.AF_INET6:
                        info = socket.getaddrinfo(
                            addr.address,
                            0,
                            socket.AF_INET6,
                            socket.SOCK_STREAM,
                            0,
                            socket.AI_PASSIVE,
                        )[0]
                        af, socktype, proto, _canonname, sa = info
                        s = socket.socket(af, socktype, proto)
                        with contextlib.closing(s):
                            s.bind(sa)
                for ip in (
                    addr.address,
                    addr.netmask,
                    addr.broadcast,
                    addr.ptp,
                ):
                    if ip is not None:
                        # TODO: skip AF_INET6 for now because I get:
                        # AddressValueError: Only hex digits permitted in
                        # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0'
                        if addr.family != socket.AF_INET6:
                            check_net_address(ip, addr.family)
                # broadcast and ptp addresses are mutually exclusive
                if addr.broadcast:
                    assert addr.ptp is None
                elif addr.ptp:
                    assert addr.broadcast is None

        if BSD or MACOS or SUNOS:
            if hasattr(socket, "AF_LINK"):
                assert psutil.AF_LINK == socket.AF_LINK
        elif LINUX:
            assert psutil.AF_LINK == socket.AF_PACKET
        elif WINDOWS:
            assert psutil.AF_LINK == -1

    def test_net_if_addrs_mac_null_bytes(self):
        # Simulate that the underlying C function returns an incomplete
        # MAC address. psutil is supposed to fill it with null bytes.
        # https://github.com/giampaolo/psutil/issues/786
        if POSIX:
            ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)]
        else:
            ret = [('em1', -1, '06-3d-29', None, None, None)]
        with mock.patch(
            'psutil._psplatform.net_if_addrs', return_value=ret
        ) as m:
            addr = psutil.net_if_addrs()['em1'][0]
            assert m.called
            if POSIX:
                assert addr.address == '06:3d:29:00:00:00'
            else:
                assert addr.address == '06-3d-29-00-00-00'

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_net_if_stats(self):
        nics = psutil.net_if_stats()
        assert nics, nics
        all_duplexes = (
            psutil.NIC_DUPLEX_FULL,
            psutil.NIC_DUPLEX_HALF,
            psutil.NIC_DUPLEX_UNKNOWN,
        )
        for name, stats in nics.items():
            assert isinstance(name, str)
            isup, duplex, speed, mtu, flags = stats
            assert isinstance(isup, bool)
            assert duplex in all_duplexes
            assert duplex in all_duplexes
            assert speed >= 0
            assert mtu >= 0
            assert isinstance(flags, str)

    @pytest.mark.skipif(
        not (LINUX or BSD or MACOS), reason="LINUX or BSD or MACOS specific"
    )
    def test_net_if_stats_enodev(self):
        # See: https://github.com/giampaolo/psutil/issues/1279
        with mock.patch(
            'psutil._psutil_posix.net_if_mtu',
            side_effect=OSError(errno.ENODEV, ""),
        ) as m:
            ret = psutil.net_if_stats()
            assert ret == {}
            assert m.called


class TestSensorsAPIs(PsutilTestCase):
    @pytest.mark.skipif(not HAS_SENSORS_TEMPERATURES, reason="not supported")
    def test_sensors_temperatures(self):
        temps = psutil.sensors_temperatures()
        for name, entries in temps.items():
            assert isinstance(name, str)
            for entry in entries:
                assert isinstance(entry.label, str)
                if entry.current is not None:
                    assert entry.current >= 0
                if entry.high is not None:
                    assert entry.high >= 0
                if entry.critical is not None:
                    assert entry.critical >= 0

    @pytest.mark.skipif(not HAS_SENSORS_TEMPERATURES, reason="not supported")
    def test_sensors_temperatures_fahreneit(self):
        d = {'coretemp': [('label', 50.0, 60.0, 70.0)]}
        with mock.patch(
            "psutil._psplatform.sensors_temperatures", return_value=d
        ) as m:
            temps = psutil.sensors_temperatures(fahrenheit=True)['coretemp'][0]
            assert m.called
            assert temps.current == 122.0
            assert temps.high == 140.0
            assert temps.critical == 158.0

    @pytest.mark.skipif(not HAS_SENSORS_BATTERY, reason="not supported")
    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_sensors_battery(self):
        ret = psutil.sensors_battery()
        assert ret.percent >= 0
        assert ret.percent <= 100
        if ret.secsleft not in (
            psutil.POWER_TIME_UNKNOWN,
            psutil.POWER_TIME_UNLIMITED,
        ):
            assert ret.secsleft >= 0
        else:
            if ret.secsleft == psutil.POWER_TIME_UNLIMITED:
                assert ret.power_plugged
        assert isinstance(ret.power_plugged, bool)

    @pytest.mark.skipif(not HAS_SENSORS_FANS, reason="not supported")
    def test_sensors_fans(self):
        fans = psutil.sensors_fans()
        for name, entries in fans.items():
            assert isinstance(name, str)
            for entry in entries:
                assert isinstance(entry.label, str)
                assert isinstance(entry.current, (int, long))
                assert entry.current >= 0
PKok\3�
��psutil/tests/test_osx.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""macOS specific tests."""

import platform
import re
import time

import psutil
from psutil import MACOS
from psutil import POSIX
from psutil.tests import HAS_BATTERY
from psutil.tests import TOLERANCE_DISK_USAGE
from psutil.tests import TOLERANCE_SYS_MEM
from psutil.tests import PsutilTestCase
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import spawn_testproc
from psutil.tests import terminate


if POSIX:
    from psutil._psutil_posix import getpagesize


def sysctl(cmdline):
    """Expects a sysctl command with an argument and parse the result
    returning only the value of interest.
    """
    out = sh(cmdline)
    result = out.split()[1]
    try:
        return int(result)
    except ValueError:
        return result


def vm_stat(field):
    """Wrapper around 'vm_stat' cmdline utility."""
    out = sh('vm_stat')
    for line in out.split('\n'):
        if field in line:
            break
    else:
        raise ValueError("line not found")
    return int(re.search(r'\d+', line).group(0)) * getpagesize()


@pytest.mark.skipif(not MACOS, reason="MACOS only")
class TestProcess(PsutilTestCase):
    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    def test_process_create_time(self):
        output = sh("ps -o lstart -p %s" % self.pid)
        start_ps = output.replace('STARTED', '').strip()
        hhmmss = start_ps.split(' ')[-2]
        year = start_ps.split(' ')[-1]
        start_psutil = psutil.Process(self.pid).create_time()
        assert hhmmss == time.strftime(
            "%H:%M:%S", time.localtime(start_psutil)
        )
        assert year == time.strftime("%Y", time.localtime(start_psutil))


@pytest.mark.skipif(not MACOS, reason="MACOS only")
class TestSystemAPIs(PsutilTestCase):

    # --- disk

    @retry_on_failure()
    def test_disks(self):
        # test psutil.disk_usage() and psutil.disk_partitions()
        # against "df -a"
        def df(path):
            out = sh('df -k "%s"' % path).strip()
            lines = out.split('\n')
            lines.pop(0)
            line = lines.pop(0)
            dev, total, used, free = line.split()[:4]
            if dev == 'none':
                dev = ''
            total = int(total) * 1024
            used = int(used) * 1024
            free = int(free) * 1024
            return dev, total, used, free

        for part in psutil.disk_partitions(all=False):
            usage = psutil.disk_usage(part.mountpoint)
            dev, total, used, free = df(part.mountpoint)
            assert part.device == dev
            assert usage.total == total
            assert abs(usage.free - free) < TOLERANCE_DISK_USAGE
            assert abs(usage.used - used) < TOLERANCE_DISK_USAGE

    # --- cpu

    def test_cpu_count_logical(self):
        num = sysctl("sysctl hw.logicalcpu")
        assert num == psutil.cpu_count(logical=True)

    def test_cpu_count_cores(self):
        num = sysctl("sysctl hw.physicalcpu")
        assert num == psutil.cpu_count(logical=False)

    # TODO: remove this once 1892 is fixed
    @pytest.mark.skipif(
        MACOS and platform.machine() == 'arm64', reason="skipped due to #1892"
    )
    def test_cpu_freq(self):
        freq = psutil.cpu_freq()
        assert freq.current * 1000 * 1000 == sysctl("sysctl hw.cpufrequency")
        assert freq.min * 1000 * 1000 == sysctl("sysctl hw.cpufrequency_min")
        assert freq.max * 1000 * 1000 == sysctl("sysctl hw.cpufrequency_max")

    # --- virtual mem

    def test_vmem_total(self):
        sysctl_hwphymem = sysctl('sysctl hw.memsize')
        assert sysctl_hwphymem == psutil.virtual_memory().total

    @retry_on_failure()
    def test_vmem_free(self):
        vmstat_val = vm_stat("free")
        psutil_val = psutil.virtual_memory().free
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_active(self):
        vmstat_val = vm_stat("active")
        psutil_val = psutil.virtual_memory().active
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_inactive(self):
        vmstat_val = vm_stat("inactive")
        psutil_val = psutil.virtual_memory().inactive
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_vmem_wired(self):
        vmstat_val = vm_stat("wired")
        psutil_val = psutil.virtual_memory().wired
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    # --- swap mem

    @retry_on_failure()
    def test_swapmem_sin(self):
        vmstat_val = vm_stat("Pageins")
        psutil_val = psutil.swap_memory().sin
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_swapmem_sout(self):
        vmstat_val = vm_stat("Pageout")
        psutil_val = psutil.swap_memory().sout
        assert abs(psutil_val - vmstat_val) < TOLERANCE_SYS_MEM

    # --- network

    def test_net_if_stats(self):
        for name, stats in psutil.net_if_stats().items():
            try:
                out = sh("ifconfig %s" % name)
            except RuntimeError:
                pass
            else:
                assert stats.isup == ('RUNNING' in out), out
                assert stats.mtu == int(re.findall(r'mtu (\d+)', out)[0])

    # --- sensors_battery

    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_sensors_battery(self):
        out = sh("pmset -g batt")
        percent = re.search(r"(\d+)%", out).group(1)
        drawing_from = re.search("Now drawing from '([^']+)'", out).group(1)
        power_plugged = drawing_from == "AC Power"
        psutil_result = psutil.sensors_battery()
        assert psutil_result.power_plugged == power_plugged
        assert psutil_result.percent == int(percent)
PKok\
�u55psutil/tests/__main__.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Run unit tests. This is invoked by:
$ python -m psutil.tests.
"""

from psutil.tests import pytest


pytest.main(["-v", "-s", "--tb=short"])
PKok\��k��0psutil/tests/__pycache__/test_aix.cpython-39.pycnu�[���a

��?h��@sjdZddlZddlZddlmZddlmZddlmZddlmZejj	edd�Gd	d
�d
e��Z
dS)zAIX specific tests.�N)�AIX)�PsutilTestCase)�pytest)�shzAIX only)�reasonc@s4eZdZdd�Zdd�Zdd�Zdd�Zd	d
�ZdS)�AIXSpecificTestCasecCs�td�}d}d��D]}|d|f7}qt�||�}|dus@J�d}t|�d��|}t|�d��|}t|�d��|}t|�d	��|}	t��}
d
||}|
j|ks�J�t	|
j
|�|ks�J�t	|
j|�|ks�J�t	|
j|	�|ks�J�dS)Nz/usr/bin/svmon -O unit=KBz	memory\s*z+size inuse free pin virtual available mmode�(?P<%s>\S+)\s+i�size�	availableZinuse�free�)
r�split�re�search�int�group�psutilZvirtual_memory�total�abs�usedr
r)�self�out�
re_pattern�field�matchobjZKBrr
rr�
psutil_resultZTOLERANCE_SYS_MEM�r�A/usr/local/lib64/python3.9/site-packages/psutil/tests/test_aix.py�test_virtual_memorys"z'AIXSpecificTestCase.test_virtual_memorycCsTtd�}t�d|�}|dus J�t|�d��}d}t��}t|j|�|ksPJ�dS)Nz/usr/sbin/lsps -az=(?P<space>\S+)\s+(?P<vol>\S+)\s+(?P<vg>\S+)\s+(?P<size>\d+)MBr	i)rrrrrrZswap_memoryr)rrrZtotal_mbZMBrrrr�test_swap_memory0s�z$AIXSpecificTestCase.test_swap_memorycCs�td�}d}d��D]}|d|f7}qt�||�}|dus@J�d}t��}t|jt|�	d���|kslJ�t|j
t|�	d���|ks�J�t|jt|�	d���|ks�J�t|jt|�	d	���|ks�J�dS)
N�/usr/bin/mpstat -azALL\s*zfmin maj mpcs mpcr dev soft dec ph cs ics bound rq push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd syscri��csZsysc�devZsoft)
rr
rrrZ	cpu_statsrZctx_switchesrrZsyscallsZ
interruptsZsoft_interrupts)rrrrrZCPU_STATS_TOLERANCErrrr�test_cpu_statsGs2�
��������z"AIXSpecificTestCase.test_cpu_statscCs:td�}tt�d|��d��}tjdd�}||ks6J�dS)Nr z
lcpu=(\d+)�T)�logical)rrrrrr�	cpu_count)rrZmpstat_lcpuZpsutil_lcpurrr�test_cpu_count_logicalisz*AIXSpecificTestCase.test_cpu_count_logicalcCs4td�}t|���}tt�����}||ks0J�dS)Nz/etc/ifconfig -l)r�setr
rZnet_if_addrs�keys)rrZifconfig_namesZpsutil_namesrrr�test_net_if_addrs_namesosz+AIXSpecificTestCase.test_net_if_addrs_namesN)�__name__�
__module__�__qualname__rrr#r'r*rrrrrs
"r)�__doc__rrrZpsutil.testsrrr�markZskipifrrrrr�<module>	sPKok\�*ejXjX6psutil/tests/__pycache__/test_testutils.cpython-39.pycnu�[���a

��?h�H�@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlm
Z
ddlmZddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*ddlm+Z+dd lm,Z,dd!lm-Z-dd"lm.Z.dd#lm/Z/dd$lm0Z0dd%lm1Z1dd&lm2Z2dd'lm3Z3dd(lm4Z4Gd)d*�d*e�Z5Gd+d,�d,e�Z6Gd-d.�d.e�Z7Gd/d0�d0e�Z8Gd1d2�d2e�Z9e)j:j;d3d4�Gd5d6�d6e��Z<Gd7d8�d8e�Z=Gd9d:�d:e�Z>Gd;d<�d<e�Z?dS)=z1Tests for testing utils (psutil.tests namespace).�N)�FREEBSD)�NETBSD)�POSIX)�open_binary)�	open_text)�
supports_ipv6)�PY3)�
CI_TESTING)�COVERAGE)�HAS_NET_CONNECTIONS_UNIX)�HERE)�
PYTHON_EXE)�PYTHON_EXE_ENV)�PsutilTestCase)�TestMemoryLeak)�bind_socket)�bind_unix_socket��
call_until)�chdir)�create_sockets)�fake_pytest)�filter_proc_net_connections)�
get_free_port)�
is_namedtuple)�mock)�process_namespace)�pytest)�
reap_children)�retry)�retry_on_failure)�
safe_mkdir)�safe_rmpath)�system_namespace)�tcp_socketpair)�	terminate)�unix_socketpair)�
wait_for_file)�wait_for_pidc@sxeZdZe�d�dd��Ze�d�dd��Ze�d�dd��Ze�d�dd	��Ze�d�d
d��Z	e�d�dd
��Z
dS)�TestRetryDecoratorz
time.sleepcsFtdddd��fdd��}ttd���|�dks4J�|jdksBJ�dS)N����retries�intervalZlogfuncs�r���ddqdS�Nr+r��pop���queuer2�G/usr/local/lib64/python3.9/site-packages/psutil/tests/test_testutils.py�fooIs
z2TestRetryDecorator.test_retry_success.<locals>.foo�)r�list�range�
call_count��self�sleepr6r2r3r5�test_retry_successEs
z%TestRetryDecorator.test_retry_successcshtdddd��fdd��}ttd���t�t��|�Wd�n1sL0Y|jdksdJ�dS)Nr*r+r,cs�r���ddqdSr/r0r2r3r2r5r6Ws
z2TestRetryDecorator.test_retry_failure.<locals>.foo�)rr8r9r�raises�ZeroDivisionErrorr:r;r2r3r5�test_retry_failureTs$z%TestRetryDecorator.test_retry_failurecCsVttdd�dd��}t�t��|�Wd�n1s:0Y|jdksRJ�dS)Nr+)�	exceptionr.cSst�dS�N)�	TypeErrorr2r2r2r5r6esz2TestRetryDecorator.test_exception_arg.<locals>.foor)r�
ValueErrorrr@rEr:r;r2r2r5�test_exception_argcs


$z%TestRetryDecorator.test_exception_argcCsXtdddd�dd��}t�t��|�Wd�n1s<0Y|jdksTJ�dS)Nr*r,cSsdddSr/r2r2r2r2r5r6qsz4TestRetryDecorator.test_no_interval_arg.<locals>.foor�rrr@rAr:r;r2r2r5�test_no_interval_argms

$z'TestRetryDecorator.test_no_interval_argcCsXtdddd�dd��}t�t��|�Wd�n1s<0Y|jdksTJ�dS)Nr*r+r,cSsdddSr/r2r2r2r2r5r6{sz0TestRetryDecorator.test_retries_arg.<locals>.foorHr;r2r2r5�test_retries_argys

$z#TestRetryDecorator.test_retries_argcCs:t�t��tddd�Wd�n1s,0YdS)Nr*r+)r-�timeout)rr@rFr)r<r=r2r2r5�test_retries_and_timeout_args�sz0TestRetryDecorator.test_retries_and_timeout_argsN)�__name__�
__module__�__qualname__r�patchr>rBrGrIrJrLr2r2r2r5r)Ds


	

	r)c@s<eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
S)�TestSyncTestUtilsc	Cs�tt���tt���d}tjdtdg�d��Dt	�
tj��t|�Wd�n1s\0YWd�n1sz0YdS)Ni���psutil.tests.retry.__iter__r�Zreturn_value)r(�os�getpid�max�psutilZpidsrrP�iterrr@Z
NoSuchProcess)r<Znopidr2r2r5�test_wait_for_pid�s
z#TestSyncTestUtils.test_wait_for_pidcCsX|��}t|d��}|�d�Wd�n1s20Yt|�tj�|�rTJ�dS)N�wr6��
get_testfn�open�writer'rT�path�exists�r<�testfn�fr2r2r5�test_wait_for_file�s
(z$TestSyncTestUtils.test_wait_for_filecCsR|��}t|d��Wd�n1s(0Yt|dd�tj�|�rNJ�dS)NrZT)�empty)r\r]r'rTr_r`�r<rbr2r2r5�test_wait_for_file_empty�s
z*TestSyncTestUtils.test_wait_for_file_emptyc	Csr|��}tjdtdg�d��Bt�t��t|�Wd�n1sF0YWd�n1sd0YdS)NrRrrS)r\rrPrXrr@�IOErrorr'rfr2r2r5�test_wait_for_file_no_file�sz,TestSyncTestUtils.test_wait_for_file_no_filecCs\|��}t|d��}|�d�Wd�n1s20Yt|dd�tj�|�sXJ�dS)NrZr6F)�deleter[rar2r2r5�test_wait_for_file_no_delete�s
(z.TestSyncTestUtils.test_wait_for_file_no_deletecCstdd��dS)NcSsdS�Nr+r2r2r2r2r5�<lambda>��z3TestSyncTestUtils.test_call_until.<locals>.<lambda>r�r<r2r2r5�test_call_until�sz!TestSyncTestUtils.test_call_untilN)	rMrNrOrYrdrgrirkrpr2r2r2r5rQ�srQc@s4eZdZdd�Zdd�Zdd�Zdd�Zd	d
�ZdS)�TestFSTestUtilscCs:tt��}|jdksJ�Wd�n1s,0YdS)N�r)r�__file__�mode�r<rcr2r2r5�test_open_text�s
zTestFSTestUtils.test_open_textcCs:tt��}|jdksJ�Wd�n1s,0YdS)N�rb)rrsrtrur2r2r5�test_open_binary�s
z TestFSTestUtils.test_open_binarycCs<|��}t|�tj�|�s J�t|�tj�|�s8J�dSrD)r\r!rTr_�isdirrfr2r2r5�test_safe_mkdir�s
zTestFSTestUtils.test_safe_mkdirc	Cs�|��}t|d���t|�tj�|�r.J�t|�t�|�t|�tj�|�rXJ�tj	dt
tjd�d��L}t
�t
��t|�Wd�n1s�0Y|js�J�Wd�n1s�0YdS)NrZzpsutil.tests.os.stat�)Zside_effect)r\r]�closer"rTr_r`�mkdirrrP�OSError�errno�EINVALrr@�called)r<rb�mr2r2r5�test_safe_rmpath�s
�&z TestFSTestUtils.test_safe_rmpathcCsp|��}t��}t�|�t|��*t��tj�||�ks>J�Wd�n1sR0Yt��|kslJ�dSrD)r\rT�getcwdr}rr_�join)r<rb�baser2r2r5�
test_chdir�s

8zTestFSTestUtils.test_chdirN)rMrNrOrvrxrzr�r�r2r2r2r5rq�s
rqc@s>eZdZdd�Zdd�Zejjedd�dd��Z	d	d
�Z
dS)�TestProcessUtilscCsN|��}t�|j�}|��s J�t�|��r2J�tjjr>J�tjjrJJ�dSrD)	�spawn_testprocrW�Process�pid�
is_runningr�testsZ
_pids_startedZ_subprocesses_started)r<Zsubp�pr2r2r5�test_reap_children�sz#TestProcessUtils.test_reap_childrencCs�|��\}}|j|jksJ�|��s(J�|��s4J�t����}||gksNJ�t��jdd�}t|�dksnJ�||vszJ�||vs�J�|��t�	�ks�J�|��|jks�J�t
|�|��r�J�|��s�J�t
|�|��r�J�dS)NT)�	recursive�)Zspawn_children_pairr�r�rWr��children�len�ppidrTrUr%)r<�childZ
grandchildr�r2r2r5�test_spawn_children_pair�s"z)TestProcessUtils.test_spawn_children_pair�
POSIX only��reasoncCs"|��\}}|��tjksJ�dSrD)�spawn_zombie�statusrWZ
STATUS_ZOMBIE)r<�_parent�zombier2r2r5�test_spawn_zombie�sz"TestProcessUtils.test_spawn_zombiecCs�|��}t|�|�|j�t|�t�|��j�}t|�|�|j�t|�tddg}tj|tj	tj	t
d�}t|�|�|j�t|�|��j}t|�|�|j�t|�tr�|��\}}t|�t|�|�|j�|�|j�dS)Nz-cz3import time; [time.sleep(0.1) for x in range(100)];)�stdout�stderr�env)
r�r%Z
assertPidGoner�rWr�r
�Popen�
subprocess�PIPErrr�)r<r��cmdr��parentr�r2r2r5�test_terminates>��
zTestProcessUtils.test_terminateN)rMrNrOr�r�r�mark�skipifrr�r�r2r2r2r5r��s
	
r�c@sleZdZdd�Zejjedd�dd��Zdd�Z	ejjedd�ejje
pNed	d�d
d���Zdd
�Z
dS)�TestNetUtilscCsRt�}t�td|fd���$}|��d|ks0J�Wd�n1sD0YdS)Nr{��addrr+)r�
contextlib�closingr�getsockname)r<�port�sr2r2r5r+szTestNetUtils.bind_socketr�r�cCs�|��}t|�}t�|��f|jtjks,J�|jtjks<J�|�	�|ksLJ�t
j�|�s\J�t
�t
�
|�j�srJ�Wd�n1s�0Y|��}t|tjd�}t�|�� |jtjks�J�Wd�n1s�0YdS)N)�type)r\rr�r��family�socket�AF_UNIXr��SOCK_STREAMr�rTr_r`�stat�S_ISSOCK�st_mode�
SOCK_DGRAM)r<�name�sockr2r2r5�test_bind_unix_socket0s4z"TestNetUtils.test_bind_unix_socketc	Cs�dt�f}ttj|d�\}}t�|��jt�|��@|��|ksDJ�|��|ksTJ�|��|ksdJ�Wd�n1sx0YWd�n1s�0YdS)Nz	127.0.0.1r�)rr$r��AF_INETr�r�r��getpeername)r<r��server�clientr2r2r5�tcp_tcp_socketpair@s
zTestNetUtils.tcp_tcp_socketpairz*/var/run/log UNIX socket opened by defaultcCs�t��}|��}t|jdd��gks(J�|��}t|�\}}z�tj�	|�sNJ�t
�t�
|�j�sdJ�|��|dksxJ�t
t|jdd���dks�J�|��|ks�J�|��|ks�J�W|��|��n|��|��0dS)N�unix)�kindr�)rWr��num_fdsrZnet_connectionsr\r&rTr_r`r�r�r�r�r�r�r|)r<r�r�r�r�r�r2r2r5�test_unix_socketpairKs,����
�z!TestNetUtils.test_unix_socketpaircCs�t���}t�t�}t�t�}|D]2}||jd7<||�tjtj�d7<q |tj	dksfJ�t
�r~|tjdks~J�tr�t
r�|tjdks�J�|tjdks�J�|tjdks�J�Wd�n1s�0YdS)Nr+r�)r�collections�defaultdict�intr��
getsockoptr��
SOL_SOCKET�SO_TYPEr�r�AF_INET6rrr�r�r�)r<�socksZfams�typesr�r2r2r5�test_create_socketsgs

z TestNetUtils.test_create_socketsN)rMrNrOrrr�r�rr�r�rrr�r�r2r2r2r5r�*s
�r��serial�r�c@sheZdZe�dd��Zdd�Ze�ejje	dd�ejje
dd�dd	����Zd
d�Zdd
�Z
dd�ZdS)�TestMemLeakClasscs8�fdd�}ddi�|j|ddd��ddks4J�dS)	Ncs�dd7<dS)N�cntr+r2r2�r�r2r5�fun|sz(TestMemLeakClass.test_times.<locals>.funr�r�
�)�times�warmup_times�)�execute)r<r�r2r�r5�
test_timeszszTestMemLeakClass.test_timescCs2t�t��"|jdd�dd�Wd�n1s20Yt�t��"|jdd�dd�Wd�n1sn0Yt�t��"|jdd�dd�Wd�n1s�0Yt�t��"|jd	d�dd
�Wd�n1s�0Yt�t��"|jdd�dd�Wd�n1�s$0YdS)
NcSsdS�Nrr2r2r2r2r5rm�rnz1TestMemLeakClass.test_param_err.<locals>.<lambda>r�r�cSsdSr�r2r2r2r2r5rm�rn���cSsdSr�r2r2r2r2r5rm�rn)r�cSsdSr�r2r2r2r2r5rm�rn)�	tolerancecSsdSr�r2r2r2r2r5rm�rn)r-)rr@rFr�ror2r2r5�test_param_err�s0000zTestMemLeakClass.test_param_errz
skipped on CIr�zskipped during test coveragecCs\g}|fdd�}zBtjtdd��|j|dd�Wd�n1sD0YW~n~0dS)NcSs|�dd�dS)NZ�xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx���append��lsr2r2r5r��sz+TestMemLeakClass.test_leak_mem.<locals>.funz	extra-mem��match�dr�)rr@�AssertionErrorr�)r<r�r�r2r2r5�
test_leak_mem�s.zTestMemLeakClass.test_leak_memcs^��fdd�}g�trdnd}tjtd|d����|�Wd�n1sP0YdS)Ncs"tt�}��|j���|�dSrD)r]rsZ
addCleanupr|r�)rc�Zboxr<r2r5r��sz1TestMemLeakClass.test_unclosed_files.<locals>.fun�fd�handlez	unclosed r�)rrr@r�r�)r<r�r�r2r�r5�test_unclosed_files�s
z$TestMemLeakClass.test_unclosed_filescs>�fdd�}g�d}|j||ddd�t��|dks:J�dS)Ncs��dd�dS)NZxxxxxxxxxxxxxxxxxxxxxxxxr�r�r2r�r2r5r��sz,TestMemLeakClass.test_tolerance.<locals>.funr�ri�)r�r�r�r+)r�r�)r<r�r�r2r�r5�test_tolerance�s�zTestMemLeakClass.test_tolerancecCs�dd�}|�t|�t�t��|�t|�Wd�n1s@0Ydd�}t�t��|�t|�Wd�n1s~0YdS)NcSsdddSr/r2r2r2r2r5�fun_1�sz2TestMemLeakClass.test_execute_w_exc.<locals>.fun_1cSsdSrDr2r2r2r2r5�fun_2�sz2TestMemLeakClass.test_execute_w_exc.<locals>.fun_2)Z
execute_w_excrArr@r~r�)r<r�r�r2r2r5�test_execute_w_exc�s*z#TestMemLeakClass.test_execute_w_excN)rMrNrOr r�r�rr�r�r	r
r�r�r�r�r2r2r2r5r�xs

r�c@sVeZdZdd�Zdd�Zdd�Zdd�Zejj	e
d	d
�dd��Zd
d�Zdd�Z
dS)�TestFakePytestcCs(t��}|�|�t��}|�|�}|SrD)�unittestZ	TestSuiteZaddTestZTextTestRunner�run)r<�klass�suite�runner�resultr2r2r5�run_test_class�s


zTestFakePytest.run_test_classc
Cs�t�t��}ddWd�n1s(0Yt|jt�sBJ�tjtdd��}td��Wd�n1sn0Yz:tjtdd��}td��Wd�n1s�0YWn4ty�}zt|�dks�J�WYd}~nd}~00|�d��dS)Nr+rr6r��barz"foo" does not match "bar"�exception not raised)	rr@rA�
isinstance�valuerFr��str�fail)r<�cm�errr2r2r5�test_raises�s&&*&zTestFakePytest.test_raisescCsVtjjdd�dd��}|�dks$J�tjjdd�Gdd�d��}|���dksRJ�dS)Nr�r�cSsdSrlr2r2r2r2r5r6�sz%TestFakePytest.test_mark.<locals>.foor+c@seZdZdd�ZdS)z%TestFakePytest.test_mark.<locals>.FoocSsdSrlr2ror2r2r5r��sz)TestFakePytest.test_mark.<locals>.Foo.barN)rMrNrOr�r2r2r2r5�Foo�sr)rr��xdist_groupr�)r<r6rr2r2r5�	test_mark�s
zTestFakePytest.test_markcCs�Gdd�dtj�}|�|d��}|��s,J�t|j�dks>J�|jdddksTJ�Gdd�dtj�}|�|d��}|��s�J�t|j�dks�J�dS)Nc@s$eZdZejjddd�dd��ZdS)�,TestFakePytest.test_skipif.<locals>.TestCaseTr�r�cSsddksJ�dSrlr2ror2r2r5r6�s�0TestFakePytest.test_skipif.<locals>.TestCase.fooN�rMrNrOrr�r�r6r2r2r2r5�TestCase�srr6r+rr�c@s$eZdZejjddd�dd��ZdS)r	Fr�r�cSsddksJ�dSrlr2ror2r2r5r6�sr
Nrr2r2r2r5r�s�r�rr�Z
wasSuccessfulr��skipped�r<rr�r2r2r5�test_skipif�szTestFakePytest.test_skipifznot PY3r�cCsXGdd�dtj�}|�|d��}|��s,J�t|j�dks>J�|jdddksTJ�dS)Nc@seZdZdd�ZdS)z*TestFakePytest.test_skip.<locals>.TestCasecSst�d�ddksJ�dS)Nr�r+r)r�skipror2r2r5r6s
z.TestFakePytest.test_skip.<locals>.TestCase.fooN)rMrNrOr6r2r2r2r5rsrr6r+rr�r
rr2r2r5�	test_skip�s
zTestFakePytest.test_skipc	Cs|jtd�}t�|�ttj�|d�d��Wd�n1s@0Yttj�|d�d��$}|�t�	d��
��Wd�n1s�0Ytj�
tjd|��T|�td��(t��}|��dks�J�Wd�n1s�0YWd�n1s�0YdS)	N)�dirz__init__.pyrZztest_file.pyz�                import unittest

                class TestCase(unittest.TestCase):
                    def test_passed(self):
                        pass
                rzFake pytest module was usedr+)r\rrTr}r]r_r�r^�textwrap�dedent�lstriprrP�objectrWr�ZassertWarnsRegex�UserWarningr�mainZcountTestCases)r<Ztmpdirrcr�r2r2r5�	test_main
s
2�zTestFakePytest.test_maincCs<t�t�� tjdtdd�Wd�n1s00Yz>t�t�� tjdtdd�Wd�n1sl0YWnty�Yn0|�d��tjtdd�� tjdtdd�Wd�n1s�0YzDtjtdd�� tjdtdd�Wd�n1�s0YWnt�y,Yn0|�d��dS)Nr6r+)�
stacklevelr�r�r�)rZwarnsr�warnings�warn�DeprecationWarningr�rror2r2r5�
test_warnss .2
.4zTestFakePytest.test_warnsN)rMrNrOr�rrrrr�r�rrrrr2r2r2r5r��s
r�c@seZdZdd�Zdd�ZdS)�TestTestingUtilscCsLt��}t|�}|��dd�|�|j�D�dd}|�|��ksHJ�dS)NcSsg|]}|ddkr|�qS)r+r�r2��.0�xr2r2r5�
<listcomp>?rnz;TestTestingUtils.test_process_namespace.<locals>.<listcomp>r)rWr�r�testrX�gettersr�)r<r��nsr�r2r2r5�test_process_namespace;s
z'TestTestingUtils.test_process_namespacecCs:t�}dd�|�|j�D�dd}|�t��ks6J�dS)NcSsg|]}|ddkr|�qS)r+�net_if_addrsr2r!r2r2r5r$Drnz:TestTestingUtils.test_system_namespace.<locals>.<listcomp>r)r#rXr&rWr))r<r'r�r2r2r5�test_system_namespaceBsz&TestTestingUtils.test_system_namespaceN)rMrNrOr(r*r2r2r2r5r :sr c@seZdZdd�ZdS)�TestOtherUtilscCs.tt�dd�ddd��sJ�tt��r*J�dS)Nr6za b cr+r�r7)rr��
namedtuple�tupleror2r2r5�test_is_namedtupleIsz!TestOtherUtils.test_is_namedtupleN)rMrNrOr.r2r2r2r5r+Hsr+)@�__doc__r�r�rrTr�r�r�rr�rrWZpsutil.testsrrrZpsutil._commonrrrZpsutil._compatrr	r
rrr
rrrrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)rQrqr�r�r�rr�r�r r+r2r2r2r5�<module>sxE(-LNKvPKok\���Sh�h�0psutil/tests/__pycache__/__init__.cpython-39.pycnu�[���a

��?h��@s:dZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZddlmZddlmZzddlZWne�ydZYn0ddl Z ddl m!Z!ddl m"Z"dd	l m#Z#dd
l m$Z$ddl m%Z%ddl m&Z&dd
l m'Z'ddl m(Z(ddl)m*Z*ddl)m+Z+ddl)m,Z,ddl)m-Z-ddl)m.Z.ddl/m0Z0ddl/m1Z1ddl/m2Z2ddl/m3Z3ddl/m4Z4ddl/m5Z5ddl/m6Z6zddlm7Z7WnPe�yre�8��"e�9d�ddl7Z7Wd�n1�sd0YYn0e0�r�ddl:Z:nddl;ZdZ:e&�r�ddl<m=Z=gd�Z>dej?vZ@d e	jAvZBd!e	jAv�p�d"e	jAvZCeB�p�eCZDd#e	jAvZEd$e	jAvZFe"�r6eC�r6eGd%��ZHd&eH�I�vZJWd�n1�s*0Ynd'ZJejKd(kZLe
�M�d)kZNe,d*d+��ZOe#�rxeO�d,kZPeO�d-kZQnd'ZPd'ZQd.ZRd/ZSd0ZTd1ZUeD�r�eRd29ZReUd29ZUeSd39ZSeTd29ZTe	jVd4k�r�d5e	�W�ZXnd6e	�W�ZXd7ZYe0�r�d8�Zd9d:�Z[nd;Z[e�\��]�d<vZ^e	j_�`e	j_�ae	j_�bec�d=d=��Zde	jA�ed>e	j_�aedd?��Zfe	j_�`e	j_�bec��Zgehe jid@�Zjehe dA�Zkehe jidB�Zlehe dC�Zmehe jidD�Znehe jidE�Zoe&�o�e'Zpehe dF�Zqehe jidG�Zrehe jidH�Zsehe jidI�Ztehe dJ�Zuzeu�o�eve �w��ZxWney�y
d'ZxYn0ehe dK�Zzehe dL�Z{ehe jidM�Z|e#�s8e!�oBe	�}�dkZ~dNdO�Ze�\Z�Z�eGe	j�dP�Z�e��e�j��dQdR�e�e �D�Z�e�edSe���Z�e��Z�e��Z�GdTdU�dUej��Z�dVdW�Z�e�d�dXdY��Z�e�dZd[��Z�d\d]�Z�e�d^d_��Z�e�d`da��Z�ej�eUfdbdc�Z�d�ddde�Z�dfdg�Z�dhdi�Z�Gdjdk�dk�Z�e�e j�deUdldm�dndo��Z�e�e2e�fdeUdldm�d�dqdr��Z�e�e�deUdldm�dsdt��Z�dudv�Z�dwdx�Z�ej�dydz��Z�d{d|�Z�d�d}d~�Z�d�d�d��Z�Gd�d��d��Z�edu�r�e�ZGd�d��d�ej��Z�e�e_�Gd�d��d�e��Z�ej�j�e@d�d��Gd�d��d�e���Z�d�d��Z�d�d��Z�d�d��Z�Gd�d��d��Z�Gd�d��d��Z�eRfd�d��Z�d�d�d��Z�d�d�d��Z�d�d�d��Z�eedfd�d��Z�ejfd�d��Z�d�d�d��Z�d�d��Z�ej�d�d���Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�e&�rej�d�d�d���Z�nej�d�d�d���Z�ej�d�d���Z�e&�r6e�ej�d�d���dS)�zTest utilities.�)�print_functionN)�AF_INET)�AF_INET6)�SOCK_STREAM)�AIX)�LINUX)�MACOS)�NETBSD)�OPENBSD)�POSIX)�SUNOS)�WINDOWS)�bytes2human)�debug)�memoize)�print_color)�
supports_ipv6)�PY3)�FileExistsError)�FileNotFoundError)�range)�super)�unicode)�which)�mock�ignore)�wait_pid)M�APPVEYOR�DEVNULL�GLOBAL_TIMEOUT�TOLERANCE_SYS_MEM�
NO_RETRIES�PYPY�
PYTHON_EXE�PYTHON_EXE_ENV�ROOT_DIR�SCRIPTS_DIR�
TESTFN_PREFIX�UNICODE_SUFFIX�INVALID_UNICODE_SUFFIX�
CI_TESTING�VALID_PROC_STATUSES�TOLERANCE_DISK_USAGE�IS_64BIT�HAS_CPU_AFFINITY�HAS_CPU_FREQ�HAS_ENVIRON�HAS_PROC_IO_COUNTERS�
HAS_IONICE�HAS_MEMORY_MAPS�HAS_PROC_CPU_NUM�
HAS_RLIMIT�HAS_SENSORS_BATTERY�HAS_BATTERY�HAS_SENSORS_FANS�HAS_SENSORS_TEMPERATURES�HAS_NET_CONNECTIONS_UNIX�MACOS_11PLUS�MACOS_12PLUS�COVERAGE�AARCH64�	QEMU_USER�PYTEST_PARALLEL�pyrun�	terminate�
reap_children�spawn_testproc�spawn_zombie�spawn_children_pair�
ThreadTask�unittest�skip_on_access_denied�skip_on_not_implemented�retry_on_failure�TestMemoryLeak�PsutilTestCase�process_namespace�system_namespace�
print_sysinfo�is_win_secure_system_proc�fake_pytest�chdir�safe_rmpath�
create_py_exe�create_c_exe�
get_testfn�
get_winver�kernel_version�
call_until�wait_for_pid�
wait_for_file�check_net_address�filter_proc_net_connections�
get_free_port�bind_socket�bind_unix_socket�tcp_socketpair�unix_socketpair�create_sockets�
reload_module�import_module_by_path�warn�copyload_shared_lib�
is_namedtupleZ__pypy__r�GITHUB_ACTIONSZCIBUILDWHEELZCOVERAGE_RUNZPYTEST_XDIST_WORKERz/proc/1/cmdlinez
/bin/qemu-Fl�aarch64cCsnt��d}ttt|�d�dd���}|dkrjtjtj	dddgdd	id
d�}ttt|�d�dd���}|S)Nr�.�)�
�z-sS�-cz-import platform; print(platform.mac_ver()[0])ZSYSTEM_VERSION_COMPAT�0T)�env�universal_newlines)
�platform�mac_ver�tuple�map�int�split�
subprocess�check_output�sys�
executable)�version_str�version�r��A/usr/local/lib64/python3.9/site-packages/psutil/tests/__init__.py�
macos_version�s��
r�)rn�)�rrniPi�����javaz$psutil-%s-z@psutil-%s-u-ƒőősf���utf8�surrogateescapeufÀ€)�asciizus-asciiz..ZPSUTIL_SCRIPTS_DIR�scripts�cpu_affinity�cpu_freq�environ�
getloadavg�ionice�memory_maps�net_io_counters�cpu_num�io_counters�rlimit�sensors_battery�sensors_fans�sensors_temperatures�threadscCs�dd�}tj��}ttdd�}trFtjdkrF|durFtj|d<||fStrTtj|fSt	r�|tj�p�|tj
�tj��p�|tdtjdd���p�|t
�����}|s�td��||fStj
�tj�}tj
�|�s�J|��||fSdS)	NcSs<ztj|dgtjtjd�Wntjy2YdS0|SdS)Nz-V)�stdout�stderr)rz�
check_call�PIPE�CalledProcessError)�exer�r�r��attempt�s�
z_get_py_exe.<locals>.attempt�_base_executable)r���__PYVENV_LAUNCHER__zpython%s.%srmz"can't find python exe real abspath)�osr��copy�getattrr|r
�version_infor}rjr�path�realpathr�psutil�Processr��
ValueError�exists)r�rr�baser�r�r�r��_get_py_exe�s,




���r�zr+cCs g|]}|�d�rtt|��qS)ZSTATUS_��
startswithr�r���.0�xr�r�r��
<listcomp>$sr��AF_UNIXcsPeZdZdZ�fdd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
�ZS)rGz6A thread task which does nothing expect staying alive.cs$t���d|_d|_t��|_dS)NF���MbP?)r�__init__�_running�	_interval�	threading�Event�_flag��self��	__class__r�r�r�5s
zThreadTask.__init__cCs|jj}d||jt|�fS)Nz<%s running=%s at %#x>)r��__name__r��id�r��namer�r�r��__repr__;szThreadTask.__repr__cCs|��|S�N)�startr�r�r�r��	__enter__?szThreadTask.__enter__cOs|��dSr�)�stop)r��args�kwargsr�r�r��__exit__CszThreadTask.__exit__cCs(|jrtd��tj�|�|j��dS)zStart thread and keep it running until an explicit
        stop() request. Polls for shutdown every 'timeout' seconds.
        zalready startedN)r�r�r��Threadr�r��waitr�r�r�r�r�FszThreadTask.startcCs(d|_|j��|jr$t�|j�qdS)NT)r�r��set�time�sleepr�r�r�r�r��runOs
zThreadTask.runcCs |jstd��d|_|��dS)z8Stop thread execution and and waits until it is stopped.zalready stoppedFN)r�r��joinr�r�r�r�r�UszThreadTask.stop)r��
__module__�__qualname__�__doc__r�r�r�r�r�r�r��
__classcell__r�r�r�r�rG2s	rGcst����fdd��}|S)Ncs0z�|i|��WSty*t��Yn0dSr�)�	ExceptionrC�r�r���funr�r��wrappercs
z&_reap_children_on_err.<locals>.wrapper��	functools�wraps�r�r�r�r�r��_reap_children_on_errbsr�cKs�|�dt�|�dt�|�dt���|�dt�trHd}|�d|�|dur�tt��d�}zXt|�d	d
|d}td|g}t	j
|fi|��}t�|�t
|d
d
d�Wt|�q�t|�0n&t	j
|fi|��}t�|�t|j�|S)aCreate a python subprocess which does nothing for some secs and
    return it as a subprocess.Popen instance.
    If "cmd" is specified that is used instead of python.
    By default stdin and stdout are redirected to /dev/null.
    It also attempts to make sure the process is in a reasonably
    initialized state.
    The process is registered for cleanup on reap_children().
    �stdinr��cwdrr��
creationflagsN��dirzimport time;zopen(r'%s', 'w').close();z&[time.sleep(0.1) for x in range(100)];rpT��delete�empty)�
setdefaultrr��getcwdr$r
rWrTr#rz�Popen�_subprocesses_started�addr\r[�pid)�cmd�kwdsZCREATE_NO_WINDOW�testfnZpyline�sprocr�r�r�rDns4
���



rDcCs�d}tt��d�}z�t�dtj�|�tf�}trDt	|dd�\}}nt	|�\}}t
�|j�}t
t|ddd��}t�|�t
�|�}||fWt|�|dur�t|�Snt|�|dur�t|�0dS)	aCreate a subprocess which creates another one as in:
    A (us) -> B (child) -> C (grandchild).
    Return a (child, grandchild) tuple.
    The 2 processes are fully initialized and will live for 60 secs
    and are registered for cleanup on reap_children().
    Nr�aV            import subprocess, os, sys, time
            s = "import os, time;"
            s += "f = open('%s', 'w');"
            s += "f.write(str(os.getpid()));"
            s += "f.close();"
            s += "[time.sleep(0.1) for x in range(100 * 6)];"
            p = subprocess.Popen([r'%s', '-c', s])
            p.wait()
            r)r�TFr�)rWr�r��textwrap�dedentr��basenamer#r
rAr�r�r�rxr\�
_pids_startedr�rT)�tfiler��s�subp�childZgrandchild_pidZ
grandchildr�r�r�rF�s0	�


��rFcs$tjs
J�t�}t�d|�}d}t|�}z�|�t�t|�\}}|�	�\}}z|t
�
|��gggt�t|�
d��}t�|�t�|��t�fdd��|�fW|��W|��t|�|dur�t|�S|��0W|��t|�|du�r t|�n$|��t|�|du�rt|�0dS)z�Create a zombie process and return a (parent, zombie) process tuple.
    In order to kill the zombie parent must be terminate()d first, then
    zombie must be wait()ed on.
    a        import os, sys, time, socket, contextlib
        child_pid = os.fork()
        if child_pid > 0:
            time.sleep(3000)
        else:
            # this is the zombie process
            s = socket.socket(socket.AF_UNIX)
            with contextlib.closing(s):
                s.connect('%s')
                if sys.version_info < (3, ):
                    pid = str(os.getpid())
                else:
                    pid = bytes(str(os.getpid()), 'ascii')
                s.sendall(pid)
        N�cs���tjkSr�)�statusr��
STATUS_ZOMBIEr���zombier�r��<lambda>��zspawn_zombie.<locals>.<lambda>)r�rrWr�r�ra�
settimeoutrrA�accept�select�filenorx�recvr�r�r�rZ�closerT)Z	unix_file�srcr��sock�parent�conn�_Zzpidr�rr�rE�sD
�


��

�
rEcKs�|�dd�|�dd�t�}z^t|d��}|�|�Wd�n1sJ0Ytt|jgfi|��}t|j�||fWSt	y�t
|��Yn0dS)z�Run python 'src' code string in a separate interpreter.
    Returns a subprocess.Popen instance and the test file where the source
    code was written.
    r�Nr��w)r�rW�open�writerDr#r�r[r�r�rT)rr��srcfile�fr�r�r�r�rA�s(

rAcKs�trdnd}|�dtj�|�dtj�|�dd�|�d|�t|t�rTt�|�}tj|fi|��}t	�
|�tr�|jt
d�\}}n|��\}}|jdkr�t||��|r�t|�|�d	�r�|d
d�}|S)zURun cmd in a subprocess and return its output.
    raises RuntimeError on error.
    r�rr�r�rsTr���timeout�
N���)r
r�rzr��
isinstance�str�shlexryr�r�r�r�communicater�
returncode�RuntimeErrorrg�endswith)r�r��flags�pr�r�r�r�r��shs&




r#c
sdd��dd�����fdd�}���fdd���fd	d
�}dd�}|}�znt|t�r�|||�Wt|tjtjf�rz||�t|t�r�|n|j}t�|�r�J|��St|tjtjf��r�||�Wt|tjtjf�r�||�t|t�r�|n|j}t�|��rJ|��St|tj��rd|||�Wt|tjtjf��r8||�t|t��rH|n|j}t�|��rbJ|��Std
|��Wt|tjtjf��r�||�t|t��r�|n|j}t�|��rJ|��nHt|tjtjf��r�||�t|t��r�|n|j}t�|��rJ|��0dS)a�Terminate a process and wait() for it.
    Process can be a PID or an instance of psutil.Process(),
    subprocess.Popen() or psutil.Popen().
    If it's a subprocess.Popen() or psutil.Popen() instance also closes
    its stdin / stdout / stderr fds.
    PID is wait()ed even if the process is already gone (kills zombies).
    Does nothing if the process does not exist.
    Return process exit status.
    cSsbt|tj�rts|��n
|�|�tr^t|tj�r^zt�|j��|�WStj	y\Yn0dSr�)
rrzr�rr�r
r�r�r��
NoSuchProcess��procrr�r�r�r�'s

zterminate.<locals>.waitcSs6trtrtj}tr(|tjkr(|�tj�|�|�dSr�)rrj�signal�SIGKILLr�send_signal�SIGCONT)r&�sigr�r�r��sendsig3s
zterminate.<locals>.sendsigc
s\z�|��WnBtyP}z*tr.|jdkr.n|jtjkr<�WYd}~n
d}~00�||�S)N�)�OSErrorr
�winerror�errnoZESRCH)r&r�err�r,r+r�r�r��term_subprocess_proc=sz'terminate.<locals>.term_subprocess_proccs.z�|��Wntjy"Yn0�||�Sr�)r�r$r%r2r�r��term_psutil_procGs
z#terminate.<locals>.term_psutil_proccsDzt�|�}Wn&tjy4tr0t||�YSYn0�||�SdSr�)r�r�r$rr)r�rr&)r4r�r��term_pidNszterminate.<locals>.term_pidcSs4|jr|j��|jr |j��|jr0|j��dSr�)r�rr�r�)r&r�r�r��flush_popenXs

zterminate.<locals>.flush_popenz
wrong type %rN)	rrxrzr�r�r��
pid_existsr��	TypeError)Zproc_or_pidr+�wait_timeoutr3r5r6r"r�r�)r,r+r4r�r�rBsL


	

�
�
��rBcCs�t��j|d�}tr&t��}t|�qtr<t��}t|�q&|r�|D]}t|dd�qDtj|td�\}}|D]}t	d|�t|t
jd�qldS)aTerminate and wait() any subprocess started by this test suite
    and any children currently running, ensuring that no processes stick
    around to hog resources.
    If recursive is True it also tries to terminate and wait()
    all grandchildren started by this process.
    ��	recursiveN)r9rz0couldn't terminate process %r; attempting kill())r+)r�r��childrenr��poprBr��
wait_procsrrgr'r()r;r<r�r�r"r�aliver�r�r�rCrs


rCcCs�tstd��d}t��d}|D]"}|��s4|dkr>||7}q qDq |sTtd|��d}d}|�d�}t|d�}t|�dkr�t|d�}t|�dkr�t|d�}|||fS)	z"Return a tuple such as (2, 6, 36).z	not POSIX�rmrlzcan't parse %rr�r�)	r�NotImplementedErrorr��uname�isdigitr�ryrx�len)r�rC�c�minor�micro�nums�majorr�r�r�rY�s&

rYcCsbtstd��t��}t|d�r*|jp&d}n&t�d|d�}|rLt|�	d��nd}|d|d|fS)Nznot WINDOWS�service_pack_majorrz\s\d$r�rA)
r
rBr|�getwindowsversion�hasattrrK�re�searchrx�group)Zwv�sp�rr�r�r�rX�s
rXc@s<eZdZdZeddddfdd�Zdd�Zdd	�Zd
d�ZdS)�retryzA retry decorator.Nr�cCs2|r|rtd��||_||_||_||_||_dS)Nz/timeout and retries args are mutually exclusive)r��	exceptionr�retries�interval�logfun)r�rTrrUrVrWr�r�r�r��szretry.__init__ccsT|jr*t��|j}t��|krPdVqn&|jrHt|j�D]
}dVq:ndVqHdSr�)rr�rUr)r��stop_atrr�r�r��__iter__�s

zretry.__iter__cCs|jdurt�|j�dSr�)rVr�r�r�r�r�r�r��s
zretry.sleepcs"t�����fdd��}�|_|S)Ncs�d}�D]l}z�|i|��WS�jyr}z8|}�jdurJ��|����WYd}~qWYd}~qd}~00qtr�|�n�dSr�)rTrWr�r)r�r��excr�r�r�r�r�r��s

$zretry.__call__.<locals>.wrapper)r�r��	decorator)r�r�r�r�r[r��__call__�szretry.__call__)	r�r�r�r�r�r�rYr�r]r�r�r�r�rS�s�
rSr�)rTrWrrVcCs$|t��vrt�|��t�|�dS)z�Wait for pid to show up in the process list then return.
    Used in the test suite to give time the sub process to initialize.
    N)r��pidsr$r��r�r�r�r�r[�s

r[TcCsNt|d��}|��}Wd�n1s(0Y|s>|s>J�|rJt|�|S)z8Wait for a file to be written on disk with some content.�rbN)r�readrT)�fnamer�r�r�datar�r�r�r\
s&r\cCs|�}|sJ�|S)z1Keep calling function until it evaluates to True.r�)r��retr�r�r�rZsrZcCsldd�}zLt�|�}t�|j�r0t�tj|�}nt�tj|�}t	rJ|�n||�Wnt
yfYn0dS)z?Convenience function for removing temporary test files or dirs.c
Ss~t��t}t��|krvz|�WSty2Yn8tyh}z |}tdt|��WYd}~n
d}~00t�d�q|�dS)Nzignoring %sg{�G�z�?)r�rrZWindowsErrorrgrr�)r�rXrr1r�r�r��	retry_fun0s&zsafe_rmpath.<locals>.retry_funN)r��stat�S_ISDIR�st_moder��partial�shutil�rmtree�removerr)r�re�str�r�r�r�rT-s
rTcCs&zt�|�Wnty Yn0dS)z.Convenience function for creating a directory.N)r��mkdirrr�r�r�r��
safe_mkdirOsroc	cs8t��}zt�|�dVWt�|�nt�|�0dS)z@Context manager which temporarily changes the current directory.N)r�r�rS)�dirname�curdirr�r�r�rSWs

rScCsRtj�|�rJ|��t�t|�t�t|�t	rNt�
|�}t�||jt
j
B�|S)z6Create a Python executable file in the given location.)r�r�r��atexit�registerrTrj�copyfiler#rrf�chmodrh�S_IEXEC)r�rmr�r�r�rUbs
rUcCs�tj�|�rJ|��td�s&t�d��|dur:t�d�}nt|t	�sLJ|��t
�t|�t
tdd�d��}|�|�Wd�n1s�0Yz"t�d|jd|g�Wt|j�nt|j�0|S)	z5Create a compiled C executable in the given location.�gcczgcc is not installedNz�
            #include <unistd.h>
            int main() {
                pause();
                return 1;
            }
            z.c��suffixrz-o)r�r�r�r�pytest�skipr�r�rrrrrsrTrrWrrzr�r�)r�Zc_coderr�r�r�rVms
(rVr@cCs>tjt||d�}tj�|�stj�|�}t�t	|�|SqdS)z�Return an absolute pathname of a file or dir that did not
    exist at the time this call is made. Also schedule it for safe
    deletion at interpreter exit. It's technically racy but probably
    not really due to the time variant.
    )�prefixryr�N)
�tempfile�mktempr'r�r�r�r�rrrsrT)ryr�r�r�r�r�r�rW�s
rWc@sTeZdZdZedd��Zeddd��Zeddd��Zedd
d��ZGdd
�d
�Z	dS)rRz�A class that mimics some basic pytest APIs. This is meant for
    when unit tests are run in production, where pytest may not be
    installed. Still, the user can test psutil installation via:

        $ python3 -m psutil.tests
    cOs4t���t�}tjdd��|�tjdtdd�|S)z�Mimics pytest.main(). It has the same effect as running
        `python3 -m unittest -v` from the project root directory.
        rm)�	verbosityz<Fake pytest module was used. Test results may be inaccurate.rA��
stacklevel)	rHZ
TestLoaderZdiscover�HEREZTextTestRunnerr��warningsrg�UserWarning)r��kwZsuiter�r�r��main�s�zfake_pytest.mainNcs.Gdd�d��tjd�fdd�	�}|||d�S)zMimics `pytest.raises`.c@seZdZdZedd��ZdS)z)fake_pytest.raises.<locals>.ExceptionInfoNcSs|jSr�)�_excr�r�r�r��value�sz/fake_pytest.raises.<locals>.ExceptionInfo.value)r�r�r�r��propertyr�r�r�r�r��
ExceptionInfo�sr�Nc
3sx��}z
|VWnV|yf}z>|rLt�|t|��sLd�|t|��}t|��||_WYd}~nd}~00td|��dS)Nz"{}" does not match "{}"z
%r not raised)rNrOr�format�AssertionErrorr�)rZ�matchZeinfor1�msg�r�r�r��context�s
z#fake_pytest.raises.<locals>.context)r�)N)�
contextlib�contextmanager)rZr�r�r�r�r��raises�szfake_pytest.raisescCs"|rt���||�St���|�S)zMimics `pytest.warns`.)rH�TestCaseZassertWarnsRegexZassertWarns)�warningr�r�r�r��warns�szfake_pytest.warnsr@cCst�|��dS)zMimics `unittest.SkipTest`.N)rHZSkipTest��reasonr�r�r�r{�szfake_pytest.skipc@s(eZdZeddd��ZGdd�d�ZdS)zfake_pytest.markr@cCst�||�S)z'Mimics `@pytest.mark.skipif` decorator.)rHZskipIf)�	conditionr�r�r�r��skipif�szfake_pytest.mark.skipifc@s"eZdZdZddd�Zdd�ZdS)zfake_pytest.mark.xdist_groupz4Mimics `@pytest.mark.xdist_group` decorator (no-op).NcCsdSr�r�r�r�r�r�r��sz%fake_pytest.mark.xdist_group.__init__cCs|Sr�r�)r�Zcls_or_methr�r�r�r]�sz%fake_pytest.mark.xdist_group.__call__)N)r�r�r�r�r�r]r�r�r�r��xdist_group�s
r�N)r@)r�r�r��staticmethodr�r�r�r�r�r��mark�sr�)N)N)r@)
r�r�r�r�r�r�r�r�r{r�r�r�r�r�rR�s

rRc@s&eZdZes"dd�Zejdd��ZdS)r�cCsdSr�r�r�r�r�r��runTest�szTestCase.runTestcos
dVdSr�r�)r�r�r�r�r�r��subTest�szTestCase.subTestN)r�r�r�rr�r�r�r�r�r�r�r�r��sr�c@sZeZdZdZddd�Zdd�Zdd	�Zd
d�Zdd
�Zdd�Z	dd�Z
dd�Zdd�ZdS)rMz�Test class providing auto-cleanup wrappers on top of process
    test utilities. All test classes should derive from this one, even
    if we use pytest.
    r@NcCst||d�}|�t|�|S)N)ryr�)rW�
addCleanuprT)r�ryr�rbr�r�r�rWszPsutilTestCase.get_testfncOst|i|��}|�t|�|Sr�)rDr�rB)r�r�r�r�r�r�r�rDszPsutilTestCase.spawn_testproccCs*t�\}}|�t|�|�t|�||fSr�)rFr�rB)r�Zchild1Zchild2r�r�r�rFs
z"PsutilTestCase.spawn_children_paircCs*t�\}}|�t|�|�t|�||fSr�)rEr�rB)r�rrr�r�r�rEs
zPsutilTestCase.spawn_zombiecOs.t|i|��\}}|�t|�|�t|�|Sr�)rAr�rTrB)r�r�r�r�rr�r�r�rAszPsutilTestCase.pyruncCs�t|tj�sJ�|j|jks J�|j|jks0J�|jr@|js@J�t|tj�rt|j|jks\J�|jdurt|jdkstJ�t	|�t
|�dS�Nr)rr��Errorr�r��_name�
ZombieProcess�ppidZ_ppidr�repr)r�r&rZr�r�r��_check_proc_excs

zPsutilTestCase._check_proc_excc	Cs�t�tj��<}zt�|�Wntjy8td��Yn0Wd�n1sN0Y|jj|kshJ�|jj	dusxJ�t�
|�r�J|��|t��vs�J�|dd�t��D�vs�J�dS)Nz&wasn't supposed to raise ZombieProcesscSsg|]
}|j�qSr�r_r�r�r�r�r�5rz0PsutilTestCase.assertPidGone.<locals>.<listcomp>)
rzr�r�r$r�r�r�r�r�r�r7r^�process_iter)r�r��cmr�r�r��
assertPidGone+s,zPsutilTestCase.assertPidGonecCs�|�|j�t|�}|j|jdd�D]�\}}|j||d��vz
|�}WnFtjy\�YnFtjy�}z|�	||�WYd}~nd}~00d||f}t
|��Wd�q$1s�0Yq$|jdd�dS)NT��clear_cache�r&r�z-Process.%s() didn't raise NSP and returned %rrr)r�r�rN�iter�allr�r�r�r$r�r�r�)r�r&�nsr�r�rdrZr�r�r�r��assertProcessGone7s 
"�(z PsutilTestCase.assertProcessGonecCs�t�|j�}||ksJ�ts4ts4t|�t|�ks4J�|��tjksFJ�|��sRJ�t�	|j�sbJ�|�
�|jt��vs|J�|jdd�t��D�vs�J�it_
|jdd�t��D�vs�J�t|�}|j|jdd�D]~\}}|j||d��Vz
|�Wn:tjtjf�y.}z|�||�WYd}~n
d}~00Wd�q�1�sF0Yq�t�r$t�tj��}|��Wd�n1�s�0Y|�||j�t�tj��}|��Wd�n1�s�0Y|�||j�t�tj��}|��Wd�n1�s0Y|�||j�|��|��|��|��|���sRJ�t�	|j��sdJ�|jt��v�sxJ�|jdd�t��D�v�s�J�it_
|jdd�t��D�v�s�J�dS)	NcSsg|]
}|j�qSr�r_r�r�r�r�r�[rz6PsutilTestCase.assertProcessZombie.<locals>.<listcomp>cSsg|]
}|j�qSr�r_r�r�r�r�r�]rTr�r�cSsg|]
}|j�qSr�r_r�r�r�r�r�yrcSsg|]
}|j�qSr�r_r�r�r�r�r�{r) r�r�r�r
r	�hashrr�
is_runningr7�as_dictr^r�Z_pmaprNr�r�r�r��AccessDeniedr�rrzr��cmdliner�r�r��suspend�resumerB�kill)r�r&�cloner�r�r�rZr�r�r�r��assertProcessZombieJsN
D(((z"PsutilTestCase.assertProcessZombie)r@N)
r�r�r�r�rWrDrFrErAr�r�r�r�r�r�r�r�rM�s

rMzunreliable on PYPYr�c@s�eZdZdZdZdZdZer dndZdZ	e
��Ze
e�d��Zedd	��Zed
d��Zdd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zddd�Zdd�ZdS) rLa�Test framework class for detecting function memory leaks,
    typically functions implemented in C which forgot to free() memory
    from the heap. It does so by checking whether the process memory
    usage increased before and after calling the function many times.

    Note that this is hard (probably impossible) to do reliably, due
    to how the OS handles memory, the GC and so on (memory can even
    decrease!). In order to avoid false positives, in case of failure
    (mem > 0) we retry the test for up to 5 times, increasing call
    repetitions each time. If the memory keeps increasing then it's a
    failure.

    If available (Linux, OSX, Windows), USS memory is used for comparison,
    since it's supposed to be more precise, see:
    https://gmpy.dev/blog/2016/real-process-memory-and-environ-in-python
    If not, RSS memory is used. mallinfo() on Linux and _heapwalk() on
    Windows may give even more precision, but at the moment are not
    implemented.

    PyPy appears to be completely unstable for this framework, probably
    because of its JIT, so tests on PYPY are skipped.

    Usage:

        class TestLeaks(psutil.tests.TestMemoryLeak):

            def test_fun(self):
                self.execute(some_function)
    ��rnrr�TZPSUTIL_DEBUGcCst�d�dS)NF)r��
_set_debug��clsr�r�r��
setUpClass�szTestMemoryLeak.setUpClasscCst�|j�dSr�)r�r��_psutil_debug_origr�r�r�r��
tearDownClass�szTestMemoryLeak.tearDownClasscCs|j��}t|d|j�S)NZuss)�	_thisproc�memory_full_infor�Zrss)r��memr�r�r��_get_mem�s
zTestMemoryLeak._get_memcCstr|j��S|j��SdSr�)rr��num_fds�num_handlesr�r�r�r��_get_num_fds�s
zTestMemoryLeak._get_num_fdscCs|jrt|dtjd�dS)N�yellow)�color�file)�verboserr|r�)r�r�r�r�r��_log�szTestMemoryLeak._logcCsx|��}|�|�|��}||}|dkr8|�d|��|dkrttrHdnd}|dkr\|d7}d|||f}|�|��dS)	z�Makes sure num_fds() (POSIX) or num_handles() (Windows) does
        not increase after calling a function.  Used to discover forgotten
        close(2) and CloseHandle syscalls.
        rzHnegative diff %r (gc probably collected a resource from a previous test)�fd�handlerAr�z%s unclosed %s after calling %rN)r��call�failr)r�r��before�after�diff�type_r�r�r�r��
_check_fds�s 
��zTestMemoryLeak._check_fdscCs^tjdd�|��}t|�D]}|�|�}~~qtjdd�|��}tjgksRJ�||}|S)z�Get 2 distinct memory samples, before and after having
        called fun repeatedly, and return the memory difference.
        rA)Z
generation)�gcZcollectr�rr��garbage)r�r��timesZmem1r�rdZmem2r�r�r�r��_call_ntimes�s
zTestMemoryLeak._call_ntimescCs�g}d}|}td|d�D]�}|�||�}	d|t|	�t|	|�|f}
|�|
�|	|kp^|	|k}|r||dkrv|�|
�dS|dkr�t�|�|
�||7}|	}q|�d�|���dS)NrrAz,Run #%s: extra-mem=%s, per-call=%s, calls=%sz. )rr�r�appendr��printr�r�)r�r�r�rU�	tolerance�messagesZprev_memZincrease�idxr�r��successr�r�r��
_check_mem�s.
�


zTestMemoryLeak._check_memcCs|�Sr�r�)r�r�r�r�r�r�
szTestMemoryLeak.callNc
Cs�|dur|n|j}|dur|n|j}|dur0|n|j}|durB|n|j}zD|dksZJd��|dksjJd��|dkszJd��|dks�Jd��Wn0ty�}ztt|���WYd}~n
d}~00|�||�|�|�|j	||||d�dS)	zTest a callable.NrAztimes must be >= 1rzwarmup_times must be >= 0zretries must be >= 0ztolerance must be >= 0)r�rUr�)
r��warmup_timesrUr�r�r�rr�r�r�)r�r�r�r�rUr�r1r�r�r��executes�"
zTestMemoryLeak.executecs&���fdd�}�j|fi|��dS)znConvenience method to test a callable while making sure it
        raises an exception on every call.
        cs�����dSr�)�assertRaisesr��rZr�r�r�r�r�+sz*TestMemoryLeak.execute_w_exc.<locals>.callN)r�)r�rZr�r�r�r�r�r��
execute_w_exc&szTestMemoryLeak.execute_w_exc)NNNN)r�r�r�r�r�r�r�r*rUr�r�r�r��boolr��getenvr��classmethodr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rL�s,

�
rLcCs�ddl}ddl}ddl}ddl}ddl}zddl}WntyJd}Yn0zddl}Wntynd}Yn0|��}t	j
r�td�r�td�|d<nzt	j
r�dt��d|d<n^t	jr�dd�ttt����|d<ttd�r�|dd	t��7<nd
t��t��f|d<d	�tt���t��g�|d<t	j�rFt��d|d
<d	�t��t��t� �g�|d<t!|dd�|d<|du�r�|dd|j"7<t	j�r�td��r�tddg�}t|��#d�d|d<nd|d<t�$�d}	|	�r�|	|d<t%�&�|d<|�'�}
d|
d|
df|d<|j�(t	�)���*d�|d<|j�+��*d�|d<|�,�|d<t-j.�/d�|d <t-�0�|d!<t1|d"<t�2�|d#<t-�3�|d$<t	�4�|d%<d&t5d'd(�t	�6�D��|d)<t	�7�}d*t8|j9�t:|j;�t:|j<�f|d+<t	�=�}d*t8|j9�t:|j;�t:|j<�f|d,<t>t	�?��|d-<t	�@��A�}
|
�Bd.d�|�C|
�|d/<tDd0t%jEd1�|�F�D]$\}}tDd2|d3|ft%jEd1��q^tDd0t%jEd1�t%jG�H�t%jG�H�dS)4Nr�lsb_releasezlsb_release -d -sZOSz	Darwin %szWindows � �
win32_editionz, z%s %s�archrmZkernel�python�__version__z
not installed�pipz (wheel=%s)rwz	--versionrrA�glibczfs-encodingz%s, %s�langz%Y-%m-%d %H:%M:%Sz	boot-timer��user�~�homer�Zpyexe�hostnameZPIDZcpusz%.1f%%, %.1f%%, %.1f%%cSsg|]}|t��d�qS)�d)r��	cpu_countr�r�r�r�r�{rz!print_sysinfo.<locals>.<listcomp>Zloadavgz%s%%, used=%s, total=%sZmemory�swapr^r�r&zF======================================================================�r�z%-17s %s�:)I�collections�datetime�getpass�locale�pprintr��ImportError�wheel�OrderedDictr�rrr#ZOSXrtrur
r�rwr�	win32_verrMr��systemr�list�architecture�machinerrC�python_implementation�python_version�python_compilerr�r�ry�libc_verr|�getfilesystemencoding�	getlocale�
fromtimestamp�	boot_time�strftime�now�getuserr�r��
expanduserr�r#�node�getpidr�rvr��virtual_memoryrx�percentr�used�total�swap_memoryrEr^r�r�r=�pformatr�r��itemsr��flush)r�r�r�rrr�r�info�outr�r�r�r�Zpinfo�k�vr�r�r�rP1s�


��


����
�

rPcCs6tdd��}z|�|dkWSty0YdS0dS)NcSsXi}td�}|��dd�D]6}dd�|�d�D�}|dt|d�}}|||<q|S)Nztasklist.exe /NH /FO csvrAcSsg|]}|�dd��qS)�"r@)�replacer�r�r�r�r��rz@is_win_secure_system_proc.<locals>.get_procs.<locals>.<listcomp>�,r)r#�
splitlinesryrx)rdr!�line�bitsr�r�r�r�r��	get_procs�s
z,is_win_secure_system_proc.<locals>.get_procsz
Secure SystemF)r�KeyError)r�r*r�r�r�rQ�s
	rQcCs6t��}t|d�r|��St|d�r2t�|���SdS)Nr�r�r)r�r�rMr��random�choicer�)r"r�r�r��_get_eligible_cpu�s

r.c@sJeZdZdZddifddifgZddifddddifd	difd
difddifddifd
difddifddifddifg
Zddifddifddifddifddifddifddifddifddddifddifddifddifd difd!difd"difd#difd$difgZe�rNed%difg7Zed&difg7Zed'difg7Zed(difg7Ze�rded)difg7Ze	�rzed*difg7Ze
�r�ed+ejfifg7Ze
�r�ed,difg7Ze�r�ed-difg7Ze�r�ed.difg7Ze�r�ed/difg7Ze�red0dd1d2ifg7ZgZe�r"eddifg7Znedejfifg7Ze
�rRed+ejd3fifg7Ze	�r�e�rved*ejd4fifg7Zned*ejfifg7Ze
�r�ed,e�gfifg7Zd5ejfifd6difd7difd8difd9difgZe�red5ejfifg7Zed5ejfifg7ZeeeeZd:d;�ZdEd<d=�Zd>d?�Z e!d@dA��Z"e!dBdC��Z#dDS)FrNaA container that lists all Process class method names + some
    reasonable parameters to be called with. Utility methods (parent(),
    children(), ...) are excluded.

    >>> ns = process_namespace(psutil.Process())
    >>> for fun, name in ns.iter(ns.getters):
    ...    fun()
    �cpu_percentr�Zmemory_percentr�r<r;T�connectionsr�Zmemory_info_exZoneshotr�parentsr�r��rr��	cpu_timesZcreate_timer�r�r�Zmemory_infor��net_connections�kindr��niceZnum_ctx_switchesZnum_threadsZ
open_filesr�rr��usernameZuids�gidsZterminalr�r�r�r�r�r�r�r�r�ZgroupedF)r�irr)r�r�rBr�cCs
||_dSr�)�_proc)r�r&r�r�r�r�szprocess_namespace.__init__ccs`t|�}t�|�|D]D\}}}|r,|��t|j|�}tj|g|�Ri|��}||fVqdS�z_Given a list of tuples yields a set of (fun, fun_name) tuples
        in random order.
        N)rr,�shuffler�r�r9r�ri)r��lsr��fun_namer�r�r�r�r�r�r�s
zprocess_namespace.itercCs|jj|jjdd�dS)z&Clear the cache of a Process instance.T)Z_ignore_nspN)r9�_initr�r�r�r�r�r�&szprocess_namespace.clear_cachecCs>|D]4\}}}d|}t||�sd|jj|f}t|��qdS)z}Given a TestCase instance and a list of tuples checks that
        the class defines the required test method names.
        Ztest_z$%r class should define a '%s' methodN)rMr�r��AttributeError)r�Z
test_classr<r=r�	meth_namer�r�r�r��test_class_coverage*s
�z%process_namespace.test_class_coveragecCs`tdd�|jD��}tdd�|jD��}tdd�ttj�D��}||B|A}|r\td|��dS)NcSsg|]}|d�qSr2r�r�r�r�r�r�:rz*process_namespace.test.<locals>.<listcomp>cSsg|]}|d�qSr2r�r�r�r�r�r�;rcSsg|]}|ddkr|�qS)rrr�r�r�r�r�r�<rz!uncovered Process class names: %r)r�r��ignoredr�r�r�r�)r��thisrB�klassZleftoutr�r�r��test8szprocess_namespace.testN)T)$r�r�r�r��utilsrB�gettersrr1r2r5r�Z
RLIMIT_NOFILEr.r4r0r
r3ZsettersZNORMAL_PRIORITY_CLASSrZIOPRIO_CLASS_NONEZ
IOPRIO_NORMALr.r'�SIGTERMZkillersZCTRL_C_EVENTZCTRL_BREAK_EVENTr�r�r�r�r�rArEr�r�r�r�rN�s�	���



rNc@s�eZdZdZddifddddifddddifddifd	dd
difd	dd
difddddifd
dddifde��fifddddifddifddifddddifde��fifddifddifddifddifgZer�e	r�e
��dkr�neddd
difg7Ze�reddifg7Ze
�r"eddifg7Ze�r8eddifg7Ze�rNed difg7Ze�rted!difg7Zed"d#ifg7Zd$difd%e��gfifd&difd'difgZeZed(d)��ZejZd*S)+rOz�A container that lists all the module-level, system-related APIs.
    Utilities such as cpu_percent() are excluded. Usage:

    >>> ns = system_namespace
    >>> for fun, name in ns.iter(ns.getters):
    ...    fun()
    rr�r��logicalFTZ	cpu_statsr3ZpercpuZdisk_io_countersZperdiskZdisk_partitionsr��
disk_usager4r5Znet_if_addrsZnet_if_statsr�Zpernicr7r^rZusersr�arm64r�r�r�r�r�Zwin_service_iterZwin_service_get)�algr�r>r/Zcpu_times_percentccsRt|�}t�|�|D]6\}}}tt|�}tj|g|�Ri|��}||fVqdSr:)rr,r;r�r�r�ri)r<r=r�r�r�r�r�r�r�ys

zsystem_namespace.iterN)r�r�r�r�r�r�rrGr/rrtr	�HAS_GETLOADAVGr9r8r6r
r�r�rBr�r�r�rNrAr�r�r�r�rOBsX	��
rOcCsdd�}ttd||d�S)zZDecorator which runs a test function and retries N times before
    actually failing.
    cSstd|tjd�dS)Nz%r, retryingr�)r�r|r�)rZr�r�r�rW�sz retry_on_failure.<locals>.logfunN)rTrrUrW)rSr�)rUrWr�r�r�rK�s�rKcs�fdd�}|S)z,Decorator to Ignore AccessDenied exceptions.cst�����fdd��}|S)NcsBz�|i|��WStjy<�dur.�s.�t�d��Yn0dS)Nzraises AccessDenied)r�r�rzr{r��r��only_ifr�r�r��sz9skip_on_access_denied.<locals>.decorator.<locals>.wrapperr�r��rOr�r�r\�s	z(skip_on_access_denied.<locals>.decoratorr��rOr\r�rPr�rI�s
rIcs�fdd�}|S)z3Decorator to Ignore NotImplementedError exceptions.cst�����fdd��}|S)NcsJz�|i|��WStyD�dur,�s,�d�j}t�|��Yn0dS)Nz4%r was skipped because it raised NotImplementedError)rBr�rzr{)r�r�r�rNr�r�r��s��z;skip_on_not_implemented.<locals>.decorator.<locals>.wrapperr�r�rPr�r�r\�s
z*skip_on_not_implemented.<locals>.decoratorr�rQr�rPr�rJ�srJ�	127.0.0.1cCsLt�t����*}|�|df�|��dWd�S1s>0YdS)z6Return an unused TCP port. Subject to race conditions.rrAN)r��closing�socket�bind�getsockname)�hostr
r�r�r�r_�sr_cCs�|dur|ttfvrd}t�||�}z@tjdvrB|�tjtjd�|�|�|tj	kr`|�
d�|WSty�|���Yn0dS)zBinds a generic socket.N�r@r)�nt�cygwinrAr�)
rrrTr�r��
setsockopt�
SOL_SOCKET�SO_REUSEADDRrUr�listenr�r)�family�type�addrr
r�r�r�r`�s



r`cCsptjs
J�tj�|�rJ|��t�tj|�}z"|�|�|tjkrL|�	d�Wnt
yj|���Yn0|S)zBind a UNIX socket.r�)r�rr�r�r�rTr�rUrr^r�r)r�r`r
r�r�r�ra�s


rarXc	Cs�t�t�|t����}|�|�|�d�|��}t�|t�}zL|�|�|��}|��\}}||kr|||fWWd�S|�	�qPWnt
y�|�	��Yn0Wd�n1s�0YdS)z^Build a pair of TCP sockets connected to each other.
    Return a (server, client) tuple.
    r�N)r�rSrTrrUr^rV�connectrrr.)r_raZllrFZcaddr�ar�r�r�rb�s


rbcCs�tjs
J�d}}z@t|tjd�}|�d�t�tjtj�}|�d�|�|�Wn4ty�|durp|�	�|dur�|�	��Yn0||fS)z�Build a pair of UNIX sockets connected to each other through
    the same UNIX file name.
    Return a (server, client) tuple.
    N�r`r)
r�rrarTr�setblockingr�rbr�r)r��server�clientr�r�r�rcs


rcc	cs g}d}}z�|�ttjtj��|�ttjtj��t�rd|�ttjtj��|�ttjtj��tr�t	r�t
�}t
�}t|�\}}t|tjd�}|||fD]}|�|�q�|VW|D]}|�
�q�||fD]}|dur�t|�q�n6|D]}|�
�q�||fD]}|du�rt|��q0dS)z1Open as many socket families / types as possible.Nrd)r�r`rTrr�
SOCK_DGRAMrrrr:rWrcrarrT)�socksZfname1Zfname2�s1�s2Zs3r�rbr�r�r�rds4
�

rdcCsddl}tr(tr(ts(t|tj�s(J|��|tjkr�dd�|�d�D�}t	|�dksZJ|��|D]"}d|krvdks^nJ|��q^ts�t
|�}|�|�nd|tjkr�t|t
�s�J|��ts�t
|�}|�|�n0|tjkr�t�d|�dus�J|��ntd	|��dS)
z[Check a net address validity. Supported families are IPv4,
    IPv6 and MAC addresses.
    rNcSsg|]}t|��qSr�)rxr�r�r�r�r�>rz%check_net_address.<locals>.<listcomp>rlr��z([a-fA-F0-9]{2}[:|\-]?){6}zunknown family %r)�	ipaddress�enumrr"r�IntEnumrTrryrEr�IPv4Addressrr�IPv6Addressr�ZAF_LINKrNr�r�)rar_rmZocts�numr�r�r�r]5s&
 

r]cCsTdd�}dd�}dd�}dd�}d	d
�}||�||�||�||�||�dS)z*Check validity of a connection namedtuple.cSs�t|�dk}t|�dvs$Jt|���|d|jks<J|j��|d|jksTJ|j��|d|jkslJ|j��|d|jks�J|j��|d|jks�J|j��|d|jks�J|j��|r�|d	|jks�J|j��dS)
Nr�)r-r�rrArmr�r�r�r-)rEr�r_r`�laddr�raddrrr�)rZhas_pidr�r�r��check_ntupleSsz-check_connection_ntuple.<locals>.check_ntuplecSs
|jtttfvsJ|j��tdur:t|jtj�sNJ|��nt|jt�sNJ|��|jtkr�t�|j|j	�}t
�|��^z|�|j
ddf�Wn4tjy�}z|jtjkr��WYd}~n
d}~00Wd�n1s�0Yn$|jtk�r|jtjk�sJ|j��dSr�)r_rrr�rnrrorxrTr`r�rSrUrs�errorr0Z
EADDRNOTAVAILrr��	CONN_NONE)rr�r1r�r�r��check_family_s
8z-check_connection_ntuple.<locals>.check_familycSs�ttdt��}|jtjtj|fvs,J|j��tdurLt|jtj�s`J|��nt|jt	�s`J|��|jtjkr�|j
tjks�J|j
��dS)N�SOCK_SEQPACKET)
r�rT�objectr`rrhrnrrorxrr�rw)rryr�r�r��
check_typets��z+check_connection_ntuple.<locals>.check_typecSs�|j|jfD]�}|jttfvr�t|t�s4Jt|���|s:qt|jt	�sTJt|j���d|jkrjdksvnJ|j��t
|j|j�q|jtkrt|t
�sJt|���qdS)Nri��)rsrtr_rrrrvr`�portrxr]�ipr�r)rrar�r�r��check_addrs�s"
z,check_connection_ntuple.<locals>.check_addrscSs�t|jt�sJ|j��dd�tt�D�}|j|vs<J|j��|jttfvrl|jt	krl|jtj
ks�J|j��n|jtj
ks�J|j��dS)NcSs g|]}|�d�rtt|��qS)ZCONN_r�r�r�r�r�r��szAcheck_connection_ntuple.<locals>.check_status.<locals>.<listcomp>)rrrr�r�r_rrr`rrw)rZvalidsr�r�r��check_status�s�z-check_connection_ntuple.<locals>.check_statusNr�)rrurxr{r~rr�r�r��check_connection_ntuplePs
r�cCsLg}|D]>}tr<|jtjkr<tr<d|jvr<tdt|��q|�|�q|S)ztOur process may start with some open UNIX sockets which are not
    initialized by us, invalidating unit tests.
    z/syslogzskipping %s)	rr_rTr�rrtrrr�)Zcons�newrr�r�r�r^�sr^cCsNzddl}t|d�st�Wn$ty>ddl}|�|�YS0|�|�SdS)z,Backport of importlib.reload of Python 3.3+.rN�reload)�	importlibrMr�impr�)�moduler�r�r�r�r�re�s
recCsptj�tj�|��d}tjddkr:ddl}|�||�Sddl}|j	�
||�}|j	�|�}|j�
|�|SdS)Nrr�)r�r��splitextr�r|r�r�Zload_source�importlib.util�util�spec_from_file_location�module_from_spec�loader�exec_module)r�r�r�r��spec�modr�r�r�rf�srfcCstj|tdd�dS)zRaise a warning msg.rmr�N)r�rgr�)r�r�r�r�rg�srgcCsVt|�}|j}t|�dks&|dtur*dSt|dd�}t|t�sDdStdd�|D��S)z-Check if object is an instance of namedtuple.rArF�_fieldsNcss|]}t|t�VqdSr�)rr)r��nr�r�r��	<genexpr>�rz is_namedtuple.<locals>.<genexpr>)r`�	__bases__rErvr�rr�)r��t�brr�r�r�ri�s
ric#s|trdnd�d�t|�d�}��fdd�t����D�}t�|�}t�||�zt	�
|�|VWt|�n
t|�0dS)z�Ctx manager which picks up a random shared CO lib used
        by this process, copies it in another location and loads it
        in memory via ctypes. Return the new absolutized path.
        �pypyr�z.sorxcs6g|].}tj�|j�d�kr�|j��vr|j�qS)rA)r�r�r��lowerr��r��extr�r�r��s$��'copyload_shared_lib.<locals>.<listcomp>N)r"rWr�r�r�r,r-rjrt�ctypes�CDLLrT)ry�dst�libsrr�r�r�rh�s
�

rhc	#sddlm}ddlm}d�t|�d�}�fdd�t����D�}trb|sbdd�t����D�}t�	|�}t
�||�d	}zPt�|�}|VW|d	ur�tj
jj}|jg|_||j�}|dkr�|�t|�nB|d	u�rtj
jj}|jg|_||j�}|dk�r|�t|�0d	S)
z�Ctx manager which picks up a random shared DLL lib used
        by this process, copies it in another location and loads it
        in memory via ctypes.
        Return the new absolutized, normcased path.
        r)�WinError)�wintypesz.dllrxcsFg|]>}|j�����rdtj�|j���vrd|j��vr|j�qS)r�Zwow64)r�r�r r�r�r��r�r�r�r�s
�r�cSs(g|] }dtj�|j���vr|j�qS)r�)r�r�r�r�r�r�r�r�r�s�N)r�r�r�rWr�r�r�r"r,r-rjrt�WinDLL�windllZkernel32�FreeLibraryZHMODULE�argtypes�_handlerT)	ryr�r�r�r�r�cfiler�rdr�r�r�rhs>

�
�





�




cCstdd�dS)NTr:)rCr�r�r�r��cleanup_test_procs7sr�cCs
t�|�Sr�)r|�exit)r+rr�r�r�rArr)N)F)TF)N)r@N)N)N)rR)rX)r@)r@)�r��
__future__rrrr�r�r0r�r�r�rtr,rNrrrjr'rTrfrzr|r}r�r�r�rHr�rrrrzrr�rrrr	r
rrr
Zpsutil._commonrrrrrZpsutil._compatrrrrrrrr�catch_warnings�simplefilterrnZ	unittest2Zpsutil._psposixr�__all__�builtin_module_namesr"r�rrjr*r=r@rrrar?�maxsizer-r	r>r�r;r<r!r r,rr�rr'r(�decoder)rr�ZASCII_FSr�r�r�rp�__file__r%�getr&r�rMr�r.r/r0rMr2r3r:ZHAS_NET_IO_COUNTERSr4r1r5r6r�r�r7r�r8r9ZHAS_THREADS�getuidZSKIP_SYSCONSr�r#r$�devnullrrsrr�r+r�rzr�r�r�r�r�rGr�rDrFrErAr#rHrBrCrYrXrSr$r[r�r\rZrTror�rSrUrVrWrRr�rMr�r�rLrPrQr.rNrOrKrIrJr_r`rarbrcrdr]r�r^rerfrgrirhr�r�r�r�r��<module>s�


.
-





.


��






*
�0)
&-

V
%;�
	��
"



M
%l	F




R3
PKok\�����\�\5psutil/tests/__pycache__/test_memleaks.cpython-39.pycnu�[���a

��?h3<�@sdZddlmZddlZddlZddlZddlZddlZddlmZddlm	Z	ddlm
Z
ddlmZddlmZdd	lm
Z
dd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%dd lm&Z&dd!lm'Z'ej(j)Z)e�*�Z+d"Z,d#d$�Z-Gd%d&�d&e�Z.Gd'd(�d(e.�Z/e#j0j1e
d)d*�Gd+d,�d,e��Z2Gd-d.�d.e�Z3dS)/a�Tests for detecting function memory leaks (typically the ones
implemented in C). It does so by calling a function many times and
checking whether process memory usage keeps increasing between
calls or over time.
Note that this may produce false positives (especially on Windows
for some reason).
PyPy appears to be completely unstable for this framework, probably
because of how its JIT handles memory, so tests are skipped.
�)�print_functionN)�LINUX)�MACOS)�OPENBSD)�POSIX)�SUNOS)�WINDOWS)�ProcessLookupError)�super)�HAS_CPU_AFFINITY)�HAS_CPU_FREQ)�HAS_ENVIRON)�
HAS_IONICE)�HAS_MEMORY_MAPS)�HAS_NET_IO_COUNTERS)�HAS_PROC_CPU_NUM)�HAS_PROC_IO_COUNTERS)�
HAS_RLIMIT)�HAS_SENSORS_BATTERY)�HAS_SENSORS_FANS)�HAS_SENSORS_TEMPERATURES)�	QEMU_USER)�TestMemoryLeak)�create_sockets)�
get_testfn)�process_namespace)�pytest)�skip_on_access_denied)�spawn_testproc)�system_namespace)�	terminate�cCsdd�}|S)zsDecorator for those Linux functions which are implemented in pure
    Python, and which we want to run faster.
    cst����fdd��}|S)Ncs\trB|jj}z(t|j_�|g|�Ri|��W||j_S||j_0n�|g|�Ri|��SdS�N)r�	__class__�times�	FEW_TIMES)�self�args�kwargs�before��fun��F/usr/local/lib64/python3.9/site-packages/psutil/tests/test_memleaks.py�wrapperDs�z5fewtimes_if_linux.<locals>.decorator.<locals>.wrapper)�	functools�wraps)r+r.r,r*r-�	decoratorCsz$fewtimes_if_linux.<locals>.decoratorr,)r1r,r,r-�fewtimes_if_linux>sr2c@s0eZdZdZeZdd�Ze�dd��Ze�dd��Z	e�dd	��Z
e�d
d��Zej
jedd
�e�dd���Zej
jedd
�e�dd���Ze�dd��Zdd�Zdd�Zej
jedd
�dd��Zej
jedd
�dd��Zej
jedd
�e�dd���Zej
jedd
�d d!��Ze�d"d#��Ze�eed$�d%d&���Zej
jed'd
�d(d)��Z ej
jedd
�e�d*d+���Z!e�d,d-��Z"e�eed$�d.d/���Z#e�d0d1��Z$e�ej
je%dd
�d2d3���Z&e�d4d5��Z'e�d6d7��Z(ej
jedd
�e�d8d9���Z)d:d;�Z*e�d<d=��Z+ej
je,dd
�d>d?��Z-ej
je,dd
�d@dA��Z.e�dBdC��Z/ej
je0dd
�e�dDdE���Z1ej
je2dFd
�ej
je3dd
�dGdH���Z4ej
je2dFd
�ej
je3dd
�dIdJ���Z5e�ej
jedKd
�dLdM���Z6ej
je7dd
�dNdO��Z8ej
jed'd
�dPdQ��Z9dRS)S�TestProcessObjectLeaksz$Test leaks of Process class methods.cCs td�}|�||j|j�dSr")r�test_class_coverageZgettersZsetters�r&�nsr,r,r-�
test_coverage_sz$TestProcessObjectLeaks.test_coveragecCs|�|jj�dSr")�execute�proc�name�r&r,r,r-�	test_namecsz TestProcessObjectLeaks.test_namecCs|�|jj�dSr")r8r9Zcmdliner;r,r,r-�test_cmdlinegsz#TestProcessObjectLeaks.test_cmdlinecCs|�|jj�dSr")r8r9Zexer;r,r,r-�test_exekszTestProcessObjectLeaks.test_execCs|�|jj�dSr")r8r9Zppidr;r,r,r-�	test_ppidosz TestProcessObjectLeaks.test_ppidz
POSIX only��reasoncCs|�|jj�dSr")r8r9Zuidsr;r,r,r-�	test_uidsssz TestProcessObjectLeaks.test_uidscCs|�|jj�dSr")r8r9�gidsr;r,r,r-�	test_gidsxsz TestProcessObjectLeaks.test_gidscCs|�|jj�dSr")r8r9�statusr;r,r,r-�test_status}sz"TestProcessObjectLeaks.test_statuscCs|�|jj�dSr")r8r9�nicer;r,r,r-�	test_nice�sz TestProcessObjectLeaks.test_nicecs t�������fdd��dS)Ncs�j���Sr")r9rGr,�Znicenessr&r,r-�<lambda>��z6TestProcessObjectLeaks.test_nice_set.<locals>.<lambda>)�thisprocrGr8r;r,rIr-�
test_nice_set�sz$TestProcessObjectLeaks.test_nice_set�
not supportedcCs|�|jj�dSr")r8r9�ionicer;r,r,r-�test_ionice�sz"TestProcessObjectLeaks.test_ionicecsZtr"t�������fdd��n4���fdd��t�tjt�	�dd�}��
t|�dS)Ncs�j���Sr")r9rOr,�r&�valuer,r-rJ�rKz8TestProcessObjectLeaks.test_ionice_set.<locals>.<lambda>cs�j�tj�Sr")r9rO�psutilZIOPRIO_CLASS_NONEr,r;r,r-rJ�rK���r)rrLrOr8r/�partial�cextZproc_ioprio_set�os�getpid�
execute_w_exc�OSError�r&r+r,rQr-�test_ionice_set�sz&TestProcessObjectLeaks.test_ionice_setcCs|�|jj�dSr")r8r9Zio_countersr;r,r,r-�test_io_counters�sz'TestProcessObjectLeaks.test_io_counterszworthless on POSIXcCst����|�|jj�dSr")rS�Process�usernamer8r9r;r,r,r-�
test_username�sz$TestProcessObjectLeaks.test_usernamecCs|�|jj�dSr")r8r9Zcreate_timer;r,r,r-�test_create_time�sz'TestProcessObjectLeaks.test_create_time)Zonly_ifcCs|�|jj�dSr")r8r9Znum_threadsr;r,r,r-�test_num_threads�sz'TestProcessObjectLeaks.test_num_threads�WINDOWS onlycCs|�|jj�dSr")r8r9Znum_handlesr;r,r,r-�test_num_handles�sz'TestProcessObjectLeaks.test_num_handlescCs|�|jj�dSr")r8r9Znum_fdsr;r,r,r-�test_num_fds�sz#TestProcessObjectLeaks.test_num_fdscCs|�|jj�dSr")r8r9Znum_ctx_switchesr;r,r,r-�test_num_ctx_switches�sz,TestProcessObjectLeaks.test_num_ctx_switchescCs|�|jj�dSr")r8r9�threadsr;r,r,r-�test_threads�sz#TestProcessObjectLeaks.test_threadscCs|�|jj�dSr")r8r9�	cpu_timesr;r,r,r-�test_cpu_times�sz%TestProcessObjectLeaks.test_cpu_timescCs|�|jj�dSr")r8r9Zcpu_numr;r,r,r-�test_cpu_num�sz#TestProcessObjectLeaks.test_cpu_numcCs|�|jj�dSr")r8r9Zmemory_infor;r,r,r-�test_memory_info�sz'TestProcessObjectLeaks.test_memory_infocCs|�|jj�dSr")r8r9Zmemory_full_infor;r,r,r-�test_memory_full_info�sz,TestProcessObjectLeaks.test_memory_full_infocCs|�|jj�dSr")r8r9Zterminalr;r,r,r-�
test_terminal�sz$TestProcessObjectLeaks.test_terminalcCs$trtn|j}|j|jj|d�dS)N�r$)rr%r$r8r9�resume�r&r$r,r,r-�test_resume�sz"TestProcessObjectLeaks.test_resumecCs|�|jj�dSr")r8r9�cwdr;r,r,r-�test_cwd�szTestProcessObjectLeaks.test_cwdcCs|�|jj�dSr")r8r9�cpu_affinityr;r,r,r-�test_cpu_affinity�sz(TestProcessObjectLeaks.test_cpu_affinitycs4t�������fdd����t�fdd��dS)Ncs�j���Sr"�r9rur,�Zaffinityr&r,r-rJ�rKz>TestProcessObjectLeaks.test_cpu_affinity_set.<locals>.<lambda>cs�j�dg�S�NrTrwr,r;r,r-rJ�rK)rLrur8rY�
ValueErrorr;r,rxr-�test_cpu_affinity_set�sz,TestProcessObjectLeaks.test_cpu_affinity_setcCs>tt�d��|�|jj�Wd�n1s00YdS)N�w)�openrr8r9Z
open_filesr;r,r,r-�test_open_files�sz&TestProcessObjectLeaks.test_open_filescCs|�|jj�dSr")r8r9Zmemory_mapsr;r,r,r-�test_memory_maps�sz'TestProcessObjectLeaks.test_memory_mapsz
LINUX onlycs���fdd��dS)Ncs�j�tj�Sr"�r9�rlimitrS�
RLIMIT_NOFILEr,r;r,r-rJ�rKz4TestProcessObjectLeaks.test_rlimit.<locals>.<lambda>�r8r;r,r;r-�test_rlimit�sz"TestProcessObjectLeaks.test_rlimitcs<t�tj������fdd����ttf�fdd��dS)Ncs�j�tj��Sr"r�r,��limitr&r,r-rJ�rKz8TestProcessObjectLeaks.test_rlimit_set.<locals>.<lambda>cs�j�d�Sry)r9r�r,r;r,r-rJ�rK)rLr�rSr�r8rYrZrzr;r,r�r-�test_rlimit_set�sz&TestProcessObjectLeaks.test_rlimit_setzworthless on WINDOWScsJt��0trdnd�����fdd��Wd�n1s<0YdS)NZinet�allcs�j���Sr")r9�net_connectionsr,��kindr&r,r-rJrKz=TestProcessObjectLeaks.test_net_connections.<locals>.<lambda>)rrr8r;r,r�r-�test_net_connections�sz+TestProcessObjectLeaks.test_net_connectionscCs|�|jj�dSr")r8r9�environr;r,r,r-�test_environsz#TestProcessObjectLeaks.test_environcCs|�dd��dS)NcSst�t���Sr")rV�	proc_inforWrXr,r,r,r-rJrKz7TestProcessObjectLeaks.test_proc_info.<locals>.<lambda>r�r;r,r,r-�test_proc_info
sz%TestProcessObjectLeaks.test_proc_infoN):�__name__�
__module__�__qualname__�__doc__rLr9r7r2r<r=r>r?r�mark�skipifrrBrDrFrHrMrrPr\rr]r`rarrrbrrdrerfrhrjrrkrlrmrnrrrtrrvr{r~rrrrr�r�r�r
r�r�r,r,r,r-r3Zs�






	











r3cspeZdZdZe�fdd��Ze�fdd��Zdd�Zerhdd	�Z	d
d�Z
dd
�Zdd�Zdd�Z
dd�Z�ZS)�TestTerminatedProcessLeaksz�Repeat the tests above looking for leaks occurring when dealing
    with terminated processes raising NoSuchProcess exception.
    The C functions are still invoked but will follow different code
    paths. We'll check those code paths.
    cs:t���t�|_t�|jj�|_|j��|j�	�dSr")
r
�
setUpClassr�subprSr^�pidr9�kill�wait��cls�r#r,r-r�s


z%TestTerminatedProcessLeaks.setUpClasscst���t|j�dSr")r
�
tearDownClassr r�r�r�r,r-r�s
z(TestTerminatedProcessLeaks.tearDownClasscCs$z
|�WntjyYn0dSr")rSZ
NoSuchProcessr[r,r,r-�call#s
zTestTerminatedProcessLeaks.callcCs|�|jj�dSr")r8r9r�r;r,r,r-�	test_kill+sz$TestTerminatedProcessLeaks.test_killcCs|�|jj�dSr")r8r9r r;r,r,r-�test_terminate.sz)TestTerminatedProcessLeaks.test_terminatecCs|�|jj�dSr")r8r9Zsuspendr;r,r,r-�test_suspend1sz'TestTerminatedProcessLeaks.test_suspendcCs|�|jj�dSr")r8r9rpr;r,r,r-rr4sz&TestTerminatedProcessLeaks.test_resumecCs|�|jj�dSr")r8r9r�r;r,r,r-�	test_wait7sz$TestTerminatedProcessLeaks.test_waitcs�fdd�}��|�dS)Ncs(zt��jj�WSty"Yn0dSr")rVr�r9r�r	r,r;r,r-r�<sz7TestTerminatedProcessLeaks.test_proc_info.<locals>.callr�)r&r�r,r;r-r�:sz)TestTerminatedProcessLeaks.test_proc_info)r�r�r�r��classmethodr�r�r�rr�r�r�rrr�r��
__classcell__r,r,r�r-r�sr�rcr@c@seZdZdd�Zdd�ZdS)�TestProcessDualImplementationcCs|�dd��dS)NcSstjt��dd�S)NT�Zuse_peb�rVZproc_cmdlinerWrXr,r,r,r-rJHrKzETestProcessDualImplementation.test_cmdline_peb_true.<locals>.<lambda>r�r;r,r,r-�test_cmdline_peb_trueGsz3TestProcessDualImplementation.test_cmdline_peb_truecCs|�dd��dS)NcSstjt��dd�S)NFr�r�r,r,r,r-rJKrKzFTestProcessDualImplementation.test_cmdline_peb_false.<locals>.<lambda>r�r;r,r,r-�test_cmdline_peb_falseJsz4TestProcessDualImplementation.test_cmdline_peb_falseN)r�r�r�r�r�r,r,r,r-r�Esr�c@sPeZdZdZdd�Ze�dd��Ze�dd��Ze�dd	��Ze�d
d��Z	e�dd
��Z
e�ejj
eore��dkdd�ejj
edd�dd����Zejj
edd�dd��Zdd�Zejj
edd�dd��Zdd�Zdd�Zejj
ed d�d!d"��Zejj
e�oej�d#�d$d�e�d%d&���Z e�d'd(��Z!e�ejj
e"dd�d)d*���Z#e�ejj
e�one�$�d+kd,d�d-d.���Z%d/d0�Z&ejj
ed d�d1d2��Z'e�ejj
e(dd�d3d4���Z)e�ejj
e*dd�d5d6���Z+e�ejj
e,dd�d7d8���Z-e�d9d:��Z.d;d<�Z/d=d>�Z0e�rLd?d@�Z1dAdB�Z2dCdD�Z3dEdF�Z4dGdH�Z5dIS)J�TestModuleFunctionsLeaksz&Test leaks of psutil module functions.cCst�}|�||j�dSr")rr4r�r5r,r,r-r7Vsz&TestModuleFunctionsLeaks.test_coveragecCs|�dd��dS)NcSstjdd�S)NT��logical�rS�	cpu_countr,r,r,r-rJ^rKz9TestModuleFunctionsLeaks.test_cpu_count.<locals>.<lambda>r�r;r,r,r-�test_cpu_count\sz'TestModuleFunctionsLeaks.test_cpu_countcCs|�dd��dS)NcSstjdd�S)NFr�r�r,r,r,r-rJbrKz?TestModuleFunctionsLeaks.test_cpu_count_cores.<locals>.<lambda>r�r;r,r,r-�test_cpu_count_cores`sz-TestModuleFunctionsLeaks.test_cpu_count_corescCs|�tj�dSr")r8rSrir;r,r,r-rjdsz'TestModuleFunctionsLeaks.test_cpu_timescCs|�dd��dS)NcSstjdd�S)NT)Zpercpu)rSrir,r,r,r-rJjrKz=TestModuleFunctionsLeaks.test_per_cpu_times.<locals>.<lambda>r�r;r,r,r-�test_per_cpu_timeshsz+TestModuleFunctionsLeaks.test_per_cpu_timescCs|�tj�dSr")r8rSZ	cpu_statsr;r,r,r-�test_cpu_statslsz'TestModuleFunctionsLeaks.test_cpu_stats�arm64zskipped due to #1892r@rNcCs|�tj�dSr")r8rSZcpu_freqr;r,r,r-�
test_cpu_freqpsz&TestModuleFunctionsLeaks.test_cpu_freqrccCst��|�tj�dSr")rS�
getloadavgr8r;r,r,r-�test_getloadavgysz(TestModuleFunctionsLeaks.test_getloadavgcCs|�tj�dSr")r8rSZvirtual_memoryr;r,r,r-�test_virtual_memory�sz,TestModuleFunctionsLeaks.test_virtual_memoryz&worthless on SUNOS (uses a subprocess)cCs|�tj�dSr")r8rSZswap_memoryr;r,r,r-�test_swap_memory�sz)TestModuleFunctionsLeaks.test_swap_memorycCs$trtn|j}|jdd�|d�dS)NcSst�t���Sr")rSZ
pid_existsrWrXr,r,r,r-rJ�rKz:TestModuleFunctionsLeaks.test_pid_exists.<locals>.<lambda>ro�rr%r$r8rqr,r,r-�test_pid_exists�sz(TestModuleFunctionsLeaks.test_pid_existscCs$trtn|j}|jdd�|d�dS)NcSs
t�d�S)N�.)rS�
disk_usager,r,r,r-rJ�rKz:TestModuleFunctionsLeaks.test_disk_usage.<locals>.<lambda>ror�rqr,r,r-�test_disk_usage�sz(TestModuleFunctionsLeaks.test_disk_usagezQEMU user not supportedcCs|�tj�dSr")r8rSZdisk_partitionsr;r,r,r-�test_disk_partitions�sz-TestModuleFunctionsLeaks.test_disk_partitionsz/proc/diskstatsz3/proc/diskstats not available on this Linux versioncCs|�dd��dS)NcSstjdd�S�NF)Znowrap)rSZdisk_io_countersr,r,r,r-rJ�rKz@TestModuleFunctionsLeaks.test_disk_io_counters.<locals>.<lambda>r�r;r,r,r-�test_disk_io_counters�sz.TestModuleFunctionsLeaks.test_disk_io_counterscCs|�tj�dSr")r8rSZpidsr;r,r,r-�	test_pids�sz"TestModuleFunctionsLeaks.test_pidscCs|�dd��dS)NcSstjdd�Sr�)rSZnet_io_countersr,r,r,r-rJ�rKz?TestModuleFunctionsLeaks.test_net_io_counters.<locals>.<lambda>r�r;r,r,r-�test_net_io_counters�sz-TestModuleFunctionsLeaks.test_net_io_countersrzneed root accesscCsDtjdd�t��|�dd��Wd�n1s60YdS)Nr��r�cSstjdd�S)Nr�r�)rSr�r,r,r,r-rJ�rKz?TestModuleFunctionsLeaks.test_net_connections.<locals>.<lambda>)rSr�rr8r;r,r,r-r��sz-TestModuleFunctionsLeaks.test_net_connectionscCs"trdn|j}|jtj|d�dS)Ni@)�	tolerance)rr�r8rSZnet_if_addrs)r&r�r,r,r-�test_net_if_addrs�sz*TestModuleFunctionsLeaks.test_net_if_addrscCs|�tj�dSr")r8rSZnet_if_statsr;r,r,r-�test_net_if_stats�sz*TestModuleFunctionsLeaks.test_net_if_statscCs|�tj�dSr")r8rSZsensors_batteryr;r,r,r-�test_sensors_battery�sz-TestModuleFunctionsLeaks.test_sensors_batterycCs|�tj�dSr")r8rSZsensors_temperaturesr;r,r,r-�test_sensors_temperatures�sz2TestModuleFunctionsLeaks.test_sensors_temperaturescCs|�tj�dSr")r8rSZsensors_fansr;r,r,r-�test_sensors_fans�sz*TestModuleFunctionsLeaks.test_sensors_fanscCs|�tj�dSr")r8rSZ	boot_timer;r,r,r-�test_boot_time�sz'TestModuleFunctionsLeaks.test_boot_timecCs|�tj�dSr")r8rSZusersr;r,r,r-�
test_users�sz#TestModuleFunctionsLeaks.test_userscCs|�dd��dS)NcSs
t�d�S)NF)rSZ
_set_debugr,r,r,r-rJ�rKz9TestModuleFunctionsLeaks.test_set_debug.<locals>.<lambda>r�r;r,r,r-�test_set_debug�sz'TestModuleFunctionsLeaks.test_set_debugcCs|�tj�dSr")r8rVZwinservice_enumerater;r,r,r-�test_win_service_iter�sz.TestModuleFunctionsLeaks.test_win_service_itercCsdSr"r,r;r,r,r-�test_win_service_get�sz-TestModuleFunctionsLeaks.test_win_service_getcs&tt������|��fdd��dS)Ncs
t���Sr")rVZwinservice_query_configr,�r:r,r-rJ�rKzFTestModuleFunctionsLeaks.test_win_service_get_config.<locals>.<lambda>��nextrSZwin_service_iterr:r8r;r,r�r-�test_win_service_get_config�sz4TestModuleFunctionsLeaks.test_win_service_get_configcs&tt������|��fdd��dS)Ncs
t���Sr")rVZwinservice_query_statusr,r�r,r-rJ�rKzFTestModuleFunctionsLeaks.test_win_service_get_status.<locals>.<lambda>r�r;r,r�r-�test_win_service_get_status�sz4TestModuleFunctionsLeaks.test_win_service_get_statuscs&tt������|��fdd��dS)Ncs
t���Sr")rVZwinservice_query_descrr,r�r,r-rJ�rKzKTestModuleFunctionsLeaks.test_win_service_get_description.<locals>.<lambda>r�r;r,r�r-� test_win_service_get_description�sz9TestModuleFunctionsLeaks.test_win_service_get_descriptionN)6r�r�r�r�r7r2r�r�rjr�r�rr�r�r�platform�machinerr�rr�r�rr�r�r�rr�rrW�path�existsr�r�rr��getuidr�r�r�rr�rr�rr�r�r�r�r�r�r�r�r�r,r,r,r-r�Ss~




�


�


r�)4r��
__future__rr/rWr�rSZpsutil._commonrrrrrrZpsutil._compatr	r
Zpsutil.testsrrr
rrrrrrrrrrrrrrrrrrr Z_psplatformrVr^rLr%r2r3r�r�r�r�r�r,r,r,r-�<module>s\
66
PKok\�đ�&>&>8psutil/tests/__pycache__/test_connections.cpython-39.pycnu�[���a

��?hS�@s\dZddlZddlZddlZddlmZddlmZddlmZddlmZddlm	Z	ddl
Z
ddl
mZdd	l
mZdd
l
m
Z
ddl
mZddl
mZdd
l
mZddl
mZddl
mZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%dd lm&Z&dd!lm'Z'e(ed"e)��Z*d#d$�Z+e!j,j-d%d&�Gd'd(�d(e��Z.Gd)d*�d*e.�Z/e!j,j-d%d&�Gd+d,�d,e.��Z0e!j,j-d%d&�Gd-d.�d.e.��Z1Gd/d0�d0e.�Z2e!j,j3ed1d2�Gd3d4�d4e.��Z4Gd5d6�d6e�Z5dS)7zFTests for psutil.net_connections() and Process.net_connections() APIs.�N)�closing)�AF_INET)�AF_INET6)�
SOCK_DGRAM)�SOCK_STREAM)�FREEBSD)�LINUX)�MACOS)�NETBSD)�OPENBSD)�POSIX)�SUNOS)�WINDOWS)�
supports_ipv6)�PY3)�AF_UNIX)�HAS_NET_CONNECTIONS_UNIX)�SKIP_SYSCONS)�PsutilTestCase)�bind_socket)�bind_unix_socket)�check_connection_ntuple)�create_sockets)�filter_proc_net_connections)�pytest)�
reap_children)�retry_on_failure)�skip_on_access_denied)�tcp_socketpair)�unix_socketpair)�
wait_for_file�SOCK_SEQPACKETcCs$t��j|d�}|dvr t|�S|S)N��kind)�all�unix)�psutil�Process�net_connectionsr)r#�cons�r*�I/usr/local/lib64/python3.9/site-packages/psutil/tests/test_connections.py�this_proc_net_connections2sr,�serial)�namec@s&eZdZdd�Zdd�Zd	dd�ZdS)
�ConnectionTestCasecCstdd�gksJ�dS�Nr$r"�r,��selfr*r*r+�setUp;szConnectionTestCase.setUpcCstdd�gksJ�dSr0r1r2r*r*r+�tearDown>szConnectionTestCase.tearDownr$csdztj|d�}Wn tjy0tr*YdS�Yn0�fdd�|D�}|��|��||ks`J�dS)z�Given a process PID and its list of connections compare
        those against system-wide connections retrieved via
        psutil.net_connections.
        r"Ncs"g|]}|j�kr|dd��qS)N�����pid��.0�cr7r*r+�
<listcomp>Q�zBConnectionTestCase.compare_procsys_connections.<locals>.<listcomp>)r&r(ZAccessDeniedr	�sort)r3r8Z	proc_consr#Zsys_consr*r7r+�compare_procsys_connectionsBsz.ConnectionTestCase.compare_procsys_connectionsN)r$)�__name__�
__module__�__qualname__r4r5r?r*r*r*r+r/9sr/c@s4eZdZejjedd�dd��Zdd�Zdd�Z	d	S)
�TestBasicOperations�
requires root��reasoncCsDt��*tjdd�D]}t|�qWd�n1s60YdSr0)rr&r(r�r3�connr*r*r+�test_systemXszTestBasicOperations.test_systemcCsBt��(tdd�D]}t|�qWd�n1s40YdSr0)rr,rrGr*r*r+�test_process^sz TestBasicOperations.test_processcCsnt�t��tdd�Wd�n1s*0Yt�t��tjdd�Wd�n1s`0YdS)Nz???r")rZraises�
ValueErrorr,r&r(r2r*r*r+�test_invalid_kindcs(z%TestBasicOperations.test_invalid_kindN)
r@rArBr�mark�skipifrrIrJrLr*r*r*r+rCWs
rCc@s�eZdZdZdd�Zdd�Zdd�Zejj	e
�dd	�d
d��Zdd
�Zejj	e
�dd	�dd��Z
ejj	edd	�dd��Zejj	edd	�dd��ZdS)�TestUnconnectedSocketsz;Tests sockets which are open but not connected to anything.cCsttdd�}tdd�|D��}ts$tr0||��St|�dks@J�|djdkrh||��j|��kshJ�|dSdS)Nr$r"cSsg|]}|j|f�qSr*)�fdr9r*r*r+r<pr=z=TestUnconnectedSockets.get_conn_from_sock.<locals>.<listcomp>�rr6)r,�dictr
r�fileno�lenrP)r3�sockr)Zsmapr*r*r+�get_conn_from_sockns
z)TestUnconnectedSockets.get_conn_from_sockcCs�|�|�}t|�|jdkr.|j|��ks.J�|j|jks>J�|j|�tjtj	�ksXJ�|�
�}|sztrzt|t
�rz|��}|jtkr�|dd�}|j|ks�J�|jtkr�tr�tdd�}|jt��|dd�|S)z�Given a socket, makes sure it matches the one obtained
        via psutil. It assumes this process created one connection
        only (the one supposed to be checked).
        r6N�r$r")rVrrPrS�family�type�
getsockopt�socket�
SOL_SOCKET�SO_TYPE�getsocknamer�
isinstance�bytes�decoder�laddrrrr,r?�os�getpid)r3rUrHrbr)r*r*r+�check_socket{s 



z#TestUnconnectedSockets.check_socketcCsbd}tttt|d���8}|�|�}|jdks0J�|jtjks@J�Wd�n1sT0YdS�N��	127.0.0.1r��addrr*)	rrrrre�raddr�statusr&�CONN_LISTEN�r3rjrUrHr*r*r+�test_tcp_v4�s

z"TestUnconnectedSockets.test_tcp_v4zIPv6 not supportedrEcCsbd}tttt|d���8}|�|�}|jdks0J�|jtjks@J�Wd�n1sT0YdS�N)�::1rrir*)	rrrrrerkrlr&rmrnr*r*r+�test_tcp_v6�s

z"TestUnconnectedSockets.test_tcp_v6cCsbd}tttt|d���8}|�|�}|jdks0J�|jtjks@J�Wd�n1sT0YdSrf)	rrrrrerkrlr&�	CONN_NONErnr*r*r+�test_udp_v4�s

z"TestUnconnectedSockets.test_udp_v4cCsbd}tttt|d���8}|�|�}|jdks0J�|jtjks@J�Wd�n1sT0YdSrp)	rrrrrerkrlr&rsrnr*r*r+�test_udp_v6�s

z"TestUnconnectedSockets.test_udp_v6�
POSIX onlycCsd|��}tt|td���8}|�|�}|jdks2J�|jtjksBJ�Wd�n1sV0YdS�N)rY��	�
get_testfnrrrrerkrlr&rs�r3�testfnrUrHr*r*r+�
test_unix_tcp�s

z$TestUnconnectedSockets.test_unix_tcpcCsd|��}tt|td���8}|�|�}|jdks2J�|jtjksBJ�Wd�n1sV0YdSrwryr{r*r*r+�
test_unix_udp�s

z$TestUnconnectedSockets.test_unix_udpN)r@rArB�__doc__rVrerorrMrNrrrrtrurr}r~r*r*r*r+rOjs



rOc@sBeZdZdZejjedd�dd��Zejje	dd�dd��Z
d	S)
�TestConnectedSocketzFTest socket pairs which are actually connected to
    each other.
    zunreliable on SUONSrEcCs�d}tdd�gksJ�tt|d�\}}zVtdd�}t|�dksBJ�|djtjksVJ�|djtjksjJ�W|��|��n|��|��0dS)Nrg�tcp4r"rirWrrQ)r,rrrTrlr&ZCONN_ESTABLISHED�close)r3rj�server�clientr)r*r*r+�test_tcp�s

�zTestConnectedSocket.test_tcprvcCs|��}t|�\}}z�tdd�}|djr<|djr<J|��|djrX|djrXJ|��ts`trndd�|D�}t|�dks~J�ts�ts�t	s�t
r�|djdks�J�|djdks�J�||djp�|djks�J�n|djp�|dj|ks�J�W|��|��n|��|��0dS)	Nr%r"rrQcSsg|]}|jdkr|�qS)z/var/run/log)rkr9r*r*r+r<�r=z1TestConnectedSocket.test_unix.<locals>.<listcomp>rWrx)rzrr,rbrkr
rrTrr
rr�)r3r|r�r�r)r*r*r+�	test_unix�s$

�zTestConnectedSocket.test_unixN)r@rArBrrrMrNr
r�rr�r*r*r*r+r��s

r�c@s.eZdZdd�Zeed�dd��Zdd�ZdS)	�TestFilterscCs�dd�}t���|dtttgtttg�|dttgttg�|dtgttg�|dttgtg�|dtgtg�|dtgtg�|d	ttgtg�|d
tgtg�|dtgtg�tr�|dtgtttg�Wd�n1s�0YdS)
NcSsbt|d�D] }|j|vsJ�|j|vs
J�q
ts^tj|d�D] }|j|vsNJ�|j|vs<J�q<dS)Nr")r,rXrYrr&r()r#�families�typesrHr*r*r+�checksz'TestFilters.test_filters.<locals>.checkr$�inet�inet4�tcpr��tcp6�udp�udp4�udp6r%)rrrrrrr!r)r3r�r*r*r+�test_filterss*	��zTestFilters.test_filters)Zonly_ifcs�t��fdd�}t�d�}t�d�}tj��jt��d��}|jt	t
�d|d�}|jt	t
�d|d�}|jt	t�d|d�}|jt	t�d|d�}��|�}	t
t|d	d
��}
��|�}t
t|d	d
��}t�r���|�}
t
t|d	d
��}��|�}t
t|d	d
��}nd}
d}d}d}t����D]�}|��}t|�dk�s8J�|D]�}|j|	jk�rh|||t
t|
dtjd
�n�|j|jk�r�|||t
t|dtjd�nZ|jt|
dd�k�r�|||tt|dtjd�n,|jt|dd�k�r<|||tt|dtjd��q<�qdS)Ncs�d}t|�|j|ksJ�|j|ks(J�|j|ks6J�|j|ksDJ�|j|ksRJ�|D]2}	|j|	d�}
|	|vr||
gks�J�qV|
gksVJ�qVtr���|j	|g�dS)N)
r$r�r��inet6r�r�r�r�r�r�r")
rrXrYrbrkrlr(rr?r8)�procrHrXrYrbrkrl�kindsZ	all_kindsr#r)r2r*r+�
check_conn$sz+TestFilters.test_combos.<locals>.check_conna4
            import socket, time
            s = socket.socket({family}, socket.SOCK_STREAM)
            s.bind(('{addr}', 0))
            s.listen(5)
            with open('{testfn}', 'w') as f:
                f.write(str(s.getsockname()[:2]))
            [time.sleep(0.1) for x in range(100)]
            a
            import socket, time
            s = socket.socket({family}, socket.SOCK_DGRAM)
            s.bind(('{addr}', 0))
            with open('{testfn}', 'w') as f:
                f.write(str(s.getsockname()[:2]))
            [time.sleep(0.1) for x in range(100)]
            )�dirrh)rXrjr|rqT)�deleterQr*)r$r�r�r�r�)r$r�r�r�r�r8)r$r�r�r�r�)r$r�r�r�r�)r�textwrap�dedentrc�path�basenamerz�getcwd�format�intrr�pyrun�evalr rr&r'�childrenr(rTr8rrmrrs�getattr)r3r�Ztcp_templateZudp_templateZtestfileZ
tcp4_templateZ
udp4_templateZ
tcp6_templateZ
udp6_templateZ	tcp4_procZ	tcp4_addrZ	udp4_procZ	udp4_addrZ	tcp6_procZ	tcp6_addrZ	udp6_procZ	udp6_addr�pr)rHr*r2r+�test_combos s�




�
�
�
�



����zTestFilters.test_comboscCs�t����tdd�}t|�t�r$dndks.J�|D]$}|jttfvsHJ�|jtks2J�q2tdd�}t|�dksrJ�|djtks�J�|djtks�J�t�r�tdd�}t|�dks�J�|djtks�J�|djtks�J�tdd�}t|�t�r�dndks�J�|D]*}|jttfv�sJ�|jt	k�sJ��qtd	d�}t|�dk�sJJ�|djtk�s^J�|djt	k�srJ�t��r�td
d�}t|�dk�s�J�|djtk�s�J�|djt	k�s�J�tdd�}t|�t��r�dndk�s�J�|D].}|jttfv�sJ�|jtt	fv�s�J��q�t��rntd
d�}t|�dk�s>J�|D]*}|jtk�sVJ�|jtt	fv�sBJ��qBt
�r�t�s�t�s�tdd�}t|�dk�s�J�|D]*}|jt
k�s�J�|jtt	fv�s�J��q�Wd�n1�s�0YdS)Nr�r"rWrQr�rr�r�r�r�r��r�r%�)rr,rTrrXrrrYrrrrr
r)r3r)rHr*r*r+�
test_count�s\









zTestFilters.test_countN)r@rArBr�rr	r�r�r*r*r*r+r�s

r�rDrEc@s&eZdZdZdd�Ze�dd��ZdS)�TestSystemWideConnectionszTests for net_connections().cCs�dd�}t��rddlm}|��D]L\}}|dkr:ts:q$|\}}t�|�}t|�tt|��ksdJ�||||�q$Wd�n1s�0YdS)NcSs<|D]2}|j|vsJ�|jtkr.|j|vs.J�t|�qdS)N)rXrrYr)r)r��types_rHr*r*r+r��s

z0TestSystemWideConnections.test_it.<locals>.checkr)�	conn_tmapr%)	r�psutil._commonr��itemsrr&r(rT�set)r3r�r�r#�groupsr�r�r)r*r*r+�test_it�s
z!TestSystemWideConnections.test_itcs�t��}t|�}Wd�n1s$0Yg�d}g}t|�D]:}|��}|�|�t�d|�}|�|�}��|j�qB|D]}t	|�q��fdd�t
jdd�D�}	�D]B�t�fdd�|	D��|ks�J�t
���}
t|
�d��|ks�J�q�dS)N�
a"                import time, os
                from psutil.tests import create_sockets
                with create_sockets():
                    with open(r'%s', 'w') as f:
                        f.write("hello")
                    [time.sleep(0.1) for x in range(100)]
                csg|]}|j�vr|�qSr*r7�r:�x)�pidsr*r+r<szFTestSystemWideConnections.test_multi_sockets_procs.<locals>.<listcomp>r$r"csg|]}|j�kr|�qSr*r7r�r7r*r+r<!r=)
rrT�rangerz�appendr�r�r�r8r r&r(r')r3�socks�expected�times�fnames�_�fname�srcZsprocZsysconsr�r*)r8r�r+�test_multi_sockets_procs�s,&
�



�
z2TestSystemWideConnections.test_multi_sockets_procsN)r@rArBrr�rr�r*r*r*r+r��sr�c@seZdZdd�ZdS)�TestMisccCs�g}g}tt�D]\}|�d�rtt|�}t|�}|��s@J|��t|vsLJ�||vsXJ�|�|�|�|�qtr~tjtj	t
r�tjdS)NZCONN_)r�r&�
startswithr��str�isupperr�r
Z	CONN_IDLEZ
CONN_BOUNDrZCONN_DELETE_TCB)r3Zints�strsr.�numZstr_r*r*r+�test_net_connection_constants's 


z&TestMisc.test_net_connection_constantsN)r@rArBr�r*r*r*r+r�&sr�)6rrcr[r��
contextlibrrrrrr&rrr	r
rrr
rr�rZpsutil._compatrZpsutil.testsrrrrrrrrrrrrrrrr r��objectr!r,rMZxdist_groupr/rCrOr�r�rNr�r�r*r*r*r+�<module>sb]7g?PKok\����7�72psutil/tests/__pycache__/test_posix.cpython-39.pycnu�[���a

��?hD�@s�dZddlZddlZddlZddlZddlZddlZddlZddlmZddlm	Z	ddlm
Z
ddlmZddlmZddlm
Z
dd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZe
�rNddlZddlZddlm Z d,dd�Z!dd�Z"dd�Z#dd�Z$d d!�Z%d"d#�Z&ej'j(e
d$d%�Gd&d'�d'e��Z)ej'j(e
d$d%�Gd(d)�d)e��Z*ej'j(e
d$d%�Gd*d+�d+e��Z+dS)-zPOSIX specific tests.�N)�AIX)�BSD)�LINUX)�MACOS)�OPENBSD)�POSIX)�SUNOS)�AARCH64)�HAS_NET_IO_COUNTERS)�
PYTHON_EXE)�	QEMU_USER)�PsutilTestCase)�mock)�pytest)�retry_on_failure)�sh)�skip_on_access_denied)�spawn_testproc)�	terminate)�which)�getpagesizec	Cs�dg}tr|�d�|dur0|�dt|�g�nts8trD|�d�n
|�d�tr^|�dd�}|�d	|g�t|�}tr�|��n|��d
d�}g}|D]6}|�	�}zt
|�}Wnty�Yn0|�|�q�|dur�|S|dSdS)zwWrapper for calling the ps command with a little bit of cross-platform
    support for a narrow range of features.
    �psz--no-headersNz-pz-A�ax�startZstimez-o�r)r�append�extend�strrr�replacer�
splitlines�strip�int�
ValueError)�fmt�pid�cmd�output�
all_output�line�r)�C/usr/local/lib64/python3.9/site-packages/psutil/tests/test_posix.pyr/s0

rcCs>d}trd}t||���}tr6d|dvs.J�|dS|dS)N�commandZcommz
/bin/qemu-rr)rr�splitr)r$�fieldr+r)r)r*�ps_namegsr.cCs0d}tstrd}t||�}t�dd|�}|��S)Nr+�argsz\(python.*?\)$�)rrr�re�subr )r$r-�outr)r)r*�ps_argsrs
r4cCsd}trd}t||�S)NZrssZrssize�rr�r$r-r)r)r*�ps_rss|sr7cCsd}trd}t||�S)NZvszZvsizer5r6r)r)r*�ps_vsz�sr8c	
Cs�ztd|���}Wn@tyT}z(dt|���vr>t�d���WYd}~n
d}~00|�d�d}|��}t|d�d}t|d�d}t|d�d}t	|d	�
d
d��}||||fS)Nzdf -k %szdevice busyzdf returned EBUSY�
r�����%r0)rr �RuntimeErrorr�lowerr�skipr,r!�floatr)	�devicer3�errr(�fields�	sys_total�sys_used�sys_free�sys_percentr)r)r*�df�s
rJz
POSIX only��reasonc@s�eZdZdZedd��Zedd��Zdd�Zdd	�Zd
d�Z	dd
�Z
dd�Ze�e
�dd���Ze�e
�dd���Zdd�Zdd�Zdd�Zdd�Zejjep�edd�dd��Zd d!�Ze
�d"d#��Zejjed$d�ejjed%d�d&d'���Zd(S))�TestProcesszBCompare psutil results against 'ps' command line utility (mainly).cCsttddgtjd�j|_dS)Nz-Ez-O)�stdin)rr�
subprocess�PIPEr$��clsr)r)r*�
setUpClass�s�zTestProcess.setUpClasscCst|j�dS�N)rr$rQr)r)r*�
tearDownClass�szTestProcess.tearDownClasscCs,td|j�}t�|j���}||ks(J�dS)N�ppid)rr$�psutil�ProcessrV)�selfZppid_psZppid_psutilr)r)r*�	test_ppid�szTestProcess.test_ppidcCs.td|j�}t�|j���j}||ks*J�dS)N�uid)rr$rWrX�uids�real)rYZuid_psZ
uid_psutilr)r)r*�test_uid�szTestProcess.test_uidcCs.td|j�}t�|j���j}||ks*J�dS)NZrgid)rr$rWrX�gidsr])rYZgid_psZ
gid_psutilr)r)r*�test_gid�szTestProcess.test_gidcCs,td|j�}t�|j���}||ks(J�dS)N�user)rr$rWrX�username)rYZusername_psZusername_psutilr)r)r*�
test_username�szTestProcess.test_usernamecCs^t��}tjdtd��4}|��t|��j�ks2J�|j	s<J�Wd�n1sP0YdS)Nzpsutil.pwd.getpwuid�Zside_effect)
rWrXr�patch�KeyErrorrbrr\r]�called)rY�pZfunr)r)r*�test_username_no_resolution�sz'TestProcess.test_username_no_resolutioncCs<t�d�t|j�}t�|j���dd}||ks8J�dS)N皙�����?rr:)�time�sleepr7r$rWrX�memory_info)rYZrss_psZ
rss_psutilr)r)r*�test_rss_memory�s

zTestProcess.test_rss_memorycCs<t�d�t|j�}t�|j���dd}||ks8J�dS)Nrjrr:)rkrlr8r$rWrXrm)rYZvsz_psZ
vsz_psutilr)r)r*�test_vsz_memory�s

zTestProcess.test_vsz_memorycCsvt|j�}tj�|���}t�|j�����}t	�
dd|�}t	�
dd|�}t	�
dd|�}t	�
dd|�}||ksrJ�dS)Nz\d.\dr0z\d)r.r$�os�path�basenamer@rWrX�namer1r2)rYZname_psZname_psutilr)r)r*�	test_name�s
zTestProcess.test_namec	Cs�d}gd�}tjd|d��Vtjd|d��(t��}|��dksDJ�Wd�n1sX0YWd�n1sv0YdS)N�long-program-name)�long-program-name-extendedZfoo�bar�psutil._psplatform.Process.name�Zreturn_value�"psutil._psplatform.Process.cmdlinerv)rrerWrXrs)rYrs�cmdlinerhr)r)r*�test_name_long�s�zTestProcess.test_name_longc	Cs�d}tjd|d��^tjdt�dd�d��(t��}|��dksDJ�Wd�n1sX0YWd�n1sv0YdS�Nrurxryrzrr0rd)rrerWZAccessDeniedrXrs�rYrsrhr)r)r*�test_name_long_cmdline_ad_exc�s
�z)TestProcess.test_name_long_cmdline_ad_excc
Cs�d}tjd|d���tjdt�dd�d��Lt��}t�tj��|��Wd�n1s^0YWd�n1s|0YWd�n1s�0YdSr})rrerWZ
NoSuchProcessrXr�raisesrsr~r)r)r*�test_name_long_cmdline_nsp_excs
�z*TestProcess.test_name_long_cmdline_nsp_exczps -o start not availablerKcCs\td|j�}t�|j���}tj�|��d�}t|�}tj�|��d�}|||fvsXJ�dS)Nrz%H:%M:%S)	rr$rWrXZcreate_time�datetime�
fromtimestamp�strftime�round)rYZtime_psZtime_psutilZtime_psutil_tstampZround_time_psutilZround_time_psutil_tstampr)r)r*�test_create_times����zTestProcess.test_create_timecCs^t|j�}t�|j���}z||ks(J�Wn.tyX|dt|��}||ksTJ�Yn0dSrT)r.r$rWrXZexe�AssertionError�len)rYZps_pathnameZpsutil_pathnameZadjusted_ps_pathnamer)r)r*�test_exes
zTestProcess.test_execCsTt|j�}d�t�|j����}trDt|�t|�krD|�|�sPJ�n||ksPJ�dS)N� )	r4r$�joinrWrXr{r	r��
startswith)rYZ
ps_cmdlineZpsutil_cmdliner)r)r*�test_cmdline1s

zTestProcess.test_cmdlineznot reliable on SUNOSznot reliable on AIXcCs(td|j�}t����}||ks$J�dS)N�nice)rr$rWrXr�)rYZps_niceZpsutil_nicer)r)r*�	test_nice?szTestProcess.test_niceN)�__name__�
__module__�__qualname__�__doc__�classmethodrSrUrZr^r`rcrirrrnrortr|rr�r�mark�skipifrrr�r�r�rrr�r)r)r)r*rM�s8

	





rMc@s�eZdZdZe�dd��Zejje	dd�ejje
d�dd�ejjedd�d	d
����Ze�dd��Z
e�d
d��Zdd�Zdd�Zdd�Zdd�Zejjedd�e�dd���ZdS)�TestSystemAPIszTest some system APIs.cs~ttd���t���ts$tr0d�vr0��dd�t��t��dkrz�fdd��D��fdd��D�}|�dt	|���dS)Nr$rrcsg|]}|�vr|�qSr)r)��.0�x)�pids_psr)r*�
<listcomp>X�z,TestSystemAPIs.test_pids.<locals>.<listcomp>csg|]}|�vr|�qSr)r)r�)�pids_psutilr)r*r�Xszdifference: )
�sortedrrWZpidsrr�insertr��failr)rY�
differencer))r�r�r*�	test_pidsKs�zTestSystemAPIs.test_pidszunreliable on SUNOSrK�ifconfigzno ifconfig cmdz
not supportedcCsLtd�}tjdd�D]2}|��D]}|�|�r qq |�d||f��qdS)Nzifconfig -aT)Zpernicz/couldn't find %s nic in 'ifconfig -a' output
%s)rrWZnet_io_countersr,r�r�)rYr&Znicr(r)r)r*�test_nic_names_s
��zTestSystemAPIs.test_nic_namescCs�td�}|��st�d��|�d�}dd�|D�}dd�|D�}t|�tt���ksXJ�|jt��|d��`t	t���D]B\}}|j
||ks�J�|j||ks�J�|jdurxt�
|j�qxWd�n1s�0YdS)N�who -u�no users on this systemr9cSsg|]}|��d�qS)r�r,r�r)r)r*r�vr�z-TestSystemAPIs.test_users.<locals>.<listcomp>cSsg|]}|��d�qS)rr�r�r)r)r*r�wr��rWZwho)rr rrAr,r�rW�users�subTest�	enumeratersZterminalr$rX)rYr3�linesr�Z	terminals�idx�ur)r)r*�
test_usersps


zTestSystemAPIs.test_userscCstd�}|��st�d��d}t�d|�}|r4d}nNt�d|�}|rJd}n8t�d|�}|r`d}n"t�d	|�}|r�d}d
d�|D�}|s�t�d|��|jt��|d
��Jt	t���D],\}}t
j
�|j��
|�}|||ks�J�q�Wd�n1s�0YdS)Nr�r�z\d\d\d\d-\d\d-\d\d \d\d:\d\dz%Y-%m-%d %H:%Mz[A-Z][a-z][a-z] \d\d \d\d:\d\dz%b %d %H:%Mz[A-Z][a-z][a-z] \d\dz%b %dz[a-z][a-z][a-z] \d\dcSsg|]}|���qSr))�
capitalizer�r)r)r*r��r�z5TestSystemAPIs.test_users_started.<locals>.<listcomp>z(cannot interpret tstamp in who output
%sr�)rr rrAr1�findallr�rWr�r�r�r��startedr�)rYr3Ztstampr�r�r�Zpsutil_valuer)r)r*�test_users_started�s:
���z!TestSystemAPIs.test_users_startedc	Cs~tjdttjd�d��T}t�t�� tj�	t
���Wd�n1sH0Y|js\J�Wd�n1sp0YdS)Nzpsutil._psposix.os.killr0rd)
rre�OSError�errno�EBADFrr�rW�_psposixZ
pid_existsrp�getpidrg�rY�mr)r)r*�test_pid_exists_let_raise�s�.z(TestSystemAPIs.test_pid_exists_let_raisec	Cs~tjdttjd�d��T}t�t�� tj�	t
���Wd�n1sH0Y|js\J�Wd�n1sp0YdS)N�psutil._psposix.os.waitpidr0rd)
rrer�r�r�rr�rWr��wait_pidrpr�rgr�r)r)r*�test_os_waitpid_let_raise�s�.z(TestSystemAPIs.test_os_waitpid_let_raisec	Cs�tjdttjd�d��\}t�tjj	��$tjj
t��dd�Wd�n1sP0Y|j
sdJ�Wd�n1sx0YdS)Nr�r0rdg{�G�z�?)�timeout)rrer�r�ZEINTRrr�rWr��TimeoutExpiredr�rpr�rgr�r)r)r*�test_os_waitpid_eintr�s�2z$TestSystemAPIs.test_os_waitpid_eintrc	Csvtjddd��T}t�t�� tj�t�	��Wd�n1s@0Y|j
sTJ�Wd�n1sh0YdS)Nr�)r���ry)rrerr�r"rWr�r�rpr�rgr�r)r)r*�test_os_waitpid_bad_ret_status�s�.z-TestSystemAPIs.test_os_waitpid_bad_ret_statuszunreliable on AIXc	Cs�d}tjdd�D]�}t�|j�}zt|j�\}}}}WnVty�}z>t|���}d|vsjd|vsjd|vrvWYd}~q�WYd}~qd}~00t	|j
|�|ks�J�t	|j|�|ks�J�t	|j|�|ks�J�t	|j
|�dksJ�qdS)Ni@F)�allzno such file or directoryzraw devices not supportedzpermission deniedr)rWZdisk_partitions�
disk_usageZ
mountpointrJrCr?rr@�abs�total�used�free�percent)	rYZ	tolerance�part�usagerFrGrHrIrDr)r)r*�test_disk_usage�s&���zTestSystemAPIs.test_disk_usageN)r�r�r�r�rr�rr�r�rrr
r�r�r�r�r�r�r�rr�r)r)r)r*r�Gs$


&
	
r�c@seZdZdd�ZdS)�TestMisccCs4t�}|dksJ�|t��ks"J�|tjks0J�dS)Nr)r�resource�mmapZPAGESIZE)rYZpagesizer)r)r*�test_getpagesize�szTestMisc.test_getpagesizeN)r�r�r�r�r)r)r)r*r��sr�)N),r�r�r�rpr1rOrkrWrrrrrrrZpsutil.testsr	r
rrr
rrrrrrrrr�r�Zpsutil._psutil_posixrrr.r4r7r8rJr�r�rMr�r�r)r)r)r*�<module>sZ
8
-#PKok\v�b�?�?8psutil/tests/__pycache__/test_process_all.cpython-39.pycnu�[���a

��?h�H�@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddlm	Z	ddlm
Z
ddlmZddlmZddlm
Z
ddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#e�o�e�o�eZ$dd�Z%Gdd�de�Z&Gd d!�d!e�Z'dS)"zeIterate over all process PIDs and for each one of them invoke and
test all psutil.Process() methods.
�N)�AIX)�BSD)�FREEBSD)�LINUX)�MACOS)�NETBSD)�OPENBSD)�OSX)�POSIX)�WINDOWS)�PY3)�FileNotFoundError)�long)�unicode)�
CI_TESTING)�PYTEST_PARALLEL)�	QEMU_USER)�VALID_PROC_STATUSES)�PsutilTestCase)�check_connection_ntuple)�create_sockets)�
is_namedtuple)�is_win_secure_system_proc)�process_namespace)�pytestcs*t����fdd�������fdd�}zt����Wn"tjyX����iYS0z��ddg�}Wntjy�����Yn�0|d|d��d�ji}t��}|j	|j
dd	�D]Z\}}z|�||<Wq�tj�y}z&�|����WYd}~q�WYd}~q�d}~00q�|�|SdS)
Ncs���|j��|jdur&��|j|�t|tj�rd��|�|jdurz��|jd���|j|�nt|tj	�rz��
|�t|�t|�dS�Nr)
�assertEqual�pid�name�
isinstance�psutilZ
ZombieProcessZassertProcessZombie�ppidZassertGreaterEqual�
NoSuchProcess�assertProcessGone�str�repr)�exc�procrr!)r�tcase��I/usr/local/lib64/python3.9/site-packages/psutil/tests/test_process_all.py�check_exception7s



z"proc_info.<locals>.check_exceptionc
sP�dkrLz��d�Wn4tjyJ}z�|����WYd}~n
d}~00dSr)�waitr �Error)r&)r+rrr!r'r)r*�do_waitEs
zproc_info.<locals>.do_waitr!rrF)�clear_cache)rr �Processr"Z
assertPidGoneZas_dictr#rr�iterZgettersr-)rr.�d�info�nsZfunZfun_namer&r))r+rrr!r'r(r*�	proc_info4s.


$r5c@s8eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�Zd8d9�Zd:d;�Z d<d=�Z!d>d?�Z"d@dA�Z#dBdC�Z$dDdE�Z%dFdG�Z&dHdI�Z'dJdK�Z(dLS)M�TestFetchAllProcessesz�Test which iterates over all running processes and performs
    some sanity checks against Process API's returned values.
    Uses a process pool to get info about all processes.
    cCst�d�trt��|_dS�NF)r �
_set_debug�
USE_PROC_POOL�multiprocessingZPool�pool��selfr)r)r*�setUpks
zTestFetchAllProcesses.setUpcCs&t�d�tr"|j��|j��dS�NT)r r8r9r;�	terminate�joinr<r)r)r*�tearDownrs

zTestFetchAllProcesses.tearDowncCsJddlm}tr"|j�|t���Sg}t��D]}|�||��q.|SdS)Nr)r5)Zpsutil.tests.test_process_allr5r9r;Zimap_unorderedr �pids�append)r=r5Zlsrr)r)r*�iter_proc_infoxsz$TestFetchAllProcesses.iter_proc_infocCs�g}|��D]�}|��D]�\}}t||�}z|||�Wnpty�d}|d||dt|�|f7}|d7}|dt��7}d�dd�|��D��d}|�	|�Yq0|d	d
gddifvr|sJ|��qq|r�|�
d�|���dS)NzH
======================================================================
z+FAIL: name=test_%s, pid=%s, ret=%s
info=%s
rzF----------------------------------------------------------------------z
%s�
css|]}d|VqdS)z    Nr))�.0�ir)r)r*�	<genexpr>��z1TestFetchAllProcesses.test_all.<locals>.<genexpr>r��)rE�items�getattr�	Exceptionr%�	traceback�
format_excrA�
splitlinesrDZfail)r=Zfailuresr3r�value�meth�sr)r)r*�test_all�s,
�zTestFetchAllProcesses.test_allcCs*t|t�sJ�|D]}t|t�sJ�qdS�N)r�listr$)r=�retr3�partr)r)r*�cmdline�szTestFetchAllProcesses.cmdlinecCs�t|ttf�sJ�|��|ks"J�|r�tr8|�d�s8dStj�|�sLJ|��t	r�tj�
|�r�ttd�r�ttd�r�zt�|tj
�s�J�Wn$ty�tj�|�r�ts��Yn0dS)Nz.exe�access�X_OK)rr$r�stripr�endswith�os�path�isabsr
�isfile�hasattrr\r]�AssertionError�existsr�r=rYr3r)r)r*�exe�szTestFetchAllProcesses.execCst|t�sJ�|dksJ�dSr�r�intrgr)r)r*r�szTestFetchAllProcesses.pidcCs*t|ttf�sJ�|dksJ�t|�dSr)rrjrr5rgr)r)r*r!�szTestFetchAllProcesses.ppidcCsBt|ttf�sJ�tr*|s*t|d�r*dSts>|s>Jt|���dS)Nr)rr$rrrrr%rgr)r)r*r�s
zTestFetchAllProcesses.namecCs^t|t�sJ�z|dksJ�Wn(tyFtr@|dtjkr@n�Yn0t�dt�|��dS)Nr�statusz%Y %m %d %H:%M:%S)	r�floatrerr Z
STATUS_ZOMBIE�time�strftime�	localtimergr)r)r*�create_time�sz!TestFetchAllProcesses.create_timecCs4t|�sJ�|D]}t|t�s"J�|dksJ�qdSr)rrrj)r=rYr3�uidr)r)r*�uids�szTestFetchAllProcesses.uidscCs<t|�sJ�|D]&}t|t�s"J�tsts|dksJ�qdSr)rrrjrr)r=rYr3�gidr)r)r*�gids�s
zTestFetchAllProcesses.gidscCs.t|t�sJ�|��|ksJ�|��s*J�dSrW)rr$r^rgr)r)r*�username�szTestFetchAllProcesses.usernamecCs>t|t�sJ�|sJ|��tr"dS|dks.J�|tvs:J�dS)N�?)rr$rrrgr)r)r*rk�szTestFetchAllProcesses.statuscCs@t|�sJ�|D]*}t|ttf�s&J�|dkr|dksJ�qdS)N���r�rrrjr)r=rYr3�fieldr)r)r*�io_counters�s
z!TestFetchAllProcesses.io_counterscCs�trBt|jt�sJ�t|jt�s$J�|jdks2J�|jdks|J�n:tjtjtjtj	g}t|t�sdJ�|dkspJ�||vs|J�dSr)
rrZioclassrjrSr ZIOPRIO_VERYLOWZ
IOPRIO_LOWZ
IOPRIO_NORMALZIOPRIO_HIGH)r=rYr3�choicesr)r)r*�ionice�s�zTestFetchAllProcesses.ionicecCs:t|t�sJ�tr*|dkr*t|d�r*dS|dks6J�dS)Nrr�)rrjrrrgr)r)r*�num_threads
sz!TestFetchAllProcesses.num_threadscCsnt|t�sJ�|D]V}t|�s"J�|jdks0J�|jdks>J�|jdksLJ�|D]}t|ttf�sPJ�qPqdSr)rrXr�idZ	user_timeZsystem_timerjrl)r=rYr3�tryr)r)r*�threadsszTestFetchAllProcesses.threadscCs4t|�sJ�|D]}t|t�s"J�|dksJ�qdSr)rrrl)r=rYr3�nr)r)r*�	cpu_timesszTestFetchAllProcesses.cpu_timescCs0t|t�sJ�d|kr"dks,nJ|��dS)NrKgY@�rrlrgr)r)r*�cpu_percent%sz!TestFetchAllProcesses.cpu_percentcCs^t|t�sJ�tr|dkrdS|dks*J�t��dkrB|dksBJ�|ttt����vsZJ�dS)Nrwrr})rrjrr �	cpu_countrX�rangergr)r)r*�cpu_num)szTestFetchAllProcesses.cpu_numcCs|t|�sJ�|D]"}t|ttf�s&J�|dksJ�qtrx|j|jksHJ�|j|jksXJ�|j	|j
kshJ�|j|jksxJ�dSr)
rrrjrrZ	peak_wsetZwsetZpeak_paged_poolZ
paged_poolZpeak_nonpaged_poolZ
nonpaged_poolZ
peak_pagefileZpagefile�r=rYr3rSr)r)r*�memory_info2sz!TestFetchAllProcesses.memory_infocCs�t|�sJ�t��j}|jD]N}t||�}t|ttf�s<J�|dksHJ�t	st
rZ|dvrZq||ksJ|��qt	r�|j|jks�J�dS)Nr)Zvms�data)
rr Zvirtual_memory�total�_fieldsrNrrjrrr	ZpssZuss)r=rYr3r�rrSr)r)r*�memory_full_info=s


z&TestFetchAllProcesses.memory_full_infoc	Cs"t|t�sJ�|D�]}t|jt�s(J�t|jt�s8J�|j��|jksLJ�tr`|jdks�J�nltr�t|j	t�stJ�t|j
t�s�J�t|jt�s�J�|j	dks�J�|j
dvs�J�|jdks�J�ntr�|js�qt
j�|j�s�J|��zt
�|j�}Wnt�yYq0t�|j�sJ|��qdS)Nrwr)�r�w�azr+za+)rrX�fdrjrar$r^rr�position�mode�flagsrr`rb�statr
�S_ISREG�st_mode)r=rYr3�f�str)r)r*�
open_filesMs,

z TestFetchAllProcesses.open_filescCst|t�sJ�|dksJ�dSrrirgr)r)r*�num_fdsgszTestFetchAllProcesses.num_fdscCs`t��Ft|�tt|��ks J�|D]}t|�s4J�t|�q$Wd�n1sR0YdSrW)r�len�setrr)r=rYr3�connr)r)r*�net_connectionsks
z%TestFetchAllProcesses.net_connectionsc
Cs�t|ttf�sJ�|��|ks"J�|r�tj�|�s:J|��zt�|�}WnDty�}z,t	rjt
j�|�rjn|j
t
jkrx�WYd}~nd}~00t�|j�s�J�dSrW)rr$rr^r`rarbr��OSErrorrr Z_psplatformZis_permission_err�errno�ENOENT�S_ISDIRr�)r=rYr3r��errr)r)r*�cwdrszTestFetchAllProcesses.cwdcCs0t|t�sJ�d|kr"dks,nJ|��dS)Nr�dr�rgr)r)r*�memory_percent�sz$TestFetchAllProcesses.memory_percentcCst|t�sJ�dSrW)r�boolrgr)r)r*�
is_running�sz TestFetchAllProcesses.is_runningcCsRt|t�sJ�|gksJ�ttt����}|D]}t|t�s@J�||vs.J�q.dSrW)rrXr�r r�rj)r=rYr3Zcpusr�r)r)r*�cpu_affinity�sz"TestFetchAllProcesses.cpu_affinitycCsJt|ttd�f�sJ�|durFtj�|�s2J|��tj�|�sFJ|��dSrW)rr$�typer`rarbrfrgr)r)r*�terminal�szTestFetchAllProcesses.terminalcCs�|D]�}t|jt�sJ�t|jt�s(J�t|jt�s8J�|jD]�}t||�}|dkrx|�d�s�tj�	|j�s�J|j��q>|dkr�|s�Jt
|���q>|dkr�ts�|s�Jt
|���q>t|tt
f�s�J�|dks>J�q>qdS)Nra)�[zanon_inode:�addr�permsr)rr�r$r�rar�rN�
startswithr`rbr%rrjr)r=rYr3�nt�fnamerSr)r)r*�memory_maps�s 


z!TestFetchAllProcesses.memory_mapscCst|t�sJ�|dksJ�dSrrirgr)r)r*�num_handles�sz!TestFetchAllProcesses.num_handlescCsxt|t�sJ�tr2d|kr&dkstnJ|��nBdd�tt�D�}||vsPJ�trft|tj�stJ�nt|t�stJ�dS)Ni���cSs g|]}|�d�rtt|��qS)Z_PRIORITY_CLASS)r_rNr )rG�xr)r)r*�
<listcomp>�s
�z.TestFetchAllProcesses.nice.<locals>.<listcomp>)rrjr
�dirr r�enum�IntEnum)r=rYr3Z
prioritiesr)r)r*�nice�s �zTestFetchAllProcesses.nicecCs8t|�sJ�|D]"}t|ttf�s&J�|dksJ�qdSrrxr�r)r)r*�num_ctx_switches�sz&TestFetchAllProcesses.num_ctx_switchescCsBt|t�sJ�t|�dksJ�|ddks.J�|ddks>J�dS)N�rrwr})r�tupler�rgr)r)r*�rlimit�szTestFetchAllProcesses.rlimitcCs@t|t�sJ�|��D]$\}}t|t�s,J�t|t�sJ�qdSrW)r�dictrMr$)r=rYr3�k�vr)r)r*�environ�szTestFetchAllProcesses.environN))�__name__�
__module__�__qualname__�__doc__r>rBrErVr[rhrr!rrprrrtrurkrzr|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*r6esL
			
	r6c@s(eZdZdZdd�Zdd�Zdd�ZdS)	�
TestPidsRangea@Given pid_exists() return value for a range of PIDs which may or
    may not exist, make sure that psutil.Process() and psutil.pids()
    agree with pid_exists(). This guarantees that the 3 APIs are all
    consistent with each other. See:
    https://github.com/giampaolo/psutil/issues/2359

    XXX - Note about Windows: it turns out there are some "hidden" PIDs
    which are not returned by psutil.pids() and are also not revealed
    by taskmgr.exe and ProcessHacker, still they can be instantiated by
    psutil.Process() and queried. One of such PIDs is "conhost.exe".
    Running as_dict() for it reveals that some Process() APIs
    erroneously raise NoSuchProcess, so we know we have problem there.
    Let's ignore this for now, since it's quite a corner case (who even
    imagined hidden PIDs existed on Windows?).
    cCst�d�dSr7�r r8r<r)r)r*r>�szTestPidsRange.setUpcCst�d�dSr?r�r<r)r)r*rB�szTestPidsRange.tearDownc	Csfdd�}dd�}tdd�D]F}tr,||�r,q|j|d��||�Wd�q1sV0YqdS)NcSs�ztd|d�}Wnty&YdS0|�V|D]8}|�d�r2t|��d�}||kWd�Sq2td��Wd�n1s�0YdS)Nz/proc/%s/status�rbFsTgid:r}z'Tgid' line not found)�openr
r�rj�split�
ValueError)rr��lineZtgidr)r)r*�is_linux_tid�s
z+TestPidsRange.test_it.<locals>.is_linux_tidc	Ss�d}t�|�}zv|r4t�|�ts�|t��vs�J�nNtsnt�tj��t�|�Wd�n1sd0Yts�|t��vs�J�Wn*tj	t
fy�|d8}|dkr��Yq0dSqdS)N�r}r)r Z
pid_existsr0rrCrrZraisesr"r-re)rr�rfr)r)r*�check�s"

(z$TestPidsRange.test_it.<locals>.checkr}i�)r)r�rZsubTest)r=r�r�rr)r)r*�test_it�szTestPidsRange.test_itN)r�r�r�r�r>rBr�r)r)r)r*r��sr�)(r�r�r�r:r`r�rmrPr rrrrrrrr	r
rZpsutil._compatrr
rrZpsutil.testsrrrrrrrrrrrr9r5r6r�r)r)r)r*�<module>sN1qPKok\+��N�N0psutil/tests/__pycache__/test_bsd.cpython-39.pycnu�[���a

��?h�N�@s�dZddlZddlZddlZddlZddlZddlmZddlmZddlmZddlm	Z	ddl
mZddl
mZdd	l
m
Z
dd
l
mZddl
mZddl
mZdd
l
mZddl
mZddl
mZer�ddlmZe�Ze��dko�ed�ZndZdZdd�Zdd�Zejjedd�Gdd�de
��Zejjedd�Gdd�de
��Zejjedd�Gdd�de
��Zejje	dd�Gd d!�d!e
��Z ejjed"d�Gd#d$�d$e
��Z!dS)%z$Tests specific to all BSD platforms.�N)�BSD)�FREEBSD)�NETBSD)�OPENBSD)�HAS_BATTERY)�TOLERANCE_SYS_MEM)�PsutilTestCase)�pytest)�retry_on_failure)�sh)�spawn_testproc)�	terminate)�which)�getpagesize�museFcCsltd|�}tr(||�d�dd�}nts0trF||�d�dd�}z
t|�WStyf|YS0dS)zmExpects a sysctl command with an argument and parse the result
    returning only the value of interest.
    zsysctl z: �N�=�)rr�findrr�int�
ValueError)�cmdline�result�r�A/usr/local/lib64/python3.9/site-packages/psutil/tests/test_bsd.py�sysctl-s
rcCs>td�}|�d�D]}|�|�rq.qtd��t|��d�S)z+Thin wrapper around 'muse' cmdline utility.r�
zline not foundr)r�split�
startswithrr)�field�out�linerrrr<s
zBSD only��reasonc@s�eZdZdZedd��Zedd��Zejj	e
dd�dd	��Zd
d�Zejj	e
d�d
d�dd��Zejj	e
d�d
d�ejj	e
dd�dd���Zejj	e
d�dd�dd��ZdS)�BSDTestCasez)Generic tests common to all BSD variants.cCst�j|_dS�N�r�pid��clsrrr�
setUpClassPszBSDTestCase.setUpClasscCst|j�dSr%�r
r'r(rrr�
tearDownClassTszBSDTestCase.tearDownClassz -o lstart doesn't work on NETBSDr"cCsPtd|j�}|�dd���}t�|j���}t�dt�	|��}||ksLJ�dS)Nzps -o lstart -p %sZSTARTED�z%a %b %e %H:%M:%S %Y)
rr'�replace�strip�psutil�ProcessZcreate_time�time�strftime�	localtime)�self�outputZstart_psZstart_psutilrrr�test_process_create_timeXs
�z$BSDTestCase.test_process_create_timecCs�dd�}tjdd�D]�}t�|j�}||j�\}}}}|j|ksDJ�|j|ksRJ�t|j|�dkrx|�d|j|f��t|j	|�dkr|�d|j	|f��qdS)NcSs�td|���}|�d�}|�d�|�d�}|��dd�\}}}}|dkrRd}t|�d}t|�d}t|�d}||||fS)Nz
df -k "%s"rr��noner-�)rr/r�popr)�pathr �linesr!�dev�total�used�freerrr�dfes


z"BSDTestCase.test_disks.<locals>.dfF)�alli�zpsutil=%s, df=%s)
r0Zdisk_partitions�
disk_usageZ
mountpointZdevicer?�absrAZfailr@)r5rB�part�usager>r?r@rArrr�
test_disksbs
zBSDTestCase.test_disksrzsysctl cmd not availablecCs td�}tjdd�|ksJ�dS)Nzhw.ncpuT)�logical)rr0�	cpu_count�r5Zsystrrr�test_cpu_count_logical}sz"BSDTestCase.test_cpu_count_logicalzskipped on NETBSDcCstd�}|t��jksJ�dS)Nz
hw.physmem)rr0�virtual_memoryr?�r5�numrrr�test_virtual_memory_total�sz%BSDTestCase.test_virtual_memory_total�ifconfigzifconfig cmd not availablec	Csvt����D]d\}}ztd|�}Wnty6Yq0|jd|vksJJ�d|vr|jtt�	d|�d�ksJ�qdS)Nzifconfig %s�RUNNING�mtuz	mtu (\d+)r)
r0Znet_if_stats�itemsr�RuntimeErrorZisuprSr�re�findall)r5�name�statsr rrr�test_net_if_stats�szBSDTestCase.test_net_if_statsN)�__name__�
__module__�__qualname__�__doc__�classmethodr*r,r	�mark�skipifrr7rHrrLrPrZrrrrr$Ls&


	
�
�r$zFREEBSD onlyc@sfeZdZedd��Zedd��Ze�dd��Zdd�Zd	d
�Z	dd�Z
e�d
d��Ze�dd��ZdS)�FreeBSDPsutilTestCasecCst�j|_dSr%r&r(rrrr*�sz FreeBSDPsutilTestCase.setUpClasscCst|j�dSr%r+r(rrrr,�sz#FreeBSDPsutilTestCase.tearDownClasscCs�td|j�}t�|j�jdd�}|�d�dd�}|r�|��}|��}|dd�\}}}}	}
|��}d||f|jks|J�t|
�|j	ks�J�|j
�d�s4|d	|j
ks4J�q4dS)
Nzprocstat -v %sF)Zgroupedrr�z%s-%s�[�
)rr'r0r1Zmemory_mapsrr;�addrrZrssr<r)r5r �mapsr=r!�fields�_�start�stopZ_perms�res�maprrr�test_memory_maps�sz&FreeBSDPsutilTestCase.test_memory_mapscCs<td|j�}t�|j���|�d�d��dks8J�dS)Nzprocstat -b %srr���)rr'r0r1Zexer�r5r rrr�test_exe�szFreeBSDPsutilTestCase.test_execCsLtd|j�}d�t�|j����d�|�d�d��dd��ksHJ�dS)Nzprocstat -c %s� rrr)rr'�joinr0r1rrrprrr�test_cmdline�s�z"FreeBSDPsutilTestCase.test_cmdlinecCs�td|j�}|�d�d��dd�\}}}}}}t�|j�}|��}	|��}
|	jt|�ksbJ�|	j	t|�kstJ�|	j
t|�ks�J�|
jt|�ks�J�|
j	t|�ks�J�|
j
t|�ks�J�dS)Nzprocstat -s %srrr�)rr'rr0r1�uids�gids�realrZ	effectiveZsaved)r5r ZeuidZruidZsuidZegidZrgidZsgid�prvrwrrr�test_uids_gids�s&z$FreeBSDPsutilTestCase.test_uids_gidscCs�g}td|j�}t�|j�}|�d�D]�}|����}d|vrrt|��d�}|��j	}||ksfJ�|�
d�q(d|vr(t|��d�}|��j}||ks�J�|�
d�q(t|�dkr�t
d��dS)N�procstat -r %srz voluntary contextroz involuntary contextr�)couldn't find lines match in procstat out)rr'r0r1r�lowerr/rZnum_ctx_switchesZ	voluntary�appendZinvoluntary�lenrU�r5Ztestedr ryr!Zpstat_valueZpsutil_valuerrr�test_ctx_switches�s"

z'FreeBSDPsutilTestCase.test_ctx_switchescCs�g}td|j�}t�|j�}|�d�D]�}|����}d|vr�td|��d�d�d�}|��j	}||kstJ�|�
d�q(d|vr(td|��d�d�d�}|��j}||ks�J�|�
d�q(t|�dkr�t
d	��dS)
Nr{rz	user timez0.ro�.zsystem timerr|)rr'r0r1rr}r/�floatZ	cpu_times�userr~�systemrrUr�rrr�test_cpu_times�s"

z$FreeBSDPsutilTestCase.test_cpu_timesN)
r[r\r]r_r*r,r
rnrqrtrzr�r�rrrrrb�s




rbc@s�eZdZedd��Zdd�Ze�dd��Ze�dd��Ze�d	d
��Z	e�dd��Z
e�d
d��Ze�dd��Ze
jjedd�dd��Ze
jjedd�e�dd���Ze
jjedd�e�dd���Ze
jjedd�e�dd���Ze
jjedd�e�dd���Ze
jjedd�e�dd���Ze
jjedd�e�dd ���Zd!d"�Zd#d$�Zd%d&�Ze�d'd(��Zd)d*�Zd+d,�Zd-d.�Zd/d0�Ze
jje d1d�d2d3��Z!e
jje d1d�d4d5��Z"e
jje d6d�d7d8��Z#d9d:�Z$d;S)<�FreeBSDSystemTestCasecCsRtd���d}t�d|�}|s,td|��dd�|dd�D�\}}}|||fS)	Nzswapinfo -kroz\s+zCan't parse swapinfo: %scss|]}t|�dVqdS)r:N)r)�.0ryrrr�	<genexpr>�z7FreeBSDSystemTestCase.parse_swapinfo.<locals>.<genexpr>rr8)r�
splitlinesrVrr)r6�partsr?r@rArrr�parse_swapinfo�sz$FreeBSDSystemTestCase.parse_swapinfocCs�d}ztt|��}Wnty0t�d��Yn0t��j|ksDJ�d}t|�}t|��d�d�d�}t|��d�d�d�}t��j	|ks�J�t��j
|ks�J�dS)Nzdev.cpu.0.freqz#frequencies not supported by kernelzdev.cpu.0.freq_levelsr�/ro)rrrUr	�skipr0Zcpu_freq�currentr�max�min)r5�sensor�
sysctl_resultZmax_freqZmin_freqrrr�!test_cpu_frequency_against_sysctlsz7FreeBSDSystemTestCase.test_cpu_frequency_against_sysctlcCs*td�t}tt��j|�tks&J�dS)Nzvm.stats.vm.v_active_count)r�PAGESIZErEr0rM�activerrKrrr�test_vmem_activesz&FreeBSDSystemTestCase.test_vmem_activecCs*td�t}tt��j|�tks&J�dS)Nzvm.stats.vm.v_inactive_count)rr�rEr0rM�inactiverrKrrr�test_vmem_inactive!sz(FreeBSDSystemTestCase.test_vmem_inactivecCs*td�t}tt��j|�tks&J�dS)Nzvm.stats.vm.v_wire_count)rr�rEr0rM�wiredrrKrrr�test_vmem_wired&sz%FreeBSDSystemTestCase.test_vmem_wiredcCs*td�t}tt��j|�tks&J�dS)Nzvm.stats.vm.v_cache_count)rr�rEr0rM�cachedrrKrrr�test_vmem_cached+sz&FreeBSDSystemTestCase.test_vmem_cachedcCs*td�t}tt��j|�tks&J�dS)Nzvm.stats.vm.v_free_count)rr�rEr0rMrArrKrrr�test_vmem_free0sz$FreeBSDSystemTestCase.test_vmem_freecCs&td�}tt��j|�tks"J�dS)Nzvfs.bufspace)rrEr0rM�buffersrrKrrr�test_vmem_buffers5sz'FreeBSDSystemTestCase.test_vmem_bufferszmuse not installedr"cCstd�}t��j|ksJ�dS)NZTotal)rr0rMr?rNrrr�test_muse_vmem_total<sz*FreeBSDSystemTestCase.test_muse_vmem_totalcCs&td�}tt��j|�tks"J�dS)NZActive)rrEr0rMr�rrNrrr�test_muse_vmem_activeAsz+FreeBSDSystemTestCase.test_muse_vmem_activecCs&td�}tt��j|�tks"J�dS)NZInactive)rrEr0rMr�rrNrrr�test_muse_vmem_inactiveGsz-FreeBSDSystemTestCase.test_muse_vmem_inactivecCs&td�}tt��j|�tks"J�dS)NZWired)rrEr0rMr�rrNrrr�test_muse_vmem_wiredMsz*FreeBSDSystemTestCase.test_muse_vmem_wiredcCs&td�}tt��j|�tks"J�dS)N�Cache)rrEr0rMr�rrNrrr�test_muse_vmem_cachedSsz+FreeBSDSystemTestCase.test_muse_vmem_cachedcCs&td�}tt��j|�tks"J�dS)NZFree)rrEr0rMrArrNrrr�test_muse_vmem_freeYsz)FreeBSDSystemTestCase.test_muse_vmem_freecCs&td�}tt��j|�tks"J�dS)NZBuffer)rrEr0rMr�rrNrrr�test_muse_vmem_buffers_sz,FreeBSDSystemTestCase.test_muse_vmem_bufferscCs"tt��jtd��dksJ�dS)Nzvm.stats.sys.v_swtch��)rEr0�	cpu_stats�ctx_switchesr�r5rrr�test_cpu_stats_ctx_switcheses����z1FreeBSDSystemTestCase.test_cpu_stats_ctx_switchescCs"tt��jtd��dksJ�dS)Nzvm.stats.sys.v_intrr�)rEr0r��
interruptsrr�rrr�test_cpu_stats_interruptsns��z/FreeBSDSystemTestCase.test_cpu_stats_interruptscCs"tt��jtd��dksJ�dS)Nzvm.stats.sys.v_softr�)rEr0r�Zsoft_interruptsrr�rrr�test_cpu_stats_soft_interruptsts����z4FreeBSDSystemTestCase.test_cpu_stats_soft_interruptscCs"tt��jtd��dksJ�dS)Nzvm.stats.sys.v_syscalli@
)rEr0r�Zsyscallsrr�rrr�test_cpu_stats_syscalls}s��z-FreeBSDSystemTestCase.test_cpu_stats_syscallscCs,|��\}}}tt��j|�tks(J�dSr%)r�rEr0�swap_memoryrAr)r5�_total�_usedrArrr�test_swapmem_free�sz'FreeBSDSystemTestCase.test_swapmem_freecCs,|��\}}}tt��j|�tks(J�dSr%)r�rEr0r�r@r)r5r�r@�_freerrr�test_swapmem_used�sz'FreeBSDSystemTestCase.test_swapmem_usedcCs,|��\}}}tt��j|�tks(J�dSr%)r�rEr0r�r?r)r5r?r�r�rrr�test_swapmem_total�sz(FreeBSDSystemTestCase.test_swapmem_totalcCsLtd�}||�d�dd�}|d|�d��}t|�}|t��ksHJ�dS)Nzsysctl kern.boottimez sec = ��,)rrrr0�	boot_time)r5�sZbtimerrr�test_boot_time�s
z$FreeBSDSystemTestCase.test_boot_timez
no batterycCs�dd�}td�}tdd�|�d�D��}t��}t|d�dd	��}|d
}|j|ksZJ�|dkrt|jtj	ks�J�n||j�|ks�J�dS)NcSs(t|d�\}}t|d�\}}d||fS)N�<z%d:%02d)�divmod)Zsecs�mZ_s�hrrr�
secs2hours�sz>FreeBSDSystemTestCase.test_sensors_battery.<locals>.secs2hoursz
acpiconf -i 0cSs(g|] }|�d�d|�d�df�qS)�	rro)r)r��xrrr�
<listcomp>�r�z>FreeBSDSystemTestCase.test_sensors_battery.<locals>.<listcomp>rzRemaining capacity:�%r-zRemaining time:�unknown)
r�dictrr0�sensors_batteryrr.�percent�secsleftZPOWER_TIME_UNLIMITED)r5r�r rhZmetricsr�Zremaining_timerrr�test_sensors_battery�s�z*FreeBSDSystemTestCase.test_sensors_batterycCslt��jtd�ksJ�t��jtd�dkks0J�t��j}|dkrTtd�dkshJ�n|td�dkshJ�dS)N�hw.acpi.battery.life�hw.acpi.aclinerr�hw.acpi.battery.timeror�)r0r�r�rZ
power_pluggedr�)r5r�rrr�#test_sensors_battery_against_sysctl�s
�

�
z9FreeBSDSystemTestCase.test_sensors_battery_against_sysctlzhas batterycCsVt�t��(td�td�td�Wd�n1s80Yt��dusRJ�dS)Nr�r�r�)r	ZraisesrUrr0r�r�rrr�test_sensors_battery_no_battery�s
&z5FreeBSDSystemTestCase.test_sensors_battery_no_batteryc	Cs�t�d�}t|�D]�}d|}zttt|�dd���}WntyVt�d��Yn0t	t�
�d|j|�dkszJ�d|}ttt|�dd���}t�
�d|j|ksJ�qdS)NTzdev.cpu.%s.temperatureroz$temperatures not supported by kernelZcoretemprezdev.cpu.%s.coretemp.tjmax)
r0rJ�rangerr�rrUr	r�rEZsensors_temperaturesr��high)r5Znum_cpus�cpur�r�rrr�(test_sensors_temperatures_against_sysctl�s*
������z>FreeBSDSystemTestCase.test_sensors_temperatures_against_sysctlN)%r[r\r]�staticmethodr�r�r
r�r�r�r�r�r�r	r`ra�MUSE_AVAILABLEr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rr�r�r�r�rrrrr��sf







		

	



r�zOPENBSD onlyc@seZdZdd�ZdS)�OpenBSDTestCasecCs6td�}tj�|d�}tj�t���}||ks2J�dS)Nz
kern.boottimez%a %b %d %H:%M:%S %Y)r�datetime�strptime�
fromtimestampr0r�)r5r�Zsys_btZ	psutil_btrrrr��szOpenBSDTestCase.test_boot_timeN)r[r\r]r�rrrrr��sr�zNETBSD onlyc@sheZdZedd��Zdd�Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
dd�ZdS)�NetBSDTestCasecCsrtd��J}|D]4}|�|�rt|��d�dWd�SqWd�n1sX0Ytd|��dS)Nz
/proc/meminforr:z
can't find %s)�openrrrr)Zlook_for�fr!rrr�
parse_meminfo�s


FzNetBSDTestCase.parse_meminfocCst��j|�d�ksJ�dS)Nz	MemTotal:)r0rMr?r�r�rrr�test_vmem_total	szNetBSDTestCase.test_vmem_totalcCs$tt��j|�d��tks J�dS)NzMemFree:)rEr0rMrAr�rr�rrrr�s��zNetBSDTestCase.test_vmem_freecCs$tt��j|�d��tks J�dS)NzBuffers:)rEr0rMr�r�rr�rrrr�s����z NetBSDTestCase.test_vmem_bufferscCs$tt��j|�d��tks J�dS)Nz
MemShared:)rEr0rMZsharedr�rr�rrr�test_vmem_shareds����zNetBSDTestCase.test_vmem_sharedcCs$tt��j|�d��tks J�dS)NzCached:)rEr0rMr�r�rr�rrrr�$s��zNetBSDTestCase.test_vmem_cachedcCs$tt��j|�d��tks J�dS)Nz
SwapTotal:)rEr0r�r?r�rr�rrrr�,s��z!NetBSDTestCase.test_swapmem_totalcCs$tt��j|�d��tks J�dS)Nz	SwapFree:)rEr0r�rAr�rr�rrrr�2s��z NetBSDTestCase.test_swapmem_freecCs"t��}|j|j|jksJ�dSr%)r0r�r@r?rA)r5Zsmemrrrr�8sz NetBSDTestCase.test_swapmem_usedcCsxtdd��@}|D]"}|�d�rt|��d�}q<qtd��Wd�n1sP0Ytt��j|�dkstJ�dS)N�
/proc/stat�rbsintrr�couldn't find liner�)	r�rrrrrEr0r�r�)r5r�r!r�rrrr�>s
&z(NetBSDTestCase.test_cpu_stats_interruptscCsxtdd��@}|D]"}|�d�rt|��d�}q<qtd��Wd�n1sP0Ytt��j|�dkstJ�dS)Nr�r�sctxtrr�r�)	r�rrrrrEr0r�r�)r5r�r!r�rrrr�Hs
&z*NetBSDTestCase.test_cpu_stats_ctx_switchesN)r[r\r]r�r�r�r�r�r�r�r�r�r�r�r�rrrrr��s
			
r�)"r^r��osrVr2r0rrrrZpsutil.testsrrrr	r
rrr
rZpsutil._psutil_posixrr��getuidr�rrr`rar$rbr�r�r�rrrr�<module>
sJQXx
PKok\{��
y
y4psutil/tests/__pycache__/test_windows.cpython-39.pycnu�[���a

��?h؄�@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlm
Z
ddlmZddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!e
�r�e�s�e�"��:e�#d�ddl$Z$ddl%Z%ddl&Z&ddl'Z'Wd�n1�s�0Ye
�r�ddl(m)Z)ej*j+Z+ej,j-e
dd�ej,j-edd�ej,j-e�o�edd�Gdd�de����Z.dd�Z/e0fd d!�Z1Gd"d#�d#e.�Z2Gd$d%�d%e.�Z3Gd&d'�d'e.�Z4Gd(d)�d)e.�Z5Gd*d+�d+e.�Z6ej,j-e
dd�Gd,d-�d-e��Z7ej,j-e
dd�Gd.d/�d/e��Z8ej,j-e
dd�Gd0d1�d1e��Z9dS)2zWindows specific tests.�N)�WINDOWS)�FileNotFoundError)�super)�which)�APPVEYOR)�GITHUB_ACTIONS)�HAS_BATTERY)�IS_64BIT)�PY3)�PYPY)�TOLERANCE_DISK_USAGE)�TOLERANCE_SYS_MEM)�PsutilTestCase)�mock)�pytest)�retry_on_failure)�sh)�spawn_testproc)�	terminate�ignore)�convert_oserrorzWINDOWS only��reasonzpywin32 not available on PYPYzpywin32 broken on GITHUB + PY2c@seZdZdS)�WindowsTestCaseN)�__name__�
__module__�__qualname__�rr�E/usr/local/lib64/python3.9/site-packages/psutil/tests/test_windows.pyr;srcCs&td�st�d��dd|}t|�S)z�Currently not used, but available just in case. Usage:

    >>> powershell(
        "Get-CIMInstance Win32_PageFileUsage | Select AllocatedBaseSize")
    zpowershell.exezpowershell.exe not availablez?powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive z,-NoProfile -WindowStyle Hidden -Command "%s")rr�skipr)�cmd�cmdlinerrr�
powershellEs
��r"csjtd||f���}d�|��dd����}�durbd|vrXt�fdd�|��D��S�|�Sn|SdS)z�Currently not used, but available just in case. Usage:

    >>> wmic("Win32_OperatingSystem", "FreePhysicalMemory")
    2134124534
    zwmic path %s get %s��N�,csg|]}�|��qSrr��.0�x��	converterrr�
<listcomp>^�zwmic.<locals>.<listcomp>)r�strip�join�
splitlines�tuple�split)�path�whatr*�out�datarr)r�wmicTs
r6c@sReZdZejjdejvdd�dd��Zdd�Z	dd	�Z
d
d�Zdd
�Zdd�Z
dS)�TestCpuAPIs�NUMBER_OF_PROCESSORSz-NUMBER_OF_PROCESSORS env var is not availablercCs"ttjd�}|t��ksJ�dS)Nr8)�int�os�environ�psutil�	cpu_count)�selfZnum_cpusrrr�&test_cpu_count_vs_NUMBER_OF_PROCESSORSksz2TestCpuAPIs.test_cpu_count_vs_NUMBER_OF_PROCESSORScCs$t��d}t��}||ks J�dS)N�)�win32apiZ
GetSystemInfor<r=�r>�	sys_value�psutil_valuerrr�test_cpu_count_vs_GetSystemInfousz+TestCpuAPIs.test_cpu_count_vs_GetSystemInfocCs2t��}tdd�|��D��}t��|ks.J�dS)Ncss|]}|jVqdS�N)ZNumberOfLogicalProcessors�r'�procrrr�	<genexpr>~sz<TestCpuAPIs.test_cpu_count_logical_vs_wmi.<locals>.<genexpr>��wmi�WMI�sum�Win32_Processorr<r=)r>�wZprocsrrr�test_cpu_count_logical_vs_wmi|s
�z)TestCpuAPIs.test_cpu_count_logical_vs_wmicCs6t��}tdd�|��D��}tjdd�|ks2J�dS)Ncss|]}|jVqdSrF)Z
NumberOfCoresrGrrrrI�r,z:TestCpuAPIs.test_cpu_count_cores_vs_wmi.<locals>.<genexpr>F)�logicalrJ)r>rOZcoresrrr�test_cpu_count_cores_vs_wmi�sz'TestCpuAPIs.test_cpu_count_cores_vs_wmicCs t��ttjdd��ksJ�dS)NT)Zpercpu)r<r=�len�	cpu_times�r>rrr�test_cpu_count_vs_cpu_times�sz'TestCpuAPIs.test_cpu_count_vs_cpu_timescCs@t��}|��d}|jt��jks(J�|jt��jks<J�dS�Nr)	rKrLrNZCurrentClockSpeedr<Zcpu_freq�currentZ
MaxClockSpeed�max)r>rOrHrrr�
test_cpu_freq�szTestCpuAPIs.test_cpu_freqN)rrrr�mark�skipifr:r;r?rErPrRrVrZrrrrr7js�
r7c@s�eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zej	j
edd�e�d
d���Z
e�dd��Ze�dd��Zdd�Zdd�Zdd�Zdd�ZdS)�TestSystemAPIscCsRtd�}tjdd���}|D]0}d|�dd���vr6q||vr|�d|��qdS)Nz
ipconfig /allT)Zperniczpseudo-interface� �-z-%r nic wasn't found in 'ipconfig /all' output)rr<Znet_io_counters�keys�replace�lower�fail)r>r4ZnicsZnicrrr�test_nic_names�s�zTestSystemAPIs.test_nic_namescCs,t����d}t|j�t��jks(J�dSrW)rKrLZWin32_ComputerSystemr9ZTotalPhysicalMemoryr<�virtual_memory�total�r>rOrrr�test_total_phymem�sz TestSystemAPIs.test_total_phymemcCs4t����d}tt|j�t��j�t	ks0J�dSrW)
rKrL�Win32_PerfRawData_PerfOS_Memory�absr9ZAvailableBytesr<re�freer
rgrrr�test_free_phymem�s
��zTestSystemAPIs.test_free_phymemcCsht����d}t|j�t��jt��jks2J�t��jdkrdt��j	dksRJ�t��j
dksdJ�dSrW)rKrLrir9ZCommitLimitr<rerf�swap_memoryrk�usedrgrrr�test_total_swapmem�s��z!TestSystemAPIs.test_total_swapmemcCs|t��jdkrxt��jdd�d}t|j�dt|j�}t��j	dksLJ�t
t��j	|�dksfJ�t��j	dksxJ�dS)NrZ_Total)�Name�dr@)r<rmrfrKrLZ#Win32_PerfRawData_PerfOS_PagingFiler9ZPercentUsageZPercentUsage_Base�percentrj)r>rOZpercentSwaprrr�test_percent_swapmem�sz#TestSystemAPIs.test_percent_swapmemztest not relieable on appveyorrcCs:t����}tdd�|D��}tt���}||ks6J�dS)NcSsg|]
}|j�qSr�Z	ProcessIdr&rrrr+�r,z,TestSystemAPIs.test_pids.<locals>.<listcomp>)rKrL�
Win32_Process�setr<�pids)r>rOZwmi_pidsZpsutil_pidsrrr�	test_pids�szTestSystemAPIs.test_pidsc
Cs�tjdd�}t����}|D]�}|D]�}|j�dd�|jkr$|jsFqd|j	vrTq|j�
d�rdqzt�|j�}Wnty�YqYn0|j
t|j�ks�J�t|j�}|j|ks�J�t|j|�dkr�|�d|j|f��qq$|�d	t|���qdS)
NT��all�\r#�cdrom�A:i�zpsutil=%s, wmi=%szcan't find partition %s)r<�disk_partitionsrKrLZWin32_LogicalDiskZdeviceraZDeviceID�
mountpoint�opts�
startswith�
disk_usagerrfr9�SizeZ	FreeSpacerkrjrc�repr)r>Zps_partsZ	wmi_partsZps_partZwmi_part�usageZwmi_freerrr�
test_disks�s0

�zTestSystemAPIs.test_diskscCs�t��D]r}d|jvrqt�|j�}t�|j�}t|d|j�t	ksJJ�t|d|j
�t	ksdJ�|j|j
|jksJ�qdS)Nr|rr$)r<r~r�rAZGetDiskFreeSpaceExrr�rjrkrrfrn)r>ZdiskrCrDrrr�test_disk_usage�s
�zTestSystemAPIs.test_disk_usagecCs>dd�t���d�D�}dd�tjdd�D�}||ks:J�dS)NcSs"g|]}|r|�d�s|d�qS)r}r{)r�r&rrrr+s�z7TestSystemAPIs.test_disk_partitions.<locals>.<listcomp>z\cSsg|]}|j�d�s|j�qS)r})rr�r&rrrr+s�Try)rAZGetLogicalDriveStringsr1r<r~rBrrr�test_disk_partitionss�
�z#TestSystemAPIs.test_disk_partitionscCs\tt���}t����}t�}|D]}|�|j�|�|j�q"||@sXJd||f��dS)Nzno common entries in %s, %s)	rv�cextZnet_if_statsrKrLZWin32_NetworkAdapter�addrpZNetConnectionID)r>Zps_namesZwmi_adaptersZ	wmi_namesZwmi_adapterrrr�test_net_if_stats
s�z TestSystemAPIs.test_net_if_statscCs^t����}|dj�d�d}tj�|d�}tj�t�	��}t
||���}|dksZJ�dS)Nr�.�%Y%m%d%H%M%Sr@)rKrLZWin32_OperatingSystemZLastBootUpTimer1�datetime�strptime�
fromtimestampr<�	boot_timerj�
total_seconds)r>Zwmi_osZ
wmi_btime_strZwmi_btime_dtZ	psutil_dt�diffrrr�test_boot_times�zTestSystemAPIs.test_boot_timecCs�tjddd�� t��dks J�Wd�n1s40Ytjddd�� t��dks^J�Wd�n1sr0Ytjddd�� t��dks�J�Wd�n1s�0Ytjddd�� t��dks�J�Wd�n1s�0YdS)Nz psutil._pswindows.cext.boot_timer@�Zreturn_value��iM)r�patchr<r�rUrrr�test_boot_time_fluctuation#s...z)TestSystemAPIs.test_boot_time_fluctuationN)rrrrdrhrlrorsrr[r\rrrxr�r�r�r�r�r�rrrrr]�s 




r]c@sheZdZdd�Zejjedd�dd��Zejjedd�dd��Z	d	d
�Z
dd�Zd
d�Zdd�Z
dS)�TestSensorsBatterycCs2t��drt��dus.J�nt��dus.J�dS)NZSystemBatteriesPresent)rAZGetPwrCapabilitiesr<�sensors_batteryrUrrr�test_has_battery5sz#TestSensorsBattery.test_has_batteryz
no batteryrcCs:t��}|�d�d}t��}t|j|j�dks6J�dS)N�select * from Win32_Batteryrr$)rKrL�queryr<r�rjrrZEstimatedChargeRemaining�r>rOZbattery_wmiZbattery_psutilrrr�test_percent;s��zTestSensorsBattery.test_percentcCs6t��}|�d�d}t��}|j|jdkks2J�dS)Nr�r�)rKrLr�r<r�Z
power_pluggedZ
BatteryStatusr�rrr�test_power_pluggedEsz%TestSensorsBattery.test_power_pluggedcCsLtjddd��*}t��dus J�|js*J�Wd�n1s>0YdS)N�&psutil._pswindows.cext.sensors_battery)r�rrr�)rr�r<r��called�r>�mrrr�test_emulate_no_batteryNs�z*TestSensorsBattery.test_emulate_no_batterycCsPtjddd��.}t��jtjks$J�|js.J�Wd�n1sB0YdS)Nr�)r$rrrr��rr�r<r��secsleftZPOWER_TIME_UNLIMITEDr�r�rrr�test_emulate_power_connectedVs���z/TestSensorsBattery.test_emulate_power_connectedcCsPtjddd��.}t��jtjks$J�|js.J�Wd�n1sB0YdS)Nr�)r�rrr�r�r�rrr�test_emulate_power_charging`s���z.TestSensorsBattery.test_emulate_power_chargingcCsPtjddd��.}t��jtjks$J�|js.J�Wd�n1sB0YdS)Nr�)rrr���r�)rr�r<r�r�ZPOWER_TIME_UNKNOWNr�r�rrr�test_emulate_secs_left_unknownjs��z1TestSensorsBattery.test_emulate_secs_left_unknownN)rrrr�rr[r\rr�r�r�r�r�r�rrrrr�4s
	


r�c@s�eZdZedd��Zedd��Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#S)$�TestProcesscCst�j|_dSrF�r�pid��clsrrr�
setUpClass{szTestProcess.setUpClasscCst|j�dSrF�rr�r�rrr�
tearDownClassszTestProcess.tearDownClasscCsBt�d�}t�tj��|��Wd�n1s40YdSrW)r<�Processr�raises�AccessDenied�kill�r>�prrr�
test_issue_24�s
zTestProcess.test_issue_24cCs�t�d�}|��dksJ�t|�|��|��dks:J�z|��dd�\}}Wn&tjyxt�	�ddvrt�Yn0|dks�J�dS)Nr��Systemgr�r$)Zvistazwin-7Zwin7r)
r<r��name�str�username�create_time�memory_infor��platform�uname)r>r��rssZ_vmsrrr�test_special_pid�s
zTestProcess.test_special_pidcCsFt�|j�}t�t��|�tj�Wd�n1s80YdSrF)	r<r�r�rr��
ValueError�send_signal�signal�SIGINTr�rrr�test_send_signal�szTestProcess.test_send_signalcCsbt�t���}|��}t�tjtj	t���}|��}||dksDJ�t�
|�|��|ks^J�dS)Nr$)r<r�r:�getpid�num_handlesrA�OpenProcess�win32con�PROCESS_QUERY_INFORMATION�FALSE�CloseHandle)r>r��before�handle�afterrrr�test_num_handles_increment�s�
z&TestProcess.test_num_handles_incrementcCs�t�|��j�}|�tj�|�tj�|��|�	�t
�tj��|�tj�Wd�n1sf0Yt
�tj��|�tj�Wd�n1s�0YdSrF)
r<r�rr�r�r�ZCTRL_C_EVENTZCTRL_BREAK_EVENTr��waitrr��
NoSuchProcessr�rrr�test_ctrl_signals�s*zTestProcess.test_ctrl_signalscCs8t�tj�}|�d�r t�d��t���	�|ks4J�dS)N�$zrunning as service account)
rAZ
GetUserNameExr�ZNameSamCompatible�endswithrrr<r�r�)r>r�rrr�
test_username�s

zTestProcess.test_usernamecCsft�ddt�����}d�t�����}|ddkrD|dkrVnn|�	ddd�}||ksbJ�dS)Nz[ ]+r^r�"r#r�)
�re�subrAZGetCommandLiner-r.r<r�r!rarBrrr�test_cmdline�s
 zTestProcess.test_cmdlinecCsJt�tjtjt���}|�tj|�t	�
|�}t���
�}||ksFJ�dSrF)rAr�r�r�r�r:r��
addCleanupr��win32processZGetPriorityClassr<r��nice�r>r�rCrDrrr�	test_nice�s�
zTestProcess.test_nicecCs�t�tjtj|j�}|�tj|�t�	|�}t
�|j���}|d|j
ksNJ�|d|jks`J�|d|jksrJ�|d|jks�J�|d|jks�J�|d|jks�J�|d|jks�J�|d|jks�J�|j|jks�J�|j|jks�J�dS)	NZPeakWorkingSetSize�WorkingSetSizeZQuotaPeakPagedPoolUsageZQuotaPagedPoolUsageZQuotaPeakNonPagedPoolUsageZQuotaNonPagedPoolUsageZ
PagefileUsageZPeakPagefileUsage)rAr�r�r�r�r�r�r�r�ZGetProcessMemoryInfor<r�r�Z	peak_wsetZwsetZpeak_paged_poolZ
paged_poolZpeak_nonpaged_poolZ
nonpaged_poolZpagefileZ
peak_pagefiler��vmsr�rrr�test_memory_info�s.�
�����zTestProcess.test_memory_infocCsXt�tjtj|j�}|�tj|�t�	|j�}|�
�|��}t�
|�}||ksTJ�dSrF)rAr�r�r�r�r�r�r�r<r�rr�r�ZGetExitCodeProcess)r>r�r�rDrCrrr�	test_wait�s�
zTestProcess.test_waitcCs\dd�}t�tjtj|j�}|�tj|�|t�	|�d�}t
�|j���}||ksXJ�dS)Ncs�fdd�td�D�S)Ncsg|]}d|>�@r|�qS)r$r)r'�i�r(rrr+r,zGTestProcess.test_cpu_affinity.<locals>.from_bitmask.<locals>.<listcomp>�@)�ranger�rr�r�from_bitmasksz3TestProcess.test_cpu_affinity.<locals>.from_bitmaskr)
rAr�r�r�r�r�r�r�r�ZGetProcessAffinityMaskr<r�Zcpu_affinity)r>r�r�rCrDrrr�test_cpu_affinitys��zTestProcess.test_cpu_affinitycCs�t�tjtjt���}|�tj|�t	�
|�}t���
�}|j|dksLJ�|j|dks^J�|j|dkspJ�|j|dks�J�|j|dks�J�|j|dks�J�dS)NZReadOperationCountZWriteOperationCountZReadTransferCountZWriteTransferCountZOtherOperationCountZOtherTransferCount)rAr�r�r�r�r:r�r�r�r�ZGetProcessIoCountersr<r��io_countersZ
read_countZwrite_count�
read_bytes�write_bytes�other_countZother_bytesr�rrr�test_io_counterss�
zTestProcess.test_io_counterscCs�ddl}ddl}d}|jj�|d|j�}|�|jjj|�|j�	�}|jj�
||�|��|j}t
�|j���}||ks|J�dS)Nr�)�ctypesZctypes.wintypes�windllZkernel32r�r�r�r�ZwintypesZDWORDZGetProcessHandleCount�byref�valuer<r�r�)r>r�r�r�ZhndcntrCrDrrr�test_num_handles"s�

�zTestProcess.test_num_handlesc
Cs�t�}d|_tjd|d��vt�d��L}t��}t�tj��|�	�Wd�n1sZ0YWd�n1sx0YWd�n1s�0Y|j
dks�J�dS)Ni+z psutil._psplatform.cext.proc_cwd�Zside_effectz
time.sleepr@)�WindowsError�winerrorrr�r<r�rr�r��cwdZ
call_count)r>�excr�r�rrr�test_error_partial_copy4sbz#TestProcess.test_error_partial_copycCsTt��dd}tj�|�}t�tj��|��Wd�n1sF0YdS)Nr�i��)r<rw�_psplatformr�rr�r��exe)r>r�rHrrr�test_exe?szTestProcess.test_exeN)rrr�classmethodr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrrrrr�zs&

		r�c@s|eZdZdZedd��Zedd��Zdd�Zej	j
edd	�d
d��Zdd
�Z
dd�Ze�dd��Ze�dd��Zdd�ZdS)�TestProcessWMIz%Compare Process API results with WMI.cCst�j|_dSrFr�r�rrrr�KszTestProcessWMI.setUpClasscCst|j�dSrFr�r�rrrr�OszTestProcessWMI.tearDownClasscCs8t��j|jd�d}t�|j�}|��|jks4J�dS�Nrtr)rKrLrur�r<r�r�ZCaption�r>rOr�rrr�	test_nameSszTestProcessWMI.test_namez!unreliable path on GITHUB_ACTIONSrcCs@t��j|jd�d}t�|j�}|����|j��ks<J�dSr)	rKrLrur�r<r�rrbZExecutablePathr	rrrrYszTestProcessWMI.test_execCsFt��j|jd�d}t�|j�}d�|���|j�	dd�ksBJ�dS)Nrtrr^r�r#)
rKrLrur�r<r�r.r!ZCommandLinerar	rrrr�cszTestProcessWMI.test_cmdlinecCsPt��j|jd�d}t�|j�}|��\}}}d||f}|��|ksLJ�dS)Nrtrz%s\%s)rKrLrur�r<r�ZGetOwnerr�)r>rOr��domain�_r�rrrr�hs
zTestProcessWMI.test_usernamecCsBt��j|jd�d}t�|j�}|��j}|t|j	�ks>J�dSr)
rKrLrur�r<r�r�r�r9r�)r>rOr�r�rrr�test_memory_rssos
zTestProcessWMI.test_memory_rsscCs\t��j|jd�d}t�|j�}|��j}t|j	�}|||dfvrX|�
d||f��dS)Nrtrr�zwmi=%s, psutil=%s)rKrLrur�r<r�r�r�r9Z
PageFileUsagerc)r>rOr�r�Z	wmi_usagerrr�test_memory_vmsvs

zTestProcessWMI.test_memory_vmscCs\t��j|jd�d}t�|j�}t|j�d�d�}t	�
dt	�|����}||ksXJ�dS)Nrtrr�r�)
rKrLrur�r<r�r�ZCreationDater1�time�strftime�	localtimer�)r>rOr�Zwmic_createZ
psutil_createrrr�test_create_time�s�zTestProcessWMI.test_create_timeN)rrr�__doc__rr�r�r
rr[r\rrr�r�rr
rrrrrrrHs"

�


rc@sXeZdZdZedd��Zedd��Zdd�Zdd	�Zd
d�Z	dd
�Z
dd�Zdd�ZdS)�TestDualProcessImplementationawCertain APIs on Windows have 2 internal implementations, one
    based on documented Windows APIs, another one based
    NtQuerySystemInformation() which gets called as fallback in
    case the first fails because of limited permission error.
    Here we test that the two methods return the exact same value,
    see:
    https://github.com/giampaolo/psutil/issues/304.
    cCst�j|_dSrFr�r�rrrr��sz(TestDualProcessImplementation.setUpClasscCst|j�dSrFr�r�rrrr��sz+TestDualProcessImplementation.tearDownClasscCs�t�|j���}tjdttjd�d���}t�|j���}t	|�t	|�ksLJ�t
t	|��D]@}||dkslJ�||dks|J�t||||�dksXJ�qX|js�J�Wd�n1s�0YdS)Nz(psutil._psplatform.cext.proc_memory_info�msgr�ri)
r<r�r�r�rr��OSError�errno�EPERMrSr�rjr�)r>Zmem_1�funZmem_2r�rrrr��s
�z.TestDualProcessImplementation.test_memory_infocCslt�|j���}tjdttjd�d��2}t�|j���|ks@J�|j	sJJ�Wd�n1s^0YdS)N�"psutil._psplatform.cext.proc_timesrr�)
r<r�r�r�rr�rrrr�)r>�ctimerrrrr�s
�z.TestDualProcessImplementation.test_create_timecCs�t�|j���}tjdttjd�d��Z}t�|j���}|j	sBJ�t
|j|j�dksZJ�t
|j|j�dksrJ�Wd�n1s�0YdS)Nrrr�g{�G�z�?)
r<r�r�rTrr�rrrr�rj�user�system)r>Zcpu_times_1rZcpu_times_2rrr�test_cpu_times�s
�
z,TestDualProcessImplementation.test_cpu_timescCs�t�|j���}tjdttjd�d��X}t�|j���}t	t
|��D] }t||||�dksDJ�qD|jspJ�Wd�n1s�0YdS)Nz(psutil._psplatform.cext.proc_io_countersrr�r@)
r<r�r�r�rr�rrrr�rSrjr�)r>Z
io_counters_1rZ
io_counters_2r�rrrr��s
�z.TestDualProcessImplementation.test_io_counterscCslt�|j���}tjdttjd�d��2}t�|j���|ks@J�|j	sJJ�Wd�n1s^0YdS)Nz(psutil._psplatform.cext.proc_num_handlesrr�)
r<r�r�r�rr�rrrr�)r>r�rrrrr��s
�z.TestDualProcessImplementation.test_num_handlescCs�t��D]r}z tj|dd�}tj|dd�}Wn@tyl}z(t|�}t|tjtjf�sX�WYd}~qd}~00||ksJ�qdS)NT)Zuse_pebF)	r<rwr�Zproc_cmdlinerr�
isinstancer�r�)r>r��a�b�errrrrr��s�z*TestDualProcessImplementation.test_cmdlineN)
rrrrrr�r�r�rrr�r�r�rrrrr�s	

		rcspeZdZdZedd��ZddgZ�fdd�Z�fdd	�Zd
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�Z�ZS)�RemoteProcessTestCasez�Certain functions require calling ReadProcessMemory.
    This trivially works when called on the current process.
    Check that this works on other processes, especially when they
    have a different bitness.
    cCs\d}t�d�D]H}tj|d|gtjtjd�}|��\}}|��|tt�kr|SqdS)Nz6import sys; sys.stdout.write(str(sys.maxsize > 2**32))zC:\Python*\python.exe�-c)�args�stdout�stderr)	�glob�
subprocess�Popen�PIPE�STDOUT�communicater�r�r	)�code�filenamerH�outputrrrr�find_other_interpreter�s�z,RemoteProcessTestCase.find_other_interpreterr$zimport sys; sys.stdin.read()cs�t���|��}|dur$t�d��tr8tj|_||_	n||_tj|_	t
j��}t
t
���|d<|j|j	g|j|tjd�|_|j|jg|j|tjd�|_dS)Nz0could not find interpreter with opposite bitness�THINK_OF_A_NUMBER)�env�stdin)r�setUpr1rrr	�sys�
executableZpython64Zpython32r:r;�copyr�r�r�	test_argsr)r+�proc32�proc64)r>Zother_pythonr3��	__class__rrr5s&
�
��zRemoteProcessTestCase.setUpcs"t���|j��|j��dSrF)r�tearDownr:r-r;rUr<rrr>s

zRemoteProcessTestCase.tearDowncCs@t�|jj�}t|���dks"J�|��dd�|jks<J�dS�N�r$)r<r�r:r�rSr!r9r�rrr�test_cmdline_32!sz%RemoteProcessTestCase.test_cmdline_32cCs@t�|jj�}t|���dks"J�|��dd�|jks<J�dSr?)r<r�r;r�rSr!r9r�rrr�test_cmdline_64&sz%RemoteProcessTestCase.test_cmdline_64cCs&t�|jj�}|��t��ks"J�dSrF)r<r�r:r�rr:�getcwdr�rrr�test_cwd_32+sz!RemoteProcessTestCase.test_cwd_32cCs&t�|jj�}|��t��ks"J�dSrF)r<r�r;r�rr:rCr�rrr�test_cwd_64/sz!RemoteProcessTestCase.test_cwd_64cCs>t�|jj�}|��}d|vs"J�|dtt���ks:J�dS)Nr2)r<r�r:r�r;r�r:r�)r>r��errr�test_environ_323sz%RemoteProcessTestCase.test_environ_32cCs4t�|jj�}z|��Wntjy.Yn0dSrF)r<r�r;r�r;r�r�rrr�test_environ_649s
z%RemoteProcessTestCase.test_environ_64)rrrr�staticmethodr1r9r5r>rArBrDrErGrH�
__classcell__rrr<rr#�s
r#c@seZdZdd�Zdd�ZdS)�TestServicescCs`tgd��}tgd��}tgd��}t��D�],}|��}t|dt�sLJ�|d��s\J�t|dt�snJ�t|dt�s�J�|d|vs�J�|ddur�t�|d�t|d	t�s�J�t|dt�s�J�t|d
t�s�J�|d
|vs�J�|d|v�sJ�t|dt��sJ�|��}|du�r@t�|�}|�	��s@J�t�
|���}||ks,J�q,dS)N)�running�paused�start�pause�continue�stop�stopped)Z	automaticZmanual�disabled)rLrMZ
start_pendingZ
pause_pendingZcontinue_pendingZstop_pendingrRr��display_namer��statusr�ZbinpathZ
start_type�description)rvr<�win_service_iterZas_dictrr�r-r�r��
is_running�win_service_getr�)r>Zvalid_statusesZvalid_start_typesZservr5r�r��srrr�test_win_service_iterHs0		

z"TestServices.test_win_service_iterc	Cs�tjjj}tjjj}tt�����}t�	tj
��}t�|d�Wd�n1sT0Y|jj|dksrJ�t�|�}t
r�ddd|f}n|df}t|�}tjd|d��Dt�	tj
��|��Wd�n1s�0YWd�n1s�0Ytjd|d��Ft�	tj
��|��Wd�n1�s<0YWd�n1�s\0Yt
�rzddd|f}n|df}t|�}tjd|d��Ft�	tj��|��Wd�n1�s�0YWd�n1�s�0Ytjd|d��Ft�	tj��|��Wd�n1�s,0YWd�n1�sL0Y|��t|�v�slJ�|��t|�v�s�J�|��t|�v�s�J�|��t|�v�s�J�dS)Nz???rrz/psutil._psplatform.cext.winservice_query_statusr�z/psutil._psplatform.cext.winservice_query_config)r<rr��ERROR_SERVICE_DOES_NOT_EXIST�ERROR_ACCESS_DENIED�nextrWr�rr�r�rYr�r
r�rr�rUr�r�r�rTr�)r>r\r]r��cmZservicer%rrrr�test_win_service_gettsP�
,
�D�H�H�Hz!TestServices.test_win_service_getN)rrrr[r`rrrrrKFs,rK):rr�rr(r:r�r�r�r)r6r�warningsr<rZpsutil._compatrrrZpsutil.testsrrrr	r
rrr
rrrrrrr�catch_warnings�simplefilterrAr�r�rKZpsutil._pswindowsrrr�r[r\rr"r9r6r7r]r�r�rrr#rKrrrr�<module>s|

(�(#FOHW]PKok\�n�E0psutil/tests/__pycache__/test_osx.cpython-39.pycnu�[���a

��?h��@sdZddlZddlZddlZddlZddlmZddlmZddlmZddlm	Z	ddlm
Z
ddlmZdd	lmZdd
lm
Z
ddlmZddlmZdd
lmZer�ddlmZdd�Zdd�Zejjedd�Gdd�de��Zejjedd�Gdd�de��ZdS)zmacOS specific tests.�N)�MACOS)�POSIX)�HAS_BATTERY)�TOLERANCE_DISK_USAGE)�TOLERANCE_SYS_MEM)�PsutilTestCase)�pytest)�retry_on_failure)�sh)�spawn_testproc)�	terminate)�getpagesizecCs:t|�}|��d}z
t|�WSty4|YS0dS)zmExpects a sysctl command with an argument and parse the result
    returning only the value of interest.
    �N)r
�split�int�
ValueError)Zcmdline�out�result�r�A/usr/local/lib64/python3.9/site-packages/psutil/tests/test_osx.py�sysctls
rcCsHtd�}|�d�D]}||vrq,qtd��tt�d|��d��t�S)z)Wrapper around 'vm_stat' cmdline utility.�vm_stat�
zline not foundz\d+r)r
rrr�re�search�groupr
)�fieldr�linerrrr+srz
MACOS only��reasonc@s,eZdZedd��Zedd��Zdd�ZdS)�TestProcesscCst�j|_dS�N)r�pid��clsrrr�
setUpClass8szTestProcess.setUpClasscCst|j�dSr!)rr"r#rrr�
tearDownClass<szTestProcess.tearDownClasscCs�td|j�}|�dd���}|�d�d}|�d�d}t�|j���}|t�	dt�
|��ksdJ�|t�	dt�
|��ks~J�dS)	Nzps -o lstart -p %sZSTARTED�� ������z%H:%M:%Sz%Y)r
r"�replace�stripr�psutil�ProcessZcreate_time�time�strftime�	localtime)�self�outputZstart_psZhhmmss�yearZstart_psutilrrr�test_process_create_time@s
�
z$TestProcess.test_process_create_timeN)�__name__�
__module__�__qualname__�classmethodr%r&r5rrrrr 6s


r c@s�eZdZe�dd��Zdd�Zdd�Zejj	e
o:e��dkdd	�d
d��Z
dd
�Ze�dd��Ze�dd��Ze�dd��Ze�dd��Ze�dd��Ze�dd��Zdd�Zejj	edd	�dd��ZdS) �TestSystemAPIscCs�dd�}tjdd�D]j}t�|j�}||j�\}}}}|j|ksDJ�|j|ksRJ�t|j|�tkshJ�t|j	|�tksJ�qdS)NcSs�td|���}|�d�}|�d�|�d�}|��dd�\}}}}|dkrRd}t|�d}t|�d}t|�d}||||fS)Nz
df -k "%s"rr��noner'i)r
r,r�popr)�pathr�linesr�dev�total�used�freerrr�dfUs


z%TestSystemAPIs.test_disks.<locals>.dfF)�all)
r-Zdisk_partitions�
disk_usageZ
mountpointZdevicerA�absrCrrB)r2rD�part�usager@rArBrCrrr�
test_disksQs
zTestSystemAPIs.test_diskscCs td�}|tjdd�ksJ�dS)Nzsysctl hw.logicalcpuT��logical�rr-�	cpu_count�r2�numrrr�test_cpu_count_logicallsz%TestSystemAPIs.test_cpu_count_logicalcCs td�}|tjdd�ksJ�dS)Nzsysctl hw.physicalcpuFrKrMrOrrr�test_cpu_count_corespsz#TestSystemAPIs.test_cpu_count_cores�arm64zskipped due to #1892rcCsZt��}|jddtd�ks"J�|jddtd�ks<J�|jddtd�ksVJ�dS)Ni�zsysctl hw.cpufrequencyzsysctl hw.cpufrequency_minzsysctl hw.cpufrequency_max)r-Zcpu_freq�currentr�min�max)r2�freqrrr�
test_cpu_frequszTestSystemAPIs.test_cpu_freqcCstd�}|t��jksJ�dS)Nzsysctl hw.memsize)rr-�virtual_memoryrA)r2Zsysctl_hwphymemrrr�test_vmem_total�szTestSystemAPIs.test_vmem_totalcCs*td�}t��j}t||�tks&J�dS)NrC)rr-rYrCrGr�r2Z
vmstat_valZ
psutil_valrrr�test_vmem_free�s
zTestSystemAPIs.test_vmem_freecCs*td�}t��j}t||�tks&J�dS)N�active)rr-rYr]rGrr[rrr�test_vmem_active�s
zTestSystemAPIs.test_vmem_activecCs*td�}t��j}t||�tks&J�dS)N�inactive)rr-rYr_rGrr[rrr�test_vmem_inactive�s
z!TestSystemAPIs.test_vmem_inactivecCs*td�}t��j}t||�tks&J�dS)N�wired)rr-rYrarGrr[rrr�test_vmem_wired�s
zTestSystemAPIs.test_vmem_wiredcCs*td�}t��j}t||�tks&J�dS)NZPageins)rr-�swap_memory�sinrGrr[rrr�test_swapmem_sin�s
zTestSystemAPIs.test_swapmem_sincCs*td�}t��j}t||�tks&J�dS)NZPageout)rr-rcZsoutrGrr[rrr�test_swapmem_sout�s
z TestSystemAPIs.test_swapmem_soutc	Csrt����D]`\}}ztd|�}Wnty6Yq0|jd|vksNJ|��|jtt�	d|�d�ksJ�qdS)Nzifconfig %s�RUNNINGz	mtu (\d+)r)
r-Znet_if_stats�itemsr
�RuntimeErrorZisupZmturr�findall)r2�name�statsrrrr�test_net_if_stats�sz TestSystemAPIs.test_net_if_statsz
no batterycCs`td�}t�d|��d�}t�d|��d�}|dk}t��}|j|ksJJ�|jt|�ks\J�dS)Nz
pmset -g battz(\d+)%rzNow drawing from '([^']+)'zAC Power)	r
rrrr-Zsensors_battery�
power_plugged�percentr)r2rroZdrawing_fromrnZ
psutil_resultrrr�test_sensors_battery�sz#TestSystemAPIs.test_sensors_batteryN)r6r7r8r	rJrQrRr�mark�skipifr�platform�machinerXrZr\r^r`rbrerfrmrrprrrrr:Ls0
�






r:)�__doc__rsrr/r-rrZpsutil.testsrrrrrr	r
rrZpsutil._psutil_posixr
rrrqrrr r:rrrr�<module>s.PKok\�J�>C)C)2psutil/tests/__pycache__/test_linux.cpython-39.pycnu�[���a

��?h[d�@sdZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlmZddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*ddlm+Z+ddlm,Z,ddlm-Z-e�r�ddl.m/Z/dd l.m0Z0dd!l.m1Z1dd"l.m2Z2ej3�4ej3�5e6��Z7d#Z8d$Z9d%Z:d&Z;d'Z<e�r,d(Z=e�d)�Z>d*d+�Z?d,d-�Z@d.d/�ZAd0d1�ZBd2d3�ZCd4d5�ZDd6d7�ZEd8d9�ZFd:d;�ZGejHd<d=��ZIejHd>d?��ZJe'jKjLed@dA�GdBdC�dCe#��ZMe'jKjLed@dA�GdDdE�dEe#��ZNe'jKjLed@dA�GdFdG�dGe#��ZOe'jKjLed@dA�GdHdI�dIe#��ZPe'jKjLed@dA�GdJdK�dKe#��ZQe'jKjLed@dA�GdLdM�dMe#��ZRe'jKjLed@dA�GdNdO�dOe#��ZSe'jKjLed@dA�GdPdQ�dQe#��ZTe'jKjLed@dA�GdRdS�dSe#��ZUe'jKjLed@dA�GdTdU�dUe#��ZVe'jKjLed@dA�GdVdW�dWe#��ZWe'jKjLed@dA�e'jKjLe dXdA�GdYdZ�dZe#���ZXe'jKjLed@dA�Gd[d\�d\e#��ZYe'jKjLed@dA�Gd]d^�d^e#��ZZe'jKjLed@dA�Gd_d`�d`e#��Z[e'jKjLed@dA�Gdadb�dbe#��Z\e'jKjLed@dA�Gdcdd�dde#��Z]e'jKjLed@dA�Gdedf�dfe#��Z^e'jKjLed@dA�e'jKjLedgdA�Gdhdi�die#���Z_e'jKjLed@dA�Gdjdk�dke#��Z`e'jKjLed@dA�Gdldm�dme#��Zae'jKjLed@dA�Gdndo�doe#��Zbe'jKjLed@dA�Gdpdq�dqe#��Zce'jKjLed@dA�Gdrds�dse#��Zde'jKjLed@dA�Gdtdu�due#��ZedS)vzLinux specific tests.�)�divisionN)�LINUX)�PY3)�FileNotFoundError)�
basestring)�AARCH64)�GITHUB_ACTIONS)�GLOBAL_TIMEOUT)�HAS_BATTERY)�HAS_CPU_FREQ)�HAS_GETLOADAVG)�
HAS_RLIMIT)�PYPY)�PYTEST_PARALLEL)�	QEMU_USER)�TOLERANCE_DISK_USAGE)�TOLERANCE_SYS_MEM)�PsutilTestCase)�
ThreadTask)�
call_until)�mock)�pytest)�
reload_module)�retry_on_failure)�safe_rmpath)�sh)�skip_on_not_implemented)�which)�CLOCK_TICKS)�RootFsDeviceFinder)�calculate_avail_vmem)�open_binaryi�i�i'�i�i�iz/sys/class/hwmon/hwmon*cCs�ddl}|dd�}tr"t|d�}t�tjtj�}t�|��8t�|�	|�
�tt�
d|��dd��Wd�S1sz0YdS�Nr��ascii�256s��)�fcntlr�bytes�socket�AF_INET�
SOCK_DGRAM�
contextlib�closing�	inet_ntoa�ioctl�fileno�SIOCGIFADDR�struct�pack��ifnamer(�s�r8�C/usr/local/lib64/python3.9/site-packages/psutil/tests/test_linux.py�get_ipv4_addressNs
��r:cCs�ddl}|dd�}tr"t|d�}t�tjtj�}t�|��8t�|�	|�
�tt�
d|��dd��Wd�S1sz0YdSr")r(rr)r*r+r,r-r.r/r0r1�SIOCGIFNETMASKr3r4r5r8r8r9�get_ipv4_netmask]s
���r<cCs�ddl}|dd�}tr"t|d�}t�tjtj�}t�|��8t�|�	|�
�tt�
d|��dd��Wd�S1sz0YdSr")r(rr)r*r+r,r-r.r/r0r1�SIOCGIFBRDADDRr3r4r5r8r8r9�get_ipv4_broadcastls
���r>cCs�td��T}g}|D]"}|��}|d|kr|�|�qt|�dkrNtd|��Wd�n1sb0Ytt|��D]j}||d}g}tdt|�d�D]}|�|||d��q�d�|�}	t�tj	|	�}
t�
tj	|
�||<qx|S)Nz/proc/net/if_inet6���rzcould not find interface %r��:)�open�split�append�len�
ValueError�range�joinr*�	inet_pton�AF_INET6�	inet_ntop)r6�fZ
all_fields�line�fields�iZunformatted�groups�j�	formatted�packedr8r8r9�get_ipv6_addresses{s"
*
rTc	s�ddl}|dd�}tr"t|d�}t�tjtj�}t�|��n|�|�	�t
t�d|��}trfdd��nddl
}|j�d��fdd	�|d
d�D��dd�Wd�S1s�0YdS)
Nrr#r$r%cSs|S�Nr8��xr8r8r9�ord�szget_mac_address.<locals>.ord�csg|]}d�|��qS)z%02x:r8)�.0�char�rXr8r9�
<listcomp>��z#get_mac_address.<locals>.<listcomp>�r'r?)r(rr)r*r+r,r-r.r0r1�
SIOCGIFHWADDRr3r4�__builtin__rXrH)r6r(r7�inforar8r\r9�get_mac_address�s
�
rccCs�tddgddid�}|�d�}|D]F}|�d�r"|��\}}}}t�dd�}|t|�t|�t|��Sq"td	d�|���d
S)zQParse 'free' cmd and return swap memory's s total, used and free
    values.
    �free�-b�LANG�C.UTF-8��env�
ZSwapztotal used freez&can't find 'Swap' in 'free' output:
%sN)rrC�
startswith�collections�
namedtuple�intrFrH)�out�linesrM�_�total�usedrd�ntr8r8r9�	free_swap�s

�rucCs�tddgddid�}|�d�}|D]P}|�d�r"dd	�|��d
d�D�\}}}}t�dd�}||||||�Sq"td
d�|���dS)zSParse 'free' cmd and return physical memory's total, used
    and free values.
    rdrerfrgrhrjZMemcss|]}t|�VqdSrU)rn�rZrWr8r8r9�	<genexpr>�r^zfree_physmem.<locals>.<genexpr>��ztotal used free shared outputz%can't find 'Mem' in 'free' output:
%sN)rrCrkrlrmrFrH)rorprMrrrsrd�sharedrtr8r8r9�free_physmem�s

"��r{cCsZtddgddid�}|�d�D]*}|��}||vrt|�d�d�Sqtd	|��dS)
N�vmstatz-srfrgrhrj� rz can't find %r in 'vmstat' output)rrC�striprnrF)�statrorMr8r8r9r|�sr|cCs@tddg���}d|vr"t�d��tttt�d|�	�d���S)Nrdz-V�UNKNOWNzcan't determine free versionz\d+r?)
rr~r�skip�tuple�maprn�re�findallrC)ror8r8r9�get_free_version_info�s
r�c#sX��fdd�}t�trdnd}tj|d|d��}|VWd�n1sJ0YdS)z�Mock open() builtin and forces it to return a certain content
    for a given path. `pairs` is a {"path": "content", ...} dict.
    csZ|�vr@�|}tr4t|t�r(t�|�St�|�SqVt�|�Sn�|g|�Ri|��SdSrU)r�
isinstancer�io�StringIO�BytesIO)�name�args�kwargs�content��	orig_open�pairsr8r9�	open_mock�s

z$mock_open_content.<locals>.open_mock�
builtins.open�__builtin__.openT��create�side_effectN�rBrr�patch)r�r��patch_point�mr8r�r9�mock_open_content�s

r�c#sZ���fdd�}t�trdnd}tj|d|d��}|VWd�n1sL0YdS)zZMock open() builtin and raises `exc` if the path being opened
    matches `for_path`.
    cs(|�kr��n�|g|�Ri|��SdSrUr8�r�r�r���exc�for_pathr�r8r9r��sz&mock_open_exception.<locals>.open_mockr�r�Tr�Nr�)r�r�r�r�r�r8r�r9�mock_open_exception�s
r�z
LINUX only��reasonc@sLeZdZdd�Ze�dd��Ze�dd��Ze�dd��Ze�d	d
��ZdS)�"TestSystemVirtualMemoryAgainstFreecCs"t�j}t��j}||ksJ�dSrU)r{rr�psutil�virtual_memory��selfZ	cli_value�psutil_valuer8r8r9�
test_totals
z-TestSystemVirtualMemoryAgainstFree.test_totalcCsRt�dkrt�d��t�dkr(t�d��t�j}t��j}t||�tksNJ�dS)N��r���free version too old�r@rr�free version too recent)	r�rr�r{rsr�r��absrr�r8r8r9�	test_useds





z,TestSystemVirtualMemoryAgainstFree.test_usedcCs*t�j}t��j}t||�tks&J�dSrU)r{rdr�r�r�rr�r8r8r9�	test_free's
z,TestSystemVirtualMemoryAgainstFree.test_freecCsPt�}|j}|dkrt�d��t��j}t||�tksLJd|||jf��dS)Nrz%free does not support 'shared' column�	%s %s 
%s)	r{rzrr�r�r�r�r�output)r�rd�
free_valuer�r8r8r9�test_shared-s

��z.TestSystemVirtualMemoryAgainstFree.test_sharedcCsrtddg�}|�d�}d|dvr.t�d��n@t|d��d�}t��j}t||�t	ksnJd	|||f��dS)
Nrdrerj�	availablerz(free does not support 'available' columnrxr?r�)
rrCrr�rnr�r�r�r�r)r�rorpr�r�r8r8r9�test_available8s

��z1TestSystemVirtualMemoryAgainstFree.test_availableN)	�__name__�
__module__�__qualname__r�rr�r�r�r�r8r8r8r9r�s



r�c@sZeZdZdd�Ze�dd��Ze�dd��Ze�dd��Ze�d	d
��Ze�dd��Z	d
S)�$TestSystemVirtualMemoryAgainstVmstatcCs.td�d}t��j}t||�tks*J�dS)Nztotal memory�)r|r�r�rrr�r�r�Zvmstat_valuer�r8r8r9r�Js
z/TestSystemVirtualMemoryAgainstVmstat.test_totalcCsVt�dkrt�d��t�dkr(t�d��td�d}t��j}t||�tksRJ�dS)Nr�r�r�r�zused memoryr�)	r�rr�r|r�r�rsr�rr�r8r8r9r�Os





z.TestSystemVirtualMemoryAgainstVmstat.test_usedcCs.td�d}t��j}t||�tks*J�dS)Nzfree memoryr�)r|r�r�rdr�rr�r8r8r9r�as
z.TestSystemVirtualMemoryAgainstVmstat.test_freecCs.td�d}t��j}t||�tks*J�dS)Nz
buffer memoryr�)r|r�r��buffersr�rr�r8r8r9�test_buffersgs
z1TestSystemVirtualMemoryAgainstVmstat.test_bufferscCs.td�d}t��j}t||�tks*J�dS)Nz
active memoryr�)r|r�r��activer�rr�r8r8r9�test_activems
z0TestSystemVirtualMemoryAgainstVmstat.test_activecCs.td�d}t��j}t||�tks*J�dS)Nzinactive memoryr�)r|r�r��inactiver�rr�r8r8r9�
test_inactivess
z2TestSystemVirtualMemoryAgainstVmstat.test_inactiveN)
r�r�r�r�rr�r�r�r�r�r8r8r8r9r�Hs



r�c@sBeZdZdd�Ze�dd��Zdd�Zdd�Zd	d
�Zdd�Z	d
S)�TestSystemVirtualMemoryMocksc	Cs�t�d���}td|i���^}tjdd���.}t�d�t��}|j	sJJ�t
|�dksZJ�|d}dt|j�vstJ�d	t|j�vs�J�d
t|j�vs�J�dt|j�vs�J�dt|j�vs�J�d
t|j�vs�J�dt|j�vs�J�|j
dks�J�|jdks�J�|jdk�sJ�|jdk�sJ�|jdk�s,J�|jdk�s<J�|jdk�sLJ�Wd�n1�sb0YWd�n1�s�0YdS)NaL            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemAvailable:         -1 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            SReclaimable:     346648 kB
            �
/proc/meminfoT��record�alwaysrxrz#memory stats couldn't be determined�cachedrzr�r�r�r�)�textwrap�dedent�encoder��warnings�catch_warnings�simplefilterr�r��calledrE�str�messager�r�r�rzr�r��slab�r�r�r��ws�ret�wr8r8r9�test_warnings_on_misses|s,


z4TestSystemVirtualMemoryMocks.test_warnings_on_missescCs�i}td��:}|D]$}|��}t|d�d||d<qWd�n1sL0Yt|�}d|vr�|d}t||�|d}|dks�J�dS)Nr�rxr�rs
MemAvailable:�dr#)r!rCrnr r�)r�ZmemsrLrMrN�a�bZdiff_percentr8r8r9�test_avail_old_percent�s
8z3TestSystemVirtualMemoryMocks.test_avail_old_percentc	Cs�t�d���}td|i��v}tjdd��}t��}Wd�n1sF0Y|jsZJ�|j	dkshJ�|d}dt
|j�vs�J�Wd�n1s�0YdS)Na            Active:          9444728 kB
            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemAvailable:    6574984 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            SReclaimable:     346648 kB
            r�Tr�l �"r�,inactive memory stats couldn't be determined�r�r�r�r�r�r�r�r�r�r�r�r�r�r8r8r9� test_avail_old_comes_from_kernel�s&
�z=TestSystemVirtualMemoryMocks.test_avail_old_comes_from_kernelc	Cs�t�d���}td|i��v}tjdd��}t��}Wd�n1sF0Y|jsZJ�|j	dkshJ�|d}dt
|j�vs�J�Wd�n1s�0YdS)Nat            Active:          9444728 kB
            Active(anon):    6145416 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            r�Tr��`LGrr�r�r�r8r8r9�test_avail_old_missing_fields�s&
�z:TestSystemVirtualMemoryMocks.test_avail_old_missing_fieldsc
Cs�t�d���}td|i���tdttjd���ltj	dd��@}t
��}|jdksTJ�|d}d	t
|j�vsnJ�Wd�n1s�0YWd�n1s�0YWd�n1s�0YdS)
Na�            Active:          9444728 kB
            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            SReclaimable:     346648 kB
            r�z/proc/zoneinfo�no such file or directoryTr�r�rr�)r�r�r�r�r��IOError�errno�ENOENTr�r�r�r�r�r�r�)r�r�r�r�r�r8r8r9�test_avail_old_missing_zoneinfo�s
���z<TestSystemVirtualMemoryMocks.test_avail_old_missing_zoneinfocCs�t�d���}td|i���}t��}|js.J�|jdks<J�|jdksJJ�|j	dksXJ�|j
dksfJ�|jdkstJ�|jdks�J�|j
d	ks�J�|jd
ks�J�|jdks�J�Wd�n1s�0YdS)Na�            MemTotal:              100 kB
            MemFree:               2 kB
            MemAvailable:          3 kB
            Buffers:               4 kB
            Cached:                5 kB
            SwapCached:            6 kB
            Active:                7 kB
            Inactive:              8 kB
            Active(anon):          9 kB
            Inactive(anon):        10 kB
            Active(file):          11 kB
            Inactive(file):        12 kB
            Unevictable:           13 kB
            Mlocked:               14 kB
            SwapTotal:             15 kB
            SwapFree:              16 kB
            Dirty:                 17 kB
            Writeback:             18 kB
            AnonPages:             19 kB
            Mapped:                20 kB
            Shmem:                 21 kB
            Slab:                  22 kB
            SReclaimable:          23 kB
            SUnreclaim:            24 kB
            KernelStack:           25 kB
            PageTables:            26 kB
            NFS_Unstable:          27 kB
            Bounce:                28 kB
            WritebackTmp:          29 kB
            CommitLimit:           30 kB
            Committed_AS:          31 kB
            VmallocTotal:          32 kB
            VmallocUsed:           33 kB
            VmallocChunk:          34 kB
            HardwareCorrupted:     35 kB
            AnonHugePages:         36 kB
            ShmemHugePages:        37 kB
            ShmemPmdMapped:        38 kB
            CmaTotal:              39 kB
            CmaFree:               40 kB
            HugePages_Total:       41 kB
            HugePages_Free:        42 kB
            HugePages_Rsvd:        43 kB
            HugePages_Surp:        44 kB
            Hugepagesize:          45 kB
            DirectMap46k:          46 kB
            DirectMap47M:          47 kB
            DirectMap48G:          48 kB
            r�i�i�ipiTii iX�)r�r�r�r�r�r�r�rrrdr�r�rzr�r�r�r�)r�r�r�Zmemr8r8r9�test_virtual_memory_mockeds2
z7TestSystemVirtualMemoryMocks.test_virtual_memory_mockedN)
r�r�r�r�rr�r�r�r�r�r8r8r8r9r�zs$
r�c@s\eZdZedd��Zdd�Ze�dd��Ze�dd��Zd	d
�Z	dd�Z
d
d�Zdd�ZdS)�TestSystemSwapMemorycCs@td��}|��}Wd�n1s&0Yd|vo>d|vS)z3Return True if /proc/meminfo provides swap metrics.r�Nz
SwapTotal:z	SwapFree:)rB�read)rL�datar8r8r9�meminfo_has_swap_infoNs
&z*TestSystemSwapMemory.meminfo_has_swap_infocCs*t�j}t��j}t||�tks&J�dSrU)rurrr��swap_memoryr�r�r�r�r�r8r8r9r�Us
zTestSystemSwapMemory.test_totalcCs*t�j}t��j}t||�tks&J�dSrU)rursr�r�r�rr�r8r8r9r�Zs
zTestSystemSwapMemory.test_usedcCs*t�j}t��j}t||�tks&J�dSrU)rurdr�r�r�rr�r8r8r9r�`s
zTestSystemSwapMemory.test_freec	Cs�tjddd���}tjdd��r}t�d�t��}|js:J�t|�dksJJ�|d}dt	|j
�vsdJ�|jdksrJ�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)	N�psutil._common.openT�r�r�r�rxrz9'sin' and 'sout' swap memory stats couldn't be determined)
rr�r�r�r�r�r�r�rEr�r��sin�sout�r�r�r�r�r�r8r8r9�test_missing_sin_soutfs

��z*TestSystemSwapMemory.test_missing_sin_soutc	Cs�tdttjd����}tjdd��r}t�d�t��}|j	s>J�t
|�dksNJ�|d}dt|j�vshJ�|j
dksvJ�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)	Nz/proc/vmstatr�Tr�r�rxrzK'sin' and 'sout' swap memory stats couldn't be determined and were set to 0)r�r�r�r�r�r�r�r�r�r�rEr�r�r�r�r�r8r8r9�test_no_vmstat_mockedus �

��z*TestSystemSwapMemory.test_no_vmstat_mockedcCs�|��st�d��t�d��}t��}Wd�n1s:0Y|jrNJ�ddlm	}|�
�\}}}}}}}||9}||9}|j|ks�J�t|j
|�tks�J�dS)Nz!/proc/meminfo has no swap metricsz"psutil._pslinux.cext.linux_sysinfor)r�rr�rr�r�r�r�Zpsutil._psutil_linuxZ
_psutil_linuxZ
linux_sysinforrr�rdr)r�r��swapZcextrqrrrdZunit_multiplierr8r8r9�test_meminfo_against_sysinfo�s
&
z1TestSystemSwapMemory.test_meminfo_against_sysinfocCsBtddi��"}t��|js J�Wd�n1s40YdS)Nr�r^)r�r�r�r��r�r�r8r8r9�#test_emulate_meminfo_has_no_metrics�sz8TestSystemSwapMemory.test_emulate_meminfo_has_no_metricsN)
r�r�r��staticmethodr�r�rr�r�r�r�r�r�r8r8r8r9r�Ls


r�c@seZdZdd�ZdS)�TestSystemCPUTimescCs�t��j}t�dt��d�d}ttt	|�
d���}|dkrLd|vsXJ�nd|vsXJ�|dkrnd|vszJ�nd|vszJ�|d	kr�d
|vs�J�nd
|vs�J�dS)Nz
\d+\.\d+\.\d+�r�.)r����steal)r�rr'Zguest)r�r�rZ
guest_nice)r��	cpu_times�_fieldsr�r��os�unamer�r�rnrC)r�rNZ
kernel_verZkernel_ver_infor8r8r9�test_fields�s
zTestSystemCPUTimes.test_fieldsN)r�r�r�rr8r8r8r9r��sr�c@s�eZdZejjej�d�dd�dd��Z	ejjej�d�dd�dd	��Z
ejjed
�dd�dd
��Zejjed�dd�dd��Z
dd�ZdS)�TestSystemCPUCountLogical�/sys/devices/system/cpu/onlinez-/sys/devices/system/cpu/online does not existr�cCsjtd��}|����}Wd�n1s*0Ydt|�vrft|�d�d�d}t��|ksfJ�dS)Nr
�-rx)rBr�r~r�rnrCr��	cpu_count)r�rL�valuer8r8r9�test_against_sysdev_cpu_online�s

*z8TestSystemCPUCountLogical.test_against_sysdev_cpu_online�/sys/devices/system/cpuz&/sys/devices/system/cpu does not existcCs0t�d�}tdd�|D��}t��|ks,J�dS)NrcSs g|]}t�d|�dur|�qS)zcpu\d+$N)r��searchrvr8r8r9r]�r^zITestSystemCPUCountLogical.test_against_sysdev_cpu_num.<locals>.<listcomp>)r�listdirrEr�r)r�Zls�countr8r8r9�test_against_sysdev_cpu_num�s
z5TestSystemCPUCountLogical.test_against_sysdev_cpu_numZnprocznproc utility not availablecCs$ttd��}tjdd�|ks J�dS)Nznproc --allT��logical)rnrr�r)r��numr8r8r9�test_against_nproc�sz,TestSystemCPUCountLogical.test_against_nproc�lscpu�lscpu utility not availablecCs8td�}tdd�|�d�D��}tjdd�|ks4J�dS)N�lscpu -pcSsg|]}|�d�s|�qS)�#�rkrvr8r8r9r]�r^z@TestSystemCPUCountLogical.test_against_lscpu.<locals>.<listcomp>rjTr)rrErCr�r)r�rorr8r8r9�test_against_lscpu�sz,TestSystemCPUCountLogical.test_against_lscpuc	Cs�ddl}|j��}tjdtd���`}|j��|ks6J�|js@J�tjddd��F}|j��dusbJ�|jdkspJ�|jdddks�J�Wd�n1s�0Yt	d	d
��}|�
�}Wd�n1s�0Yt�|�}tjd|dd��$}|j��|k�sJ�Wd�n1�s0Yt
d	di��0}|j��|k�sHJ�|j�sTJ�Wd�n1�sj0YWd�n1�s�0YdS)
Nrzpsutil._pslinux.os.sysconf�r�r�Tr�r��
/proc/stat�
/proc/cpuinfo�rb��return_valuer�r^)�psutil._pslinux�_pslinuxZcpu_count_logicalrr�rFr�Z
call_countZ	call_argsrBr�r�r�r�)r�r��originalr�rLZcpuinfo_data�	fake_filer8r8r9�test_emulate_fallbacks�s.
�
4&
�4z0TestSystemCPUCountLogical.test_emulate_fallbacksN)r�r�r�r�mark�skipifr�path�existsrrrrrr(r8r8r8r9r	�s&�
�

�

�
r	c@s:eZdZejjed�dd�dd��Zdd�Zdd	�Z	d
S)�TestSystemCPUCountCoresrrr�cCs\td�}t�}|�d�D]&}|�d�s|�d�}|�|d�qtjdd�t|�ksXJ�dS)Nrrjr�,rxFr)r�setrCrk�addr�rrE)r�roZcore_idsrMrNr8r8r9rs

z*TestSystemCPUCountCores.test_against_lscpucCsdtj��}tjdgd��$}tj��}|js.J�Wd�n1sB0Y|dur`||ks`J�dS)N�	glob.glob�r#)r�r%�cpu_count_coresrr�r�)r�Zmeth_1r�Zmeth_2r8r8r9�
test_method_2s

(z%TestSystemCPUCountCores.test_method_2c	Cs�tjdgd��P}tjddd��"}tj��dus2J�Wd�n1sF0YWd�n1sd0Y|jsxJ�|js�J�dS)Nr1r2r�Tr�)rr�r�r%r3r�)r��m1�m2r8r8r9�test_emulate_nones
N
z)TestSystemCPUCountCores.test_emulate_noneN)
r�r�r�rr)r*rrr4r7r8r8r8r9r-s
�
	r-c@s�eZdZejjedd�dd��Zejjedd�ejjedd�dd���Z	ejjedd�dd	��Z
ejjedd�d
d��Zejjedd�dd
��ZdS)�TestSystemCPUFrequency�
not supportedr�csT�fdd�}tjj�tjd|dd��t��s2J�Wd�n1sF0YdS)Ncs|�d�rdS�|�SdS)N�&/sys/devices/system/cpu/cpufreq/policyFr�r+�Zorig_existsr8r9�path_exists_mock(s
zMTestSystemCPUFrequency.test_emulate_use_second_file.<locals>.path_exists_mock�os.path.existsT)r�r�)rr+r,rr�r��cpu_freq)r�r=r8r<r9�test_emulate_use_second_file%s�z3TestSystemCPUFrequency.test_emulate_use_second_filez,aarch64 does not report mhz in /proc/cpuinfocs��fdd�}tjj�z�tjd|d��xttj�t��}|sDJ|��|j	dksRJ�|j
dks`J�tjdd�D] }|j	dks~J�|j
dkslJ�qlWd�n1s�0YWttj�tt�nttj�tt�0dS)Ncs|�d�rdS�|�SdS)Nz/sys/devices/system/cpu/Frr;�Zos_path_existsr8r9r=;s
zITestSystemCPUFrequency.test_emulate_use_cpuinfo.<locals>.path_exists_mockr>r�T�Zpercpu)rr+r,rr�rr�r%r?�max�min)r�r=r��freqr8rAr9�test_emulate_use_cpuinfo4s 
0

�
z/TestSystemCPUFrequency.test_emulate_use_cpuinfoc	s��fdd�}t�trdnd}tj||d���tjddd��Vt��}|jd	ksRJ�|jd
krj|jdksjJ�|jd
kr�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)
Ncs�|�d�r|�d�rt�d�S|�d�r<|�d�r<t�d�S|�d�rZ|�d�rZt�d�S|dkrlt�d	�S�|g|�Ri|��SdS)
N�/scaling_cur_freqr:�500000�/scaling_min_freq�600000�/scaling_max_freqs700000r scpu MHz     : 500��endswithrkr�r�r��r�r8r9r�Rs�
�
�

z;TestSystemCPUFrequency.test_emulate_data.<locals>.open_mockr�r�rr>Tr2�@@rB���@g�@�	rBrrr�r�r?�currentrErD�r�r�r�rFr8rOr9�test_emulate_dataPs

z(TestSystemCPUFrequency.test_emulate_datac
sb�fdd�}t�trdnd}tj||d��� tjddd���tjd	d
d���tjdd�}|djd
kslJ�|djdkr�|djdks�J�|djdkr�|djdks�J�|djdks�J�|djdkr�|djdks�J�|djdkr�|djdks�J�Wd�n1�s0YWd�n1�s40YWd�n1�sT0YdS)Ncs�|}|�d�r"|�d�r"t�d�S|�d�r@|�d�r@t�d�S|�d�r^|�d�r^t�d�S|�d�r||�d�r|t�d	�S|�d�r�|�d�r�t�d
�S|�d�r�|�d�r�t�d�S|dkr�t�d
�S�|g|�Ri|��SdS)NrHz'/sys/devices/system/cpu/cpufreq/policy0s100000rJ�200000rLs300000z'/sys/devices/system/cpu/cpufreq/policy1s400000rIrKr s#cpu MHz     : 100
cpu MHz     : 400rM)r�r�r��nrOr8r9r�ss8�
�
�
�
�
�

z@TestSystemCPUFrequency.test_emulate_multi_cpu.<locals>.open_mockr�r�rr>Tr2�!psutil._pslinux.cpu_count_logicalr�rCr�Y@rBgi@g�r@rxgy@rPrQrRrTr8rOr9�test_emulate_multi_cpuqs&�z-TestSystemCPUFrequency.test_emulate_multi_cpuc
s��fdd�}t�trdnd}tj||d���tjddd��Ttjd	d
d��&t��}|jdksbJ�Wd�n1sv0YWd�n1s�0YWd�n1s�0YdS)NcsX|�d�rttjd��n<|�d�r,t�d�S|dkr>t�d�S�|g|�Ri|��SdS)NrHrYz/cpuinfo_cur_freqrVr scpu MHz     : 200)rNr�r�r�r�r�r�rOr8r9r��s



zOTestSystemCPUFrequency.test_emulate_no_scaling_cur_freq_file.<locals>.open_mockr�r�rr>Tr2rXrx��)rBrrr�r�r?rSrTr8rOr9�%test_emulate_no_scaling_cur_freq_file�s
�z<TestSystemCPUFrequency.test_emulate_no_scaling_cur_freq_fileN)
r�r�r�rr)r*rr@rrGrUrZr\r8r8r8r9r8#s
�
 
3r8c@seZdZdd�ZdS)�TestSystemCPUStatscCs*td�}t��j}t||�dks&J�dS)N�
interruptsi�)r|r�Z	cpu_statsr^r�r�r8r8r9�test_interrupts�s
z"TestSystemCPUStats.test_interruptsN)r�r�r�r_r8r8r8r9r]�s	r]c@s&eZdZejjedd�dd��ZdS)�TestLoadAvgr9r�cCs�t��}td��}|����}Wd�n1s20Ytt|d�|d�dks\J�tt|d�|d�dks|J�tt|d�|d�dks�J�dS)Nz
/proc/loadavgrrxr�)r��
getloadavgrBr�rCr��float)r�r�rLZ
proc_valuer8r8r9�test_getloadavg�s
*  zTestLoadAvg.test_getloadavgN)r�r�r�rr)r*rrcr8r8r8r9r`�sr`c@seZdZdd�ZdS)�TestSystemNetIfAddrscCs�t����D]�\}}|D]�}|jtjkr<|jt|�ks�J�q|jtjkr�|jt	|�ksZJ�|j
t|�kslJ�|jdur�|jt
|�ks�J�q�t
|�dks�J�q|jtjkr|j�d�d}|t|�vsJ�qqdS)Nz0.0.0.0�%r)r�Znet_if_addrs�items�familyZAF_LINK�addressrcr*r+r:�netmaskr<�	broadcastr>rJrCrT)r�r��addrs�addrrhr8r8r9�test_ips�s
zTestSystemNetIfAddrs.test_ipsN)r�r�r�rmr8r8r8r9rd�srd�QEMU user not supportedc@sPeZdZejjed�dd�dd��Zdd�Zejjed�dd�dd	��Z	d
S)�TestSystemNetIfStats�ifconfig�ifconfig utility not availabler�c	Csrt����D]`\}}ztd|�}Wnty6Yq0|jd|vksNJ|��|jtt�	d|�d�ksJ�qdS)N�ifconfig %s�RUNNINGz(?i)MTU[: ](\d+)r)
r��net_if_statsrfr�RuntimeErrorZisup�mturnr�r�)r�r��statsror8r8r9�test_against_ifconfig	s�z*TestSystemNetIfStats.test_against_ifconfigc	Cs`t����D]N\}}td|��*}|jt|�����ks<J�Wd�q1sP0YqdS)Nz/sys/class/net/%s/mtu)r�rtrfrBrvrnr�r~)r�r�rwrLr8r8r9�test_mtuszTestSystemNetIfStats.test_mtuc	Cs
d}t����D]�\}}ztd|�}Wnty:Yq0t�d|�}|r�t|���dkr�|d7}t	|�
d����d��}t	|j
�d��}||ks�J�qt�d|�}|rt|���dkr|d7}t	|�
d������}t	|j
�d��}||ksJ�q|�s|�d	��dS)
Nrrrzflags=(\d+)?<(.*?)>r�rxr.z(.*)  MTU:(\d+)  Metric:(\d+)r�zno matches were found)r�rtrfrrur�rrErPr/�group�lowerrC�flags�fail)r�Z
matches_foundr�rwro�matchZifconfig_flagsZpsutil_flagsr8r8r9�
test_flagss(zTestSystemNetIfStats.test_flagsN)
r�r�r�rr)r*rrxryrr8r8r8r9ros
�

�roc@s0eZdZejjed�dd�e�dd���ZdS)�TestSystemNetIOCountersrprqr�c	Cs$dd�}tjddd�}|��D�]�\}}z||�}WntyJYqYn0t|j|d�dksfJ�t|j|d�dks�J�t|j|d	�d
ks�J�t|j|d�d
ks�J�t|j	|d�d
ks�J�t|j
|d�d
ks�J�t|j|d�d
k�sJ�t|j|d�d
ksJ�qdS)NcSs�i}td|�}tt�d|�d�|d<tt�d|�d�|d<tt�d|�d�|d<tt�d|�d	�|d
<tt�d|�d�|d<tt�d|�d	�|d
<tt�d|�d�|d<tt�d|�d�|d<|S)NrrzRX packets[: ](\d+)r�packets_recvzTX packets[: ](\d+)�packets_sentzerrors[: ](\d+)�errinrx�erroutzdropped[: ](\d+)�dropin�dropoutz#RX (?:packets \d+ +)?bytes[: ](\d+)�
bytes_recvz#TX (?:packets \d+ +)?bytes[: ](\d+)�
bytes_sent)rrnr�r�)Znicr�ror8r8r9rpEs&����z?TestSystemNetIOCounters.test_against_ifconfig.<locals>.ifconfigTF)Zpernic�nowrapr�i(r�r�r�r�r��
r�r�r�)
r��net_io_countersrfrur�r�r�r�r�r�r�r�r�)r�rpZnior�rwZifconfig_retr8r8r9rx@s&
����z-TestSystemNetIOCounters.test_against_ifconfigN)	r�r�r�rr)r*rrrxr8r8r8r9r�>s

�r�c@s8eZdZejded�ejddd�dd���Zdd	�Zd
S)�TestSystemNetConnectionsz psutil._pslinux.socket.inet_ntoprzpsutil._pslinux.supports_ipv6Fr2cCsPz*t�tjtj�}|�|j�|�d�Wntjy>Yn0tjdd�dS)N)z::1rZinet6��kind)	r*rJ�SOCK_STREAMZ
addCleanup�close�bind�errorr��net_connections)r�Z
supports_ipv6rKr7r8r8r9�test_emulate_ipv6_unsupportedtsz6TestSystemNetConnections.test_emulate_ipv6_unsupportedcCsPt�d�}td|i��&}tjdd�|js.J�Wd�n1sB0YdS)Na            0: 00000003 000 000 0001 03 462170 @/tmp/dbus-Qw2hMPIU3n
            0: 00000003 000 000 0001 03 35010 @/tmp/dbus-tB2X8h69BQ
            0: 00000003 000 000 0001 03 34424 @/tmp/dbus-cHy80Y8O
            000000000000000000000000000000000000000000000000000000
            z/proc/net/unix�unixr�)r�r�r�r�r�r�)r�r�r�r8r8r9�test_emulate_unix�s
z*TestSystemNetConnections.test_emulate_unixN)r�r�r�rr�rFr�r�r8r8r8r9r�rs
r�c@sBeZdZejjeed�dd�e�dd���Z	dd�Z
dd	�Zd
S)�TestSystemDiskPartitions�statvfszos.statvfs() not availabler�cCsvdd�}tjdd�D]\}t�|j�}||j�\}}}}|j|ksDJ�t|j|�tksZJ�t|j|�tksJ�qdS)NcSsztd|���}|�d�}|�d�|�d�}|��dd�\}}}}|dkrRd}t|�t|�t|�}}}||||fS)Nzdf -P -B 1 "%s"rjrr@�nonerY)rr~rC�poprn)r+rorprM�devrrrsrdr8r8r9�df�s


z4TestSystemDiskPartitions.test_against_df.<locals>.dfF)�all)	r��disk_partitions�
disk_usageZ
mountpointrrr�rdrrs)r�r��part�usagerqrrrsrdr8r8r9�test_against_df�sz(TestSystemDiskPartitions.test_against_dfc	Cstd��}|��}Wd�n1s&0Yd|vr`t��D]}|jdkr@q^q@|�d��n�t�d�}tj	d|dd��v}tj	dd	gd
��F}t��}|j
s�J�|j
s�J�|s�J�|djdks�J�Wd�n1s�0YWd�n1s�0YdS)Nz/proc/filesystems�zfszcouldn't find any ZFS partitionz
nodev	zfs
r�Tr"�$psutil._pslinux.cext.disk_partitions)z	/dev/sdb3�/r��rwr2r)rBr�r�r�Zfstyper}r�r�rr�r�)r�rLr�r�r'r5r6r�r8r8r9�test_zfs_fs�s,
&

��

z$TestSystemDiskPartitions.test_zfs_fsc	Cs�zttjddd��L}t�t��t��Wd�n1s:0Y|jsNJ�Wd�n1sb0YWdt_ndt_0dS)Nzos.path.realpathz
/non/existentr2�/proc)	rr�r�raisesrr�r�r��PROCFS_PATHr�r8r8r9�test_emulate_realpath_fail�s�&*z3TestSystemDiskPartitions.test_emulate_realpath_failN)r�r�r�rr)r*�hasattrrrr�r�r�r8r8r8r9r��s�r�c@sDeZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	dS)�TestSystemDiskIoCountersc	Cs�d}td|i���tjddd���tjdd�}|jdks<J�|jd	ksJJ�|jd
tks\J�|j	dksjJ�|j
dksxJ�|jd
ks�J�|jdtks�J�|j
dks�J�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)Nz+   3     0   1 hda 2 3 4 5 6 7 8 9 10 11 12�/proc/diskstats�!psutil._pslinux.is_storage_deviceTr2F�r�rxr�r�r@ryr��r��r�rr�r��disk_io_counters�
read_count�read_merged_count�
read_bytes�SECTOR_SIZE�	read_time�write_count�write_merged_count�write_bytes�
write_time�	busy_time�r�r�r�r8r8r9�test_emulate_kernel_2_4�s�z0TestSystemDiskIoCounters.test_emulate_kernel_2_4c	Cs�d}td|i���tjddd���tjdd�}|jdks<J�|jd	ksJJ�|jd
tks\J�|j	dksjJ�|j
dksxJ�|jd
ks�J�|jdtks�J�|j
dks�J�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)Nz'   3    0   hda 1 2 3 4 5 6 7 8 9 10 11r�r�Tr2Fr�rxr�r�r@ryrr�r�r�r�r�r8r8r9�test_emulate_kernel_2_6_full�s�z5TestSystemDiskIoCounters.test_emulate_kernel_2_6_fullc	Cs�tddi���tjddd���tjdd�}|jdks8J�|jd	tksJJ�|jd
ksXJ�|j	dtksjJ�|j
dksxJ�|jdks�J�|jdks�J�|j
dks�J�|jdks�J�Wd�n1s�0YWd�n1s�0YdS)
Nr�z   3    1   hda 1 2 3 4r�Tr2Fr�rxr�r�r@r)r�rr�r�r�r�r�r�r�r�r�r�r�r�r�)r�r�r8r8r9�test_emulate_kernel_2_6_limited�s�z8TestSystemDiskIoCounters.test_emulate_kernel_2_6_limitedc	Cs�t�d�}td|i���tjddd��vtjddd�}t|�dksFJ�|d	jd
ksXJ�|djd
ksjJ�|d	j	dks|J�|dj	dks�J�Wd�n1s�0YWd�n1s�0YdS)
N�x            3    0   nvme0n1 1 2 3 4 5 6 7 8 9 10 11
            3    0   nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11
            r�r�Fr2T��perdiskr�r��nvme0n1rxZ	nvme0n1p1ry)
r�r�r�rr�r�r�rEr�r�r�r8r8r9�test_emulate_include_partitionss
�z8TestSystemDiskIoCounters.test_emulate_include_partitionsc	Cst�d�}td|i��Xtjddd��*tjddd�}|dusBJ�Wd�n1sV0YWd�n1st0Ydd�}t�d�}td|i��jtjdd	|d
��:tjddd�}|jdks�J�|jdks�J�Wd�n1s�0YWd�n1�s0YdS)
Nr�r�r�Fr2r�cSs|dkS)Nr�r8)r�r8r8r9�is_storage_device4szSTestSystemDiskIoCounters.test_emulate_exclude_partitions.<locals>.is_storage_deviceTr�rxry)	r�r�r�rr�r�r�r�r�)r�r�r�r�r8r8r9�test_emulate_exclude_partitions%s$
�H
�z8TestSystemDiskIoCounters.test_emulate_exclude_partitionscCshdd�}tjdd�}tjdd|d��tjdd�}Wd�n1sF0Yt|�t|�ksdJ�dS)NcSs|dkS)Nr�r8r;r8r8r9r,Fsz?TestSystemDiskIoCounters.test_emulate_use_sysfs.<locals>.existsT)r��psutil._pslinux.os.path.existsr�)r�r�rr�rE)r�r,ZwprocfsZwsysfsr8r8r9�test_emulate_use_sysfsEs�*z/TestSystemDiskIoCounters.test_emulate_use_sysfsc	Csndd�}tjdd|d��Bt�t��t��Wd�n1sB0YWd�n1s`0YdS)NcSsdS)NFr8r;r8r8r9r,Qsz>TestSystemDiskIoCounters.test_emulate_not_impl.<locals>.existsr�Tr�)rr�rr��NotImplementedErrorr�r�)r�r,r8r8r9�test_emulate_not_implPs�z.TestSystemDiskIoCounters.test_emulate_not_implN)
r�r�r�r�r�r�r�r�r�r�r8r8r8r9r��s r�c@sjeZdZdd�Zdd�Zejjedd�dd��Z	ejje
d	�d
d�ejjedd�dd���Zd
d�ZdS)�TestRootFsDeviceFindercCs(t�d�j}t�|�|_t�|�|_dS)Nr�)rr�st_dev�major�minor)r�r�r8r8r9�setUp]szTestRootFsDeviceFinder.setUpcCs�t�}tj�d�r|��n2t�t��|��Wd�n1sD0Ytj�d|j|j	f�rp|�
�n2t�t��|�
�Wd�n1s�0Y|��dS�Nz/proc/partitionsz/sys/dev/block/%s:%s/uevent)rrr+r,�ask_proc_partitionsrr�rr�r��ask_sys_dev_block�ask_sys_class_block)r��finderr8r8r9�test_call_methodsbs
&�
&z(TestRootFsDeviceFinder.test_call_methodszunsupported on GITHUB_ACTIONSr�cCs�t�}|��dusJ�d}}}tj�d�r6|��}tj�d|j|jf�rV|��}|�	�}|ph|ph|}|r~|r~||ks~J�|r�|r�||ks�J�|r�|r�||ks�J�dSr�)
r�findrr+r,r�r�r�r�r�)r�r�r�r��c�baser8r8r9�test_comparisonsrs"�z'TestRootFsDeviceFinder.test_comparisonsZfindmntzfindmnt utility not availablecCs"t���}td�}||ksJ�dS)Nzfindmnt -o SOURCE -rn /)rr�r)r�r�Z
findmnt_valuer8r8r9�test_against_findmnt�s
z+TestRootFsDeviceFinder.test_against_findmntcCs�tjddgd��\}t��d}|js(J�tsP|jdks:J�|jt���ks^J�n|jdks^J�Wd�n1sr0YdS)Nr�)�	/dev/rootr�Zext4r�r2rr�)	rr�r�r�r�rZdevicerr�)r�r�r�r8r8r9�test_disk_partitions_mocked�s�
z2TestRootFsDeviceFinder.test_disk_partitions_mockedN)
r�r�r�r�r�rr)r*rr�rr�r�r8r8r8r9r�[s

�r�c@sbeZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Ze	�e
jje
d
d�dd���Zdd�ZdS)�TestMisccCs(td�}t��}t|�t|�ks$J�dS)Nz	boot time)r|r��	boot_timernr�r8r8r9�test_boot_time�szTestMisc.test_boot_timec	sb|��}t�|�ttj�|d�d��.}|�d�|�d�|�d�Wd�n1sZ0Y�z�t��fdd�}tr�dnd	}tj	||d
���~t
t�t�
t��t��Wd�n1s�0Yt�
t��tjdd�Wd�n1s�0Yt�
t��t��Wd�n1�s00Yt�
t��tjdd�Wd�n1�sh0Yt�
t��t��Wd�n1�s�0Yt�
t��tjdd�Wd�n1�s�0Y|t_t��d
k�s�J�tt���d
k�sJ�tjdd�}t|�d
k�s*J�tjdd�}ttt|��d
k�sNJ�ttj�|d�d��.}|�d�|�d�|�d�Wd�n1�s�0Yt��d
k�s�J�ttjdd��d
k�s�J�tt���d
k�s�J�ttttjdd���d
k�sJ�Wd�n1�s0YWt�|�t
t�nt�|�t
t�0tjdk�s^J�dS)Nrr�zcpu   0 0 0 0 0 0 0 0 0 0
zcpu0  0 0 0 0 0 0 0 0 0 0
zcpu1  0 0 0 0 0 0 0 0 0 0
cs,|�d�rttjd���|g|�Ri|��S)Nr�zrejecting access for test)rkr�r�r�r�rOr8r9r��s
z4TestMisc.test_no_procfs_on_import.<locals>.open_mockr�r�rTrCrzcpu   1 0 0 0 0 0 0 0 0 0
zcpu0  1 0 0 0 0 0 0 0 0 0
zcpu1  1 0 0 0 0 0 0 0 0 0
r�)�
get_testfnr�mkdirrBr+rH�writerrr�rr�rr�r�r�cpu_percent�cpu_times_percentr��sumr��shutil�rmtree)r�Z	my_procfsrLr�r�Zper_cpu_percentZper_cpu_times_percentr8rOr9�test_no_procfs_on_import�sZ


(&*(,(,

*�*

�

z!TestMisc.test_no_procfs_on_importcCsjt�d���}td|i��B}t��|js.J�tjdd�t��tjdd�Wd�n1sb0Yt�d���}td|i���t��}|js�J�tjdd�}t��}tjdd�}|dks�J�t|�dks�J�t|�dks�J�t|�dks�J�tt	t|��dk�sJ�tt	t|��dk�s&J�|j
dk�s6J�|jdk�sFJ�Wd�n1�s\0YdS)Nz~            cpu   0 0 0 0 0 0 0 1 0 0
            cpu0  0 0 0 0 0 0 0 1 0 0
            cpu1  0 0 0 0 0 0 0 1 0 0
            rTrCz~            cpu   1 0 0 0 0 0 0 0 0 0
            cpu0  1 0 0 0 0 0 0 0 0 0
            cpu1  1 0 0 0 0 0 0 0 0 0
            rrY)r�r�r�r�r�r�r�r�r�r�r�user)r�r�r�r�Zcpu_percent_percpur�Zcpu_times_percent_percpur8r8r9�test_cpu_steal_decrease�s,
*
z TestMisc.test_cpu_steal_decreasec	Csptjddd��N}t�t��tj��Wd�n1s:0Y|jsNJ�Wd�n1sb0YdS)Nr�Tr�)	rr�rr�rur�r%r�r�r�r8r8r9�test_boot_time_mockeds(zTestMisc.test_boot_time_mockedcCs t��D]}|jdvsJ�qdS)N)z:0z:0.0)r�Zusers�host)r�r�r8r8r9�
test_usersszTestMisc.test_userscCs|��}t�|��z�|t_t�t��t��Wd�n1sD0Yt�t��t�	�Wd�n1sv0Yt�t��tj	dd�Wd�n1s�0Yt�t��t�
�Wd�n1s�0Yt�t��t��Wd�n1�s0Yt�t��t��Wd�n1�sF0Yt�t��t�
�Wd�n1�sz0Yt�t��t��Wd�n1�s�0Yt�tj��t��Wd�n1�s�0YWdt_ndt_0dS)NTrCr�)r�rr�r�r�rr�r�r�rr�r�r�rtr�Z
NoSuchProcess�Process)r�Ztdirr8r8r9�test_procfs_path s.
&&*&((((*zTestMisc.test_procfs_pathzskip if pytest-parallelr�cCs�t��~t��}|��}t|�tr&dndks0J�t|dd�d�dj}|j|ksTJ�t�|�}|�	�|t�
�vsvJ�Wd�n1s�0YdS)Nr�r�cSs|jSrU)�idrVr8r8r9�<lambda>Hr^z)TestMisc.test_issue_687.<locals>.<lambda>)�keyrx)rr�r��threadsrEr�sortedr��pidZas_dictZpids)r��pr��tid�ptr8r8r9�test_issue_687<s
zTestMisc.test_issue_687cCsLtddi��,}t�t���s J�|js*J�Wd�n1s>0YdS)N�/proc/%s/statusrY)r�r�Z
pid_existsr�getpidr�r�r8r8r9�test_pid_exists_no_proc_statusNsz'TestMisc.test_pid_exists_no_proc_statusN)r�r�r�r�r�r�r�r�r�rrr)r*rr�r�r8r8r8r9r��sB'r�z
no batteryc@sjeZdZejjed�dd�dd��Zdd�Zdd	�Z	d
d�Z
dd
�Zdd�Zdd�Z
dd�Zdd�ZdS)�TestSensorsBatteryZacpizacpi utility not availabler�cCsHtd�}t|�d�d���dd��}t��j}t||�dksDJ�dS)Nzacpi -br.rxrerY)	rrnrCr~�replacer��sensors_battery�percentr�)r�roZ
acpi_valuer�r8r8r9�test_percent_s
zTestSensorsBattery.test_percentcs~�fdd�}t�trdnd}tj||d��@}t��jdus>J�t��jtjksRJ�|j	s\J�Wd�n1sp0YdS)Ncs.|�d�rt�d�S�|g|�Ri|��SdS)N�z
AC0/onlinez	AC/online�1�rNr�r�r�rOr8r9r�hs

z@TestSensorsBattery.test_emulate_power_plugged.<locals>.open_mockr�r�rT)
rBrrr�r�r�
power_pluggedZsecsleftZPOWER_TIME_UNLIMITEDr��r�r�r�r�r8rOr9�test_emulate_power_pluggedfs��z-TestSensorsBattery.test_emulate_power_pluggedcsj�fdd�}t�trdnd}tj||d��,}t��jdus>J�|jsHJ�Wd�n1s\0YdS)NcsF|�d�rttjd��n*|�d�r,t�d�S�|g|�Ri|��SdS)NrrY�/statusZcharging�rNr�r�r�r�r�r�rOr8r9r�{s



zBTestSensorsBattery.test_emulate_power_plugged_2.<locals>.open_mockr�r�rT�rBrrr�r�rrr�r	r8rOr9�test_emulate_power_plugged_2xsz/TestSensorsBattery.test_emulate_power_plugged_2csj�fdd�}t�trdnd}tj||d��,}t��jdus>J�|jsHJ�Wd�n1s\0YdS)Ncs.|�d�rt�d�S�|g|�Ri|��SdS)Nr�0rr�rOr8r9r��s

zDTestSensorsBattery.test_emulate_power_not_plugged.<locals>.open_mockr�r�rFr
r	r8rOr9�test_emulate_power_not_plugged�sz1TestSensorsBattery.test_emulate_power_not_pluggedcsj�fdd�}t�trdnd}tj||d��,}t��jdus>J�|jsHJ�Wd�n1s\0YdS)NcsF|�d�rttjd��n*|�d�r,t�d�S�|g|�Ri|��SdS)NrrYrZdischargingrr�rOr8r9r��s



zFTestSensorsBattery.test_emulate_power_not_plugged_2.<locals>.open_mockr�r�rFr
r	r8rOr9� test_emulate_power_not_plugged_2�sz3TestSensorsBattery.test_emulate_power_not_plugged_2csj�fdd�}t�trdnd}tj||d��,}t��jdus>J�|jsHJ�Wd�n1s\0YdS)NcsF|�d�rttjd��n*|�d�r,t�d�S�|g|�Ri|��SdS)N)�"/sys/class/power_supply/AC0/online�!/sys/class/power_supply/AC/onlinerY�#/sys/class/power_supply/BAT0/statuss???)rkr�r�r�r�r�r�rOr8r9r��s



zETestSensorsBattery.test_emulate_power_undetermined.<locals>.open_mockr�r�rr
r	r8rOr9�test_emulate_power_undetermined�sz2TestSensorsBattery.test_emulate_power_undeterminedcCsLtddi��,}t��jdks J�|js*J�Wd�n1s>0YdS)N�(/sys/class/power_supply/BAT0/energy_fullrr)r�r�rrr�r�r8r8r9�test_emulate_energy_full_0�s�z-TestSensorsBattery.test_emulate_energy_full_0c
Cs�tdttjd����tdttjd���Ntddi��"t��jdksHJ�Wd�n1s\0YWd�n1sz0YWd�n1s�0YdS)NrrYz(/sys/class/power_supply/BAT0/charge_fullz%/sys/class/power_supply/BAT0/capacitys88�X)r�r�r�r�r�r�rr�r�r8r8r9�"test_emulate_energy_full_not_avail�s
�
��z5TestSensorsBattery.test_emulate_energy_full_not_availc
Cs�tdttjd����tdttjd���Ttdttjd���"t��jdusNJ�Wd�n1sb0YWd�n1s�0YWd�n1s�0YdS)NrrYrr)r�r�r�r�r�rrrr8r8r9�test_emulate_no_power�s��
�z(TestSensorsBattery.test_emulate_no_powerN)r�r�r�rr)r*rrr
rrrrrrrr8r8r8r9r\s
rc@seZdZdd�ZdS)�TestSensorsBatteryEmulatedc	s��fdd�}t�trdnd}tjddgd��N}tj||d�� }t��dusNJ�Wd�n1sb0YWd�n1s�0Y|js�J�|js�J�dS)	NcsV|�d�rt�d�S|�d�r(t�d�S|�d�r<t�d�S�|g|�Ri|��SdS)Nz/energy_nowZ60000000z
/power_now�0z/energy_fullZ60000001�rNr�r�r�rOr8r9r��s





z5TestSensorsBatteryEmulated.test_it.<locals>.open_mockr�r�z
os.listdirZBAT0r2r)rBrrr�r�rr�)r�r�r�ZmlistdirZmopenr8rOr9�test_it�s
L
z"TestSensorsBatteryEmulated.test_itN)r�r�r�rr8r8r8r9r�src@seZdZdd�Zdd�ZdS)�TestSensorsTemperaturesc	s��fdd�}t�trdnd}tj||d���tjddgd��Xt��d	d
}|jdks\J�|jdksjJ�|jd
ksxJ�|j	dks�J�Wd�n1s�0YWd�n1s�0YdS)Ncs~|�d�rt�d�S|�d�r(t�d�S|�d�r<t�d�S|�d�rPt�d�S|�d	�rdt�d
�S�|g|�Ri|��SdS)N�/namer�z/temp1_label�labelz/temp1_input�30000z
/temp1_maxs40000z/temp1_crit�50000)rNr�r�r�r�rOr8r9r��s









zCTestSensorsTemperatures.test_emulate_class_hwmon.<locals>.open_mockr�r�rr1z/sys/class/hwmon/hwmon0/temp1r2r�rr"�>@gD@�I@�
rBrrr�r�Zsensors_temperaturesr"rS�high�critical)r�r�r��tempr8rOr9�test_emulate_class_hwmon�s�z0TestSensorsTemperatures.test_emulate_class_hwmonc	s��fdd�}dd�}t�tr dnd}tj||d���tjdd	|d
��Xt��dd}|jd
ksdJ�|jdksrJ�|jdks�J�|j	dks�J�Wd�n1s�0YWd�n1s�0YdS)Ncsj|�d�rt�d�S|�d�r(t�d�S|�d�r<t�d�S|�d�rPt�d�S�|g|�Ri|��SdS)	NZ0_tempr$r*r#Z0_typer)�typer�)rNr�r�r�r�rOr8r9r�s







zETestSensorsTemperatures.test_emulate_class_thermal.<locals>.open_mockcSs:|dkrgS|dkrgS|dkr&dgS|dkr6ddgSgS)Nz/sys/class/hwmon/hwmon*/temp*_*z&/sys/class/hwmon/hwmon*/device/temp*_*z /sys/class/thermal/thermal_zone*z /sys/class/thermal/thermal_zone0z,/sys/class/thermal/thermal_zone0/trip_point*z2/sys/class/thermal/thermal_zone1/trip_point_0_typez2/sys/class/thermal/thermal_zone1/trip_point_0_tempr8r;r8r8r9�	glob_mock$s�zETestSensorsTemperatures.test_emulate_class_thermal.<locals>.glob_mockr�r�rr1Tr�r�rrYr%r&r')r�r�r-r�r*r8rOr9�test_emulate_class_thermalsz2TestSensorsTemperatures.test_emulate_class_thermalN)r�r�r�r+r.r8r8r8r9r �sr c@seZdZdd�ZdS)�TestSensorsFansc	s��fdd�}t�trdnd}tj||d��ltjddgd��<t��d	d
}|jdks\J�|jdksjJ�Wd�n1s~0YWd�n1s�0YdS)
NcsV|�d�rt�d�S|�d�r(t�d�S|�d�r<t�d�S�|g|�Ri|��SdS)Nr!r�z/fan1_labelr"z/fan1_input�2000rr�rOr8r9r�@s





z4TestSensorsFans.test_emulate_data.<locals>.open_mockr�r�rr1z/sys/class/hwmon/hwmon2/fan1r2r�rr"i�)rBrrr�r�Zsensors_fansr"rS)r�r�r�Zfanr8rOr9rU?s
�z!TestSensorsFans.test_emulate_dataN)r�r�r�rUr8r8r8r9r/=sr/c@s�eZdZe�dd��Zdd�Zejje	dd�dd��Z
d	d
�Zdd�Zd
d�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zejjedd�d d!��Zd"d#�Zd$d%�Zd&d'�Zd(S))�TestProcesscCs�|��}tj�|j���\}}}t�|j�jdd�}t|tdd�|D���dksVJ�t|tdd�|D���dksxJ�t|tdd�|D���dks�J�dS)NF)ZgroupedcSsg|]}|j|j�qSr8)Z
private_dirtyZ
private_cleanrvr8r8r9r]br^z?TestProcess.test_parse_smaps_vs_memory_maps.<locals>.<listcomp>r�cSsg|]
}|j�qSr8)�pssrvr8r8r9r]er^cSsg|]
}|j�qSr8)r�rvr8r8r9r]fr^)	Zspawn_testprocr�r%r�r��_parse_smaps�memory_mapsr�r�)r�Zsproc�ussr2r��mapsr8r8r9�test_parse_smaps_vs_memory_maps\s��"z+TestProcess.test_parse_smaps_vs_memory_mapscCs�t�d���}tdt��|i��\}tj�t���}|�	�\}}}|j
sLJ�|dksXJ�|dksdJ�|dkspJ�Wd�n1s�0YdS)Nan            fffff0 r-xp 00000000 00:00 0                  [vsyscall]
            Size:                  1 kB
            Rss:                   2 kB
            Pss:                   3 kB
            Shared_Clean:          4 kB
            Shared_Dirty:          5 kB
            Private_Clean:         6 kB
            Private_Dirty:         7 kB
            Referenced:            8 kB
            Anonymous:             9 kB
            LazyFree:              10 kB
            AnonHugePages:         11 kB
            ShmemPmdMapped:        12 kB
            Shared_Hugetlb:        13 kB
            Private_Hugetlb:       14 kB
            Swap:                  15 kB
            SwapPss:               16 kB
            KernelPageSize:        17 kB
            MMUPageSize:           18 kB
            Locked:                19 kB
            VmFlags: rd ex
            �/proc/%s/smapsilr�i<)r�r�r�r�rr�r�r%r�r3r�)r�r�r�r�r5r2r�r8r8r9�test_parse_smaps_mockedhs
z#TestProcess.test_parse_smaps_mockedzunreliable on PYPYr�cCsdd�}|��}t|d��"||�jdks.J�Wd�n1sB0Yt|��"||�jdkshJ�Wd�n1s|0Yt|d��"||�jdks�J�Wd�n1s�0Yt|d��"||�jdks�J�Wd�n1s�0Yt|d��$||�jdk�sJ�Wd�n1�s40Yt|d��$||�jdk�s^J�Wd�n1�st0Yt�rt|�t|d	��$||�jdk�s�J�Wd�n1�s�0Yt|�t|d
��$||�jdk�s�J�Wd�n1�s
0YdS)NcSsZt��}t��t}|��D].}|jtj�|�kr:|St��|krqqqtd��dS)Nztimeout looking for test file)	r�r��timer	�
open_filesr+r�abspathru)�fnamer�Z	giveup_at�filer8r8r9�
get_test_file�sz7TestProcess.test_open_files_mode.<locals>.get_test_filer��rr�zr+zw+za+rWzx+)r�rB�moderr)r�r?Ztestfnr8r8r9�test_open_files_mode�s*0
000444z TestProcess.test_open_files_modec	s�t�������t|��d���t��fdd��tjdtt	j
d�d��*}���gksZJ�|jsdJ�Wd�n1sx0Ytjdtt	jd�d��*}���gks�J�|js�J�Wd�n1s�0YWd�n1s�0YdS)Nr�cst����t��kSrU�rEr;r8��filesr�r8r9r��r^z7TestProcess.test_open_files_file_gone.<locals>.<lambda>�psutil._pslinux.os.readlinkrYr)
r�r�r;rBr�rrr��OSErrorr�r�r��EINVALr�r8rDr9�test_open_files_file_gone�s$
�(
�z%TestProcess.test_open_files_file_gonec	s�t�������t|��d��~t��fdd��tr:dnd}tj|t	t
jd�d��*}���gksfJ�|jspJ�Wd�n1s�0YWd�n1s�0YdS)Nr�cst����t��kSrUrCr8rDr8r9r��r^z5TestProcess.test_open_files_fd_gone.<locals>.<lambda>r�r�rYr)
r�r�r;rBr�rrrr�r�r�r�r��r�r�r�r8rDr9�test_open_files_fd_gone�s�z#TestProcess.test_open_files_fd_gonec
s�t�������t|��d���t��fdd��d}tj|tt	j
d�d��T}t�d��*���gksjJ�|jstJ�Wd�n1s�0YWd�n1s�0YWd�n1s�0YdS)Nr�cst����t��kSrUrCr8rDr8r9r��r^z:TestProcess.test_open_files_enametoolong.<locals>.<lambda>rFrYr�psutil._pslinux.debug)r�r�r;rBr�rrr�rGr��ENAMETOOLONGr�rJr8rDr9�test_open_files_enametoolong�s�z(TestProcess.test_open_files_enametoolongcCsXtjdid��6}tj�t�����dus,J�|js6J�Wd�n1sJ0YdS)Nz)psutil._pslinux._psposix.get_terminal_mapr2)	rr�r�r%r�rr�Zterminalr�r�r8r8r9�test_terminal_mocked�s�z TestProcess.test_terminal_mockedcCs�t��}t�d�}tjd|dd��.}|��ddgks8J�|jsBJ�Wd�n1sV0Yt�d�}tjd|dd��.}|��gd�ks�J�|js�J�Wd�n1s�0YdS)	Nzfoobarr�Tr"�foo�barz	foobar�rPrQrY�r�r�r�r�rr�Zcmdliner��r�r�r'r�r8r8r9�test_cmdline_mocked�s
�(
�zTestProcess.test_cmdline_mockedcCs�t��}t�d�}tjd|dd��.}|��ddgks8J�|jsBJ�Wd�n1sV0Yt�d�}tjd|dd��.}|��gd�ks�J�|js�J�Wd�n1s�0YdS)	Nzfoo bar r�Tr"rPrQz	foo bar  rRrSrTr8r8r9�test_cmdline_spaces_mockeds
�(
�z&TestProcess.test_cmdline_spaces_mockedcCsdt��}t�d�}tjd|dd��.}|��ddgks8J�|jsBJ�Wd�n1sV0YdS)Nzfoo barr�Tr"rPrQrSrTr8r8r9�test_cmdline_mixed_separatorss
�z)TestProcess.test_cmdline_mixed_separatorscCsZtjddd��8t����dks$J�t����dks8J�Wd�n1sL0YdS)NrFz/home/foo (deleted)r2z	/home/foo)rr�r�r��exe�cwdrr8r8r9�!test_readlink_path_deleted_mocked!s
�z-TestProcess.test_readlink_path_deleted_mockedc	s��fdd�}t�trdnd}tj||d��2}t����}|jsBJ�|gksNJ�Wd�n1sb0Y�fdd�}tj||d��Ht�	tj
��t����Wd�n1s�0YWd�n1s�0YdS)Ncs:|�dt���r ttjd��n�|g|�Ri|��SdS�Nz
/proc/%s/taskrY)rkrr�r�r�r�r�rOr8r9�open_mock_1-sz4TestProcess.test_threads_mocked.<locals>.open_mock_1r�r�rcs:|�dt���r ttjd��n�|g|�Ri|��SdSr[)rkrr�r�r��EPERMr�rOr8r9�open_mock_2<sz4TestProcess.test_threads_mocked.<locals>.open_mock_2)rBrrr�r�r�r�r�rr�ZAccessDenied)r�r\r�r�r�r^r8rOr9�test_threads_mocked(s
*zTestProcess.test_threads_mockedc	Cs�tjdttjd�d��`}tjdgd��2t����}|js>J�|dksJJ�Wd�n1s^0YWd�n1s|0YdS)Nzpsutil._pslinux.readlinkrYrzpsutil._pslinux.Process.cmdliner2)	rr�rGr�r�r�r�rXr�)r�r�r�r8r8r9�test_exe_mockedFs��
zTestProcess.test_exe_mockedc	Cs�tdt��ttjd���T}t��}t�	t
��|��Wd�n1sL0Y|js`J�Wd�n1st0YdS)Nr8rY)
r�rr�r�r�r�r�r�rr�rr4r��r�r�r�r8r8r9�test_issue_1014Rs�&zTestProcess.test_issue_1014r9c
Cs�tjdttjd�d���}tjddd��X}t��}|��t�	tj
��}|�tj�Wd�n1sf0YWd�n1s�0YWd�n1s�0Y|j
s�J�|j
s�J�|jj|jks�J�|jj|��ks�J�dS)Nzpsutil._pslinux.prlimitrYrz"psutil._pslinux.Process._is_zombieTr2)rr�rGr�ZENOSYSr�r�r�rr�Z
ZombieProcessZrlimitZ
RLIMIT_NOFILEr�r
r�)r�r5r6r��cmr8r8r9�test_rlimit_zombie]s ��f

zTestProcess.test_rlimit_zombiecCsgd�}d�|���}tdt��|i���t��}|��dksDJ�|��tj	ksVJ�|�
�dksfJ�|��dtt�
�ks�J�|��}|jdtks�J�|jdtks�J�|jd	tks�J�|jd
tks�J�|jdtks�J�|��dks�J�Wd�n1�s
0YdS)N)*rz(cat)�Z�1rrrrrrrrr�2�3�4�5rrrr�6rrrrrrrrrrrrrrrrrkrr�7r}z
/proc/%s/stat�catrxrr�r�r@ryr�)rHr�r�rr�r�r�r��statusZ
STATUS_ZOMBIE�ppidZcreate_timerr�rr��system�
children_user�children_systemZiowaitZcpu_num)r�r�r�r��cpur8r8r9�test_stat_file_parsingqs,z"TestProcess.test_stat_file_parsingcCst�d���}tdt��|i���t��}|��j	dks>J�|��j
dksPJ�|��dks`J�|��}|j
dksvJ�|jdks�J�|jdks�J�|��}|j
d	ks�J�|jd
ks�J�|jdks�J�|j��ttd��ks�J�Wd�n1s�0YdS)
Nz�            Uid:	1000	1001	1002	1003
            Gid:	1004	1005	1006	1007
            Threads:	66
            Cpus_allowed:	f
            Cpus_allowed_list:	0-7
            voluntary_ctxt_switches:	12
            nonvoluntary_ctxt_switches:	13r�r��
�Bi�i�i�i�i�i�r�)r�r�r�r�rr�r�r��num_ctx_switches�	voluntary�involuntary�num_threads�uids�realZ	effectiveZsaved�gids�_proc�_get_eligible_cpus�listrG)r�r�r�r{r}r8r8r9�test_status_file_parsing�sz$TestProcess.test_status_file_parsingc	Cs�tjdttjd�d��\}t��}t�d��*|��gks<J�|jsFJ�Wd�n1sZ0YWd�n1sx0YdS)NrFrYrrL)	rr�rGr�rMr�r�r�r�rar8r8r9�!test_net_connections_enametoolong�s
�z-TestProcess.test_net_connections_enametoolongN)r�r�r�rr7r9rr)r*rrBrIrKrNrOrUrVrWrZr_r`rbr
rdrtr�r�r8r8r8r9r1Zs*
"
"
<r1c@s�eZdZdZedd��Zdd�Zdd�Zej	j
edd	�d
d��Zdd
�Z
dd�Zdd�Zdd�Ze�dd��Zdd�Zdd�ZdS)�TestProcessAgainstStatusa/proc/pid/stat and /proc/pid/status have many values in common.
    Whenever possible, psutil uses /proc/pid/stat (it's faster).
    For all those cases we check that the value found in
    /proc/pid/stat (by psutil) matches the one found in
    /proc/pid/status.
    cCst��|_dSrU)r�r��proc)�clsr8r8r9�
setUpClass�sz#TestProcessAgainstStatus.setUpClassc
Cs�tj�d|jj���}|D]j}|��}|�|�r|�d�d}zt|�WWd�St	y�|YWd�S0qt	d|��Wd�n1s�0YdS)Nr��	r�z
can't find %r)
r��_psplatform�	open_textr�r�r~rk�	partitionrnrF)r�Z	linestartrLrMr
r8r8r9�read_status_file�s
�
z)TestProcessAgainstStatus.read_status_filecCs |�d�}|j��|ksJ�dS)NzName:)r�r�r��r�r
r8r8r9�	test_name�s
z"TestProcessAgainstStatus.test_namernr�cCsH|�d�}||�d�d|�d��}|�dd�}|j��|ksDJ�dS)NzState:�(rx�)r}r)r�r��rfindrr�rnr�r8r8r9�test_status�s
z$TestProcessAgainstStatus.test_statuscCs |�d�}|j��|ksJ�dS)NzPPid:)r�r�ror�r8r8r9�	test_ppid�s
z"TestProcessAgainstStatus.test_ppidcCs |�d�}|j��|ksJ�dS)NzThreads:)r�r�rzr�r8r8r9�test_num_threads�s
z)TestProcessAgainstStatus.test_num_threadscCs:|�d�}ttt|��dd���}|j��|ks6J�dS)NzUid:rxr@)r�r�r�rnrCr�r{r�r8r8r9�	test_uids	s
z"TestProcessAgainstStatus.test_uidscCs:|�d�}ttt|��dd���}|j��|ks6J�dS)NzGid:rxr@)r�r�r�rnrCr�r}r�r8r8r9�	test_gids	s
z"TestProcessAgainstStatus.test_gidscCs@|�d�}|j��j|ksJ�|�d�}|j��j|ks<J�dS)Nzvoluntary_ctxt_switches:znonvoluntary_ctxt_switches:)r�r�rwrxryr�r8r8r9�test_num_ctx_switches	s

z.TestProcessAgainstStatus.test_num_ctx_switchescCsN|�d�}dt|�vrJtt|�d��\}}|j��tt||d��ksJJ�dS)N�Cpus_allowed_list:rrx)	r�r�r�rnrCr�Zcpu_affinityr�rG)r�r
Zmin_Zmax_r8r8r9�test_cpu_affinity	s
z*TestProcessAgainstStatus.test_cpu_affinitycCsf|�d�}t�d��}|jj��Wd�n1s60Ydt|�vrX|jrbJ�n
|jsbJ�dS)Nr�zpsutil._pslinux.per_cpu_timesr)r�rr�r�r~rr�r�)r�r
r�r8r8r9�test_cpu_affinity_eligible_cpus	s
*z8TestProcessAgainstStatus.test_cpu_affinity_eligible_cpusN)r�r�r��__doc__�classmethodr�r�r�rr)r*rr�r�r�r�r�rr�r�r�r8r8r8r9r��s


r�c@seZdZdd�ZdS)�	TestUtilscCsPtjddd��.}tj�d�dks$J�|js.J�Wd�n1sB0YdS)Nzos.readlinkz
foo (deleted)r2rQrP)rr�r�r��readlinkr�r�r8r8r9�
test_readlink)	szTestUtils.test_readlinkN)r�r�r�r�r8r8r8r9r�'	sr�)fr��
__future__rrlr-r��globr�rr�r�r*r3r�r:r�r�rZpsutil._compatrrrZpsutil.testsrrr	r
rrr
rrrrrrrrrrrrrrrrr$rrr r!r+r<�dirname�__file__ZHEREr2ZSIOCGIFCONFr`r;r=r�ZEMPTY_TEMPERATURESr:r<r>rTrcrur{r|r��contextmanagerr�r�r)r*r�r�r�r�r�r	r-r8r]r`rdror�r�r�r�r�r�rrr r/r1r�r�r8r8r8r9�<module>s	

91RZI'63AH8CzSPKok\ r.�}�}�4psutil/tests/__pycache__/test_process.cpython-39.pycnu�[���a

��?hn��@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlmZddlmZddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlm Z ddlm!Z!ddl"m#Z#ddl"m$Z$ddl"m%Z%ddl"m&Z&ddl"m'Z'ddl"m(Z(ddl"m)Z)ddl"m*Z*ddl"m+Z+ddl"m,Z,ddl"m-Z-ddl"m.Z.ddl"m/Z/dd l"m0Z0dd!l"m1Z1dd"l"m2Z2dd#l"m3Z3dd$l"m4Z4dd%l"m5Z5dd&l"m6Z6dd'l"m7Z7dd(l"m8Z8dd)l"m9Z9dd*l"m:Z:dd+l"m;Z;dd,l"m<Z<dd-l"m=Z=dd.l"m>Z>dd/l"m?Z?dd0l"m@Z@dd1l"mAZAdd2l"mBZBGd3d4�d4e4�ZCe�r�e�D�dk�r�Gd5d6�d6eC�ZEGd7d8�d8e4�ZFdS)9�Tests for psutil.Process class.�N)�AIX)�BSD)�LINUX)�MACOS)�NETBSD)�OPENBSD)�OSX)�POSIX)�SUNOS)�WINDOWS)�	open_text)�PY3)�FileNotFoundError)�long)�redirect_stderr)�super)�APPVEYOR)�
CI_TESTING)�GITHUB_ACTIONS)�GLOBAL_TIMEOUT)�HAS_CPU_AFFINITY)�HAS_ENVIRON)�
HAS_IONICE)�HAS_MEMORY_MAPS)�HAS_PROC_CPU_NUM)�HAS_PROC_IO_COUNTERS)�
HAS_RLIMIT)�HAS_THREADS)�MACOS_11PLUS)�PYPY)�
PYTHON_EXE)�PYTHON_EXE_ENV)�	QEMU_USER)�PsutilTestCase)�
ThreadTask)�
call_until)�copyload_shared_lib)�create_c_exe)�
create_py_exe)�mock)�process_namespace)�pytest��
reap_children)�retry_on_failure)�sh)�skip_on_access_denied)�skip_on_not_implemented)�wait_for_pidc@seZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�Ze	j
jedd
�dd��Z
dd�Ze	j
jedd
�dd��Zdd�Zdd�Zdd�Zdd�Zdd�Ze	j
jedd
�d d!��Ze	j
jedd
�d"d#��Ze	j
jed$d
�d%d&��Zd'd(�Ze	j
jed)d
�d*d+��Ze	j
jed$d
�eed,�d-d.���Z e	j
je!d$d
�e	j
jed/d
�d0d1���Z"e	j
je!d$d
�e	j
je#d2d
�d3d4���Z$e	j
je%d$d
�d5d6��Z&e	j
je%d$d
�d7d8��Z'e	j
je%d$d
�d9d:��Z(e	j
je%d$d
�d;d<��Z)e	j
je%d$d
�d=d>��Z*d?d@�Z+e	j
je#dAd
�dBdC��Z,e	j
je-d$d
�dDdE��Z.e/�e0e1d,�e	j
je-d$d
�dFdG����Z2e/�dHdI��Z3dJdK�Z4e	j
je5d$d
�dLdM��Z6e	j
je5d$d
�dNdO��Z7dPdQ�Z8dRdS�Z9e	j
jedd
�dTdU��Z:dVdW�Z;e	j
je<dXd
�dYdZ��Z=d[d\�Z>e	j
je<�ped]d
�e	j
jed^d
�d_d`���Z?e	j
je@dad
�e	j
jeAdbd
�e	j
je<dXd
�e	j
jedcd
�ddde�����ZBe	j
jed)d
�dfdg��ZCe	j
jed)d
�dhdi��ZDdjdk�ZEe	j
jedd
�dldm��ZFdndo�ZGdpdq�ZHdrds�ZIe	j
jeJd$d
�dtdu��ZKe	j
jeJd$d
�dvdw��ZLe	j
jeJd$d
�dxdy��ZMe	j
jeNdzd
�e	j
jeOd{d
�d|d}���ZPe	j
jeNdzd
�e	j
jeOd{d
�d~d���ZQe	j
jed)d
�d�d���ZReed,�e	j
jeS�p�ed�d
�d�d����ZTd�d��ZUd�d��ZVd�d��ZWe	j
jedd
�e/�d�d����ZXd�d��ZYd�d��ZZd�d��Z[d�d��Z\d�d��Z]d�d��Z^d�d��Z_d�d��Z`d�d��Zad�d��Zbd�d��Zce	j
jed)d
�d�d���Zde	j
jed)d
�d�d���Zee	j
jed)d
�d�d���Zfd�d��Zgd�d��Zhe	j
jeid$d
�d�d���Zje	j
jeid$d
�e	j
jed)d
�e	j
jekd�d
�e	j
jed�d
�d�d������Zld�S)��TestProcessrcOsF|j|i|��}zt�|j�WStjy@|�|j��Yn0dS�N)�spawn_testproc�psutil�Process�pid�
NoSuchProcessZ
assertPidGone)�self�args�kwargs�sproc�r?�E/usr/local/lib64/python3.9/site-packages/psutil/tests/test_process.py�spawn_psprocSszTestProcess.spawn_psproccCsNt��}|jt��ksJ�t�t��d|_Wd�n1s@0YdS)N�!)r7r8r9�os�getpidr,�raises�AttributeError�r;�pr?r?r@�test_pid]szTestProcess.test_pidcCsJ|��}|��|��}tr,|tjks<J�n|tjks<J�|�|�dSr5)rA�kill�waitr�signal�SIGTERM�SIGKILL�assertProcessGone�r;rH�coder?r?r@�	test_killcszTestProcess.test_killcCsJ|��}|��|��}tr,|tjks<J�n|tjks<J�|�|�dSr5)rA�	terminaterKrrLrMrOrPr?r?r@�test_terminatemszTestProcess.test_terminatecCsXtr
tjntj}|��}|�|�|��}tr<||ksJJ�n||ksJJ�|�|�dSr5)	r
rLrNrMrA�send_signalrKrrO)r;�sigrHrQr?r?r@�test_send_signalws
zTestProcess.test_send_signalz	not POSIX��reasonc	Cs�tj}|��}tjdttjd�d��Ft�	t
j��|�|�Wd�n1sR0YWd�n1sp0Y|��}tjdttj
d�d��Ft�	t
j��|�|�Wd�n1s�0YWd�n1s�0YdS)Nzpsutil.os.kill���side_effect)rLrMrAr*�patch�OSError�errnoZESRCHr,rEr7r:rU�EPERM�AccessDenied)r;rVrHr?r?r@�test_send_signal_mocked�s�F�z#TestProcess.test_send_signal_mockedcCs�tddg}|�|�}|��}|dks(J�|�|�tddg}|j|tjd�}|��}|dks`J�|�|�tddg}|�|�}|��}|dks�J�|�|�tdd	g}|�|�}|��}|dks�J�|�|�dS)
N�-c�passrz1 / 0)�stderr�zimport sys; sys.exit(5);�zimport os; os._exit(5);)r!rArKrO�
subprocess�PIPE)r;�cmdrHrQr?r?r@�test_wait_exited�s(









zTestProcess.test_wait_exitedzfails on NETBSDcCs�|��}tr�|�tj�t�tj��|j	dd�Wd�n1sF0Y|�tj
�t�tj��|j	dd�Wd�n1s�0Y|�tj�|�	�tjks�J�|�	�tjks�J�n�|��t�tj��|j	dd�Wd�n1�s0Y|�
�t�tj��|j	dd�Wd�n1�sD0Y|��|�	�tjk�sjJ�|�	�tjk�s~J�dS)N���MbP?)�timeout)rAr
rUrL�SIGSTOPr,rEr7�TimeoutExpiredrK�SIGCONTrM�suspend�resumerSrGr?r?r@�test_wait_stopped�s(**,,zTestProcess.test_wait_stoppedcCs�|��\}}t�tj��|�d�Wd�n1s80Yt�tj��|�d�Wd�n1sn0Y|��|��|��}|��}tr�|tj	ks�J�|dus�J�n|tj	ks�J�|tj	ks�J�dS)N�{�G�z�?)
�spawn_children_pairr,rEr7rorKrSr
rLrM)r;�child�
grandchildZ	child_retZgrandchild_retr?r?r@�test_wait_non_children�s((z"TestProcess.test_wait_non_childrencCs�|��}|��t�tj��|�d�Wd�n1s<0Yt�tj��|�d�Wd�n1sr0Yt�t��|�d�Wd�n1s�0YdS)Nrtr���)rA�namer,rEr7rorK�
ValueErrorrGr?r?r@�test_wait_timeout�s((zTestProcess.test_wait_timeoutcCs�|��}t�tj��|�d�Wd�n1s40Y|��t��t}t��|kr�z|�d�}Wq�WqRtjy�YqR0qR|�	d��t
r�|tjks�J�n|tj
ks�J�|�|�dS)Nrrm)rAr,rEr7rorKrJ�timer�failr
rLrNrMrO)r;rHZstop_atrQr?r?r@�test_wait_timeout_nonblocking�s (

z)TestProcess.test_wait_timeout_nonblockingcCs�t��}|jdd�|jdd�td�D]*}|jdd�}t|t�sFJ�|dks(J�q(t�t��|jdd�Wd�n1s�0YdS)Nrl)�interval�d�ry)	r7r8�cpu_percent�range�
isinstance�floatr,rEr{)r;rH�_�percentr?r?r@�test_cpu_percent�szTestProcess.test_cpu_percentcCsHtjddd��&}t����|js&J�Wd�n1s:0YdS)Nzpsutil.cpu_count)Zreturn_value)r*r]r7r8r��called)r;�mr?r?r@�test_cpu_percent_numcpus_nonesz)TestProcess.test_cpu_percent_numcpus_nonezQEMU user not supportedc	Cs�t����}|jdksJ|��|jdks0J|��|jdksBJ|��|jdksTJ|��trj|jdksjJ|��|j	D]}t
�dt
�t
||���qpdS)Nr�z%H:%M:%S)r7r8�	cpu_times�user�system�
children_user�children_systemrZiowait�_fieldsr}�strftime�	localtime�getattr)r;�timesrzr?r?r@�test_cpu_timess
zTestProcess.test_cpu_timescCs�t����dd�\}}t��dd�\}}t||g�t||g�dkrZ|�d||f��t||g�t||g�dkr�|�d||f��dS)N�皙�����?zexpected: %s, found: %s)r7r8r�rCr��max�minr~)r;�	user_timeZkernel_time�utimeZktimer?r?r@�test_cpu_times_2szTestProcess.test_cpu_times_2z
not supportedcCsPt��}|��}|dksJ�t��dkr4|dks4J�|��tt���vsLJ�dS�Nrrf)r7r8Zcpu_num�	cpu_countr�)r;rH�numr?r?r@�test_cpu_num)szTestProcess.test_cpu_numcCsZ|��}t��}|��}t||�}|dkr@|�d|||f��t�dt�|����dS)Nr�z'expected: %s, found: %s, difference: %sz%Y %m %d %H:%M:%S)rAr}�create_time�absr~r�r�)r;rH�nowr��
differencer?r?r@�test_create_time2s��zTestProcess.test_create_timez
POSIX onlycCsVt����}|durRztj�td��}WntyDt�	d��Yn0||ksRJ�dS)N�ttyzcan't rely on `tty` CLI)
r7r8�terminalrC�path�realpathr0�RuntimeErrorr,�skip)r;r�r�r?r?r@�
test_terminalDszTestProcess.test_terminal)Zonly_ifcCs�t��}|��}ttd��}|��Wd�n1s80Y|��}ts�ts�|j|jksbJ�|j	|j	ksrJ�t
r�|j|jks�J�|j|jks�J�n |j
|j
ks�J�|j|jks�J�|��}t|��d��8}tr�|�tddd��n|�dd�Wd�n1�s0Y|��}|j	|j	k�s2J�|j|jk�sDJ�|j|jk�sVJ�|j
|j
k�shJ�t
�r�|j|jk�s�J�|j|jk�s�J�tt|��D]>}t�r�|dk�r��q�||dk�s�J�||dk�s�J��q�dS)N�rb�wb�xi@B�asciir�r)r7r8Zio_counters�openr!�readrrZ
read_countZwrite_countrZ
read_charsZwrite_chars�
read_bytes�write_bytes�
get_testfnr�write�bytesr��len)r;rHZio1�fZio2�ir?r?r@�test_io_countersPs>&.zTestProcess.test_io_countersz
linux onlycsR�fdd�}t���ts.���dtjks.J�tjdks<J�tjdksJJ�tjdksXJ�tjdksfJ����}|�||���tj�t	����tjdfks�J�t
�t�� �jtjdd�Wd�n1s�0Y��tj�t	����tjdfk�sJ��jtjdd�t	����tjdfk�s.J�t
�t�� �jtjd	d�Wd�n1�s`0Yz�jtjdd�Wntj
�y�Yn0t
jtd
d����tjd�Wd�n1�s�0Yt
jtd
d����tjd�Wd�n1�s0Yt
jtdd���jdd�Wd�n1�sD0YdS)
Ncs&|\}}|tjkrd}��||�dS�Nr)r7�IOPRIO_CLASS_NONE�ionice)�initZioclass�value�rHr?r@�cleanup~s
z.TestProcess.test_ionice_linux.<locals>.cleanuprrfr����r��zioclass accepts no value��matchz$'ioclass' argument must be specified)r7r8rr�r�ZIOPRIO_CLASS_RTZIOPRIO_CLASS_BEZIOPRIO_CLASS_IDLE�
addCleanup�tupler,rEr{ra)r;r�r�r?r�r@�test_ionice_linux{s@.0..�zTestProcess.test_ionice_linuxz!not supported on this win versioncCs*t��}ts|��tjksJ�|��}|�|j|�|�tj�|��tjksRJ�|�tj�|��tjkspJ�z|�tj�Wntj	y�Yn0|��tjks�J�t
jtdd�� |jtjdd�Wd�n1s�0Yt
jt
dd�� |�tjd�Wd�n1�s0YdS)Nz&value argument not accepted on Windowsr�rfr�zis not a valid priority)r7r8rr�Z
IOPRIO_NORMALr�ZIOPRIO_VERYLOWZ
IOPRIO_LOWZIOPRIO_HIGHrar,rE�	TypeErrorr{)r;rHr�r?r?r@�test_ionice_win�s(�.zTestProcess.test_ionice_wincCs�ddl}t�t���}dd�tt�D�}|s4J|��|D]�}tt|�}|dksRJ�|t|�vr�|t||�kspJ�trvq8|�|�|�	|�ks�J�q8|�|�}t
|�dks�J�|ddks�J�|ddks8J�q8dS)NrcSsg|]}|�d�r|�qS)ZRLIMIT��
startswith��.0r�r?r?r@�
<listcomp>��z/TestProcess.test_rlimit_get.<locals>.<listcomp>r�ryrf)�resourcer7r8rCrD�dirr�r �rlimitZ	getrlimitr�)r;r�rH�namesrzr��retr?r?r@�test_rlimit_get�s 

zTestProcess.test_rlimit_getcCs�|��}|�tjd�|�tj�dks*J�trntjtdd��"tj�	d��d�Wd�n1sd0Yt�t��|�tjd�Wd�n1s�0YdS)N)rgrgzcan't use prlimitr�r)rgrgrg)
rAr�r7Z
RLIMIT_NOFILErr,rEr{Z_psplatformr8rGr?r?r@�test_rlimit_set�s0zTestProcess.test_rlimit_setcCsHt��}|��}|�tj�\}}z�|�tjd|f�t|d��}|�d�Wd�n1s^0Yt�t	��D}t|d��}|�d�Wd�n1s�0YWd�n1s�0Yt
r�|jjn|jdtj
ks�J�W|�tj||f�|�tj�||fk�sDJ�n.|�tj||f�|�tj�||fk�sBJ�0dS)N�r�sXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXsXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXr)r7r8r�r��RLIMIT_FSIZEr�r�r,rE�IOErrorrr�r_ZEFBIG)r;rH�testfn�soft�hardr��excr?r?r@�test_rlimit�s(F"�zTestProcess.test_rlimitcCs�t��}|�tj�\}}z�|�tjd|f�|�tjtj|f�t|��d��}|�d�Wd�n1sn0YW|�tj||f�|�tj�||fks�J�n,|�tj||f�|�tj�||fks�J�0dS)Nr�r�sXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)r7r8r�r��
RLIM_INFINITYr�r�r�)r;rHr�r�r�r?r?r@�test_rlimit_infinity�s*�z TestProcess.test_rlimit_infinitycCs<t��}|�tj�\}}|tjks&J�|�tj||f�dSr5)r7r8r�r�r�)r;rHr�r�r?r?r@�test_rlimit_infinity_value
sz&TestProcess.test_rlimit_infinity_valuecCs�t��}tr:z|��}WqBtjy6t�d��YqB0n|��}t��(|��}||dksbJ�Wd�n1sv0YdS)N�$on OpenBSD this requires root accessrf)r7r8r�num_threadsrar,r�r%)r;rH�step1�step2r?r?r@�test_num_threadsszTestProcess.test_num_threadszWINDOWS onlycCst��}|��dksJ�dSr�)r7r8Znum_handlesrGr?r?r@�test_num_handles*szTestProcess.test_num_handlescCs�t��}tr:z|��}WqBtjy6t�d��YqB0n|��}t��n|��}t|�t|�dksjJ�|d}|j	|dks�J�|j
|dks�J�|j|dks�J�Wd�n1s�0YdS)Nr�rfrr�)r7r8r�threadsrar,r�r%r��idr��system_time)r;rHr�r�Zathreadr?r?r@�test_threads0szTestProcess.test_threadscCs�|��}tr8z|��Wntjy6t�d��Yn0t|��j	t
dd�|��D���dksdJ�t|��jt
dd�|��D���dks�J�dS)Nr�cSsg|]
}|j�qSr?)r�r�r?r?r@r�Or�z.TestProcess.test_threads_2.<locals>.<listcomp>r�cSsg|]
}|j�qSr?)r�r�r?r?r@r�Ur�)rArr�r7rar,r�r�r�r��sumr�rGr?r?r@�test_threads_2Ds$"������zTestProcess.test_threads_2cCs�t��}|��dd�\}}|��}|dks0J�|dks<J�dgd}|��dd�\}}|��}||ksnJ�||kszJ�||ks�J�~tr�|��}	|	j|	jks�J�|	j|	jks�J�|��}	|	j	D]}
t
|	|
�dks�J�q�dS)Nr�ri`�)r7r8Zmemory_info�memory_percentrZrssZwset�vmsZpagefiler�r�)r;rHZrss1Zvms1Zpercent1ZmemarrZrss2Zvms2Zpercent2�memrzr?r?r@�test_memory_infoZs&

zTestProcess.test_memory_infocCs�t��}t��j}|��}|jD]8}t||�}|dks:J�|dkrFts trLq ||ks J�q tsft	sft
rt|jdkstJ�tr�|jdks�J�|j
dks�J�dS)Nrr�)r7r8Zvirtual_memory�totalZmemory_full_infor�r�r	rrr�ussZpssZswap)r;rHr�r�rzr�r?r?r@�test_memory_full_infoys


z!TestProcess.test_memory_full_infoc
Cs�t��}|��}t|�tt|��ks(J�|jdd�}|D�]}|j�d�s8trZd|jvrZq8tj�	|j�srJ|j��t
�rz*tj�|j�s�tj�|j�s�J|j��WnZt
y�ts��n@td��}|��}Wd�n1s�0Yd|j|vr��Yn0q8dtj�|j�vr8zt�|j�}Wnt�y6Yq80t�|j�s8J|j��q8|D]l}|jD]^}t||�}	|dk�rz�q^|d	v�r�|	�s�J|	��n&t|	ttf��s�J�|	d
k�s^J|	���q^�qTdS)NF)Zgrouped�[z
/bin/qemu-z/proc/self/smapsz%s (deleted)Z64r�)�addrZpermsr)r7r8�memory_mapsr��setr�r�r#rC�isabsr
�exists�islink�AssertionErrorrr
r��basename�statr�S_ISREG�st_moder�r�r��intr)
r;rH�mapsZext_maps�ntr��data�st�fnamer�r?r?r@�test_memory_maps�sL
��
&




zTestProcess.test_memory_mapscs`t��}t��>}dd���fdd�|��D�}�|�|vs>J�Wd�n1sR0YdS)NcSstj�tj�|��Sr5)rCr�r��normcaser�r?r?r@�normpath�sz8TestProcess.test_memory_maps_lists_lib.<locals>.normpathcsg|]}�|j��qSr?)r�r��rr?r@r��r�z:TestProcess.test_memory_maps_lists_lib.<locals>.<listcomp>)r7r8r'r�)r;rHr�Zlibpathsr?rr@�test_memory_maps_lists_lib�s
z&TestProcess.test_memory_maps_lists_libcCsbt��}|��t�t��|jdd�Wd�n1s<0YtsRtsRtr^|jdd�dS)Nz?!?)Zmemtyper�)	r7r8r�r,rEr{rrrrGr?r?r@�test_memory_percent�s*zTestProcess.test_memory_percentcCsL|��}|��sJ�|��s J�|��|��|��r<J�|��rHJ�dSr5)rA�
is_runningrJrKrGr?r?r@�test_is_running�szTestProcess.test_is_runningcCs�|��}|��}z|tksJ�Wn�ty�tr`t|�tt�kr`tjj}||�|t�ks�J�nLdt	j
dt	j
df}z |�|d�t�|d�ks�J�Wnty�Yn0Yn0t|ddg�}|dks�J�dS)Nz%s.%srrfrZrczimport os; print('hey')Zhey)
rA�exer!rrr�rCr�r�sys�version_info�replacer0)r;rHrr�ver�outr?r?r@�test_exe�s zTestProcess.test_execCs�tddg}|�|�}tr.|��gkr.t�d��ts:ts:trP|��dtks�J�n�tr�t	r�|��d}|tkr�d�
|��dd��d�
|dd��ks�J�dStr�d�
|��dd��d�
|�ks�J�dSd�
|���d�
|�ks�J�dS)Nrc�2import time; [time.sleep(0.1) for x in range(100)]�OPENBSD: returned EBUSYr� rfr�)r!rAr�cmdliner,r�rrrr�joinr#)r;rrH�pyexer?r?r@�test_cmdline�s$�

,$zTestProcess.test_cmdlinezbroken on PYPYcCs�tg}|�dgd�|�ddg�|�|�}trhz|��|ksDJ�Wq�tjydt�d��Yq�0nHt	r�|��dd�|ks�J�n*|��}t
r�|gkr�t�d��||ks�J�dS)Nz-v�2rcrz#OPENBSD: process turned into zombier�r)r!�extendrArrr7�
ZombieProcessr,r�r#r)r;rrHr�r?r?r@�test_long_cmdlines"�

zTestProcess.test_long_cmdlinecCsH|��}|����}tj�tj�tj����}|�	|�sDJ||f��dSr5)
rArz�lowerrCr�rr�r�
executabler�)r;rHrzr!r?r?r@�	test_name(szTestProcess.test_namezunreliable on PYPYzunreliable on QEMU usercCs�t|jtjdd��}|ddg}|�|�}tr�z|��tj�	|�ksHJ�Wq�t
y�|��tj
kr�tj�	|��|���s�J�n�Yq�0n|��tj�	|�ks�J�dS)Nr���suffixrcr)r)r��string�digitsrArrzrCr�rr�statusr7�
STATUS_ZOMBIEr��r;r!rrHr?r?r@�test_long_name.s�

zTestProcess.test_long_namezbroken on SUNOSz
broken on AIXzbroken on QEMU usercCspt|jdd��}|ddg}|�|�}|��|ks4J�|��tj�|�ksLJ�tj�|�	��tj�|�kslJ�dS)Nz	foo bar )r*rcr)
r)r�rArrzrCr�rrrr0r?r?r@�test_prog_w_funky_nameKs�
z"TestProcess.test_prog_w_funky_namecCsXt��}|��\}}}|t��ks&J�|t��ks6J�ttd�rTt��|��ksTJ�dS�N�	getresuid)r7r8�uidsrC�getuid�geteuid�hasattrr4�r;rH�realZ	effectiveZ_savedr?r?r@�	test_uids^s
zTestProcess.test_uidscCsXt��}|��\}}}|t��ks&J�|t��ks6J�ttd�rTt��|��ksTJ�dSr3)r7r8�gidsrC�getgid�getegidr8�	getresgidr9r?r?r@�	test_gidsls
zTestProcess.test_gidsc
s��fdd�}t���t�t����d�Wd�n1s>0Y���}|�||�t�r(d}tjtj	tj
tjtjtj
fD]�}|j|d���z��|�Wntjy�YnN0���}|tjtjtj
fvr�||ks�|dur�|}||ks�J�n||k�sJ�Wd�q�1�s0Yq�n�z�ttd��rVt�tjt������k�sVJ���d����dk�srJ�ttd��r�t�tjt������k�s�J�t�s���d����dk�s�J�Wntj�y�Yn0dS)Ncs(z��|�Wntjy"Yn0dSr5)�nicer7ra)r�r�r?r@r�{sz&TestProcess.test_nice.<locals>.cleanup�str)�prio�getpriorityrfr)r7r8r,rEr�rAr�rZIDLE_PRIORITY_CLASSZBELOW_NORMAL_PRIORITY_CLASSZNORMAL_PRIORITY_CLASSZABOVE_NORMAL_PRIORITY_CLASSZHIGH_PRIORITY_CLASSZREALTIME_PRIORITY_CLASS�subTestrar8rCrD�PRIO_PROCESSrDr)r;r�r�Zhighest_priorCZnew_prior?r�r@�	test_nicezs`(��2��
��
zTestProcess.test_nicecCst��}|��tjksJ�dSr5)r7r8r.ZSTATUS_RUNNINGrGr?r?r@�test_status�szTestProcess.test_statuscCs||��}|��}trh|�d�\}}t��}|�d�r>t�d��||ksJJ�dt	j
vrx|t	j
dksxJ�n|t��ksxJ�dS)N�\�$zrunning as service accountZ
USERDOMAIN)rA�usernamer�split�getpass�getuser�endswithr,r�rC�environ)r;rHrK�domainZgetpass_userr?r?r@�
test_username�s


zTestProcess.test_usernamecCs |��}|��t��ksJ�dSr5)rA�cwdrC�getcwdrGr?r?r@�test_cwd�szTestProcess.test_cwdcs(tddg}|�|��t�fdd��dS)NrczFimport os, time; os.chdir('..'); [time.sleep(0.1) for x in range(100)]cs���tj�t���kSr5)rSrCr��dirnamerTr?r�r?r@�<lambda>�r�z(TestProcess.test_cwd_2.<locals>.<lambda>)r!rAr&)r;rjr?r�r@�
test_cwd_2�s�
zTestProcess.test_cwd_2cCs�t��}|��}|sJ|��|�|j|�ttd�rL|tt�|j��ksLJ�t	|�t	t
|��ksdJ�ttt	tjdd����}|D]j}|�|g�|��|gks�J�ttd�r�|��tt�|j��ks�J�t|d�r�|��d|�
�ks�J�q�|�g�t�r|��|j��k�s(J�n|��|k�s(J�ttd��rR|��tt�|j��k�sRJ�t�t��|�d�Wd�n1�s~0Y|�|�|�t
|��|�t|��dS)N�sched_getaffinityT�Zpercpu�num_cpurrf)r7r8�cpu_affinityr�r8rC�listrYr9r�r�r�r�r[r�_procZ_get_eligible_cpusr,rEr�r�)r;rH�initialZall_cpus�nr?r?r@�test_cpu_affinity�s4



*
zTestProcess.test_cpu_affinitycCs|��}ttjdd��dg}t�t��|�|�Wd�n1sH0Yt�t�� |�tdd��Wd�n1s�0Yt�t	��|�ddg�Wd�n1s�0Yt�t��|�ddg�Wd�n1s�0YdS)	NTrZ�
i'i�*r�1ry)
rAr�r7r�r,rEr{r\r�r�)r;rHZinvalid_cpur?r?r@�test_cpu_affinity_errs	s(.,z"TestProcess.test_cpu_affinity_errscCs�t��}|��}|sJ|��|�|j|�t|�dkrB|dd�}g}tt|�d�D](}t�||�D]}|rf|�t	|��qfqV|D]&}|�|�t
|���t
|�ks�J�q�dS)N�rf)r7r8r\r�r�r��	itertools�combinations�appendr]�sorted)r;rHr_Zcombosr�ZsubsetZcombor?r?r@�"test_cpu_affinity_all_combinationss
z.TestProcess.test_cpu_affinity_all_combinationsz
broken on BSDzunreliable on APPVEYORcsrt���|��}����|�vs$J�t|d���}|�d�|��t��fdd������dd��D�}tj	�
|�|vs~J�tr��D]}|j	|kr�|jdks�J�q�Wd�n1s�0Y�D]}tj	�
|j	�s�J|��q�d|}|�td	|g��td
�D]2}dd����D�}||v�r(�qLt�d��qtj	�
|�|v�sLJ�|D]}tj	�
|��sPJ|���qPdS)
Nr�sxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcst����t��kSr5)r��
open_filesr?��filesrHr?r@rW7r�z-TestProcess.test_open_files.<locals>.<lambda>cSsg|]}tj�|j��qSr?�rCr�rr�r?r?r@r�9r�z/TestProcess.test_open_files.<locals>.<listcomp>r�zIimport time; f = open(r'%s', 'r'); [time.sleep(0.1) for x in range(100)];rcr�cSsg|]}tj�|j��qSr?rnr�r?r?r@r�Jr�rt)r7r8r�rkr�r��flushr&rCr�rr�position�isfilerAr!r�r}�sleep)r;r�r��	filenames�filerr�r?rlr@�test_open_files+s<

.��
zTestProcess.test_open_filescCst��}tjj}|��}t|d���}|��D]*}||j�||j�ksR|j	|�
�kr,qnq,|�dt|�����||j�||j�ks�J�t
r�|j	dks�J�n|j	|�
�ks�J�|��d}|d|jks�J�|d|j	ks�J�|j|��vs�J�Wd�n1�s0YdS)N�wzno file found; files=%sryrrf)r7r8rCr�rr�r�rkrz�fd�filenor~�reprr)r;rHrr��fileobjrtZntupler?r?r@�test_open_files_2Ts*���zTestProcess.test_open_files_2cCs�t��}|��}|��}t|d�}|�|j�|��|dksBJ�t��}|�|j�|��|dksjJ�|��|��|��|ks�J�dS)Nrvrfr�)r7r8r�Znum_fdsr�r��close�socket)r;rHr��startrt�sockr?r?r@�test_num_fdsss
zTestProcess.test_num_fdsz not reliable on OPENBSD & NETBSDcCsTt��}t|���}td�D](}t�d�t|���}||krdSq|�d��dS)Nr�g�������?z2num ctx switches still the same after 2 iterations)r7r8r�Znum_ctx_switchesr�r}rrr~)r;rH�beforer��afterr?r?r@�test_num_ctx_switches�s
z!TestProcess.test_num_ctx_switchescCsFt��}ttd�r&|��t��ks&J�|��}|��t��ksBJ�dS)N�getppid)r7r8r8rC�ppidr�rArDrGr?r?r@�	test_ppid�s

zTestProcess.test_ppidcCsD|��}|��jt��ksJ�t��d}t�|���dus@J�dSr�)rA�parentr9rCrDr7�pidsr8)r;rHZ
lowest_pidr?r?r@�test_parent�szTestProcess.test_parentcCs8t��}|��\}}|��|ks$J�|��|ks4J�dSr5)r7r8rur��r;r�rvrwr?r?r@�test_parent_multi�szTestProcess.test_parent_multicCs`t��}|��sJ�|��\}}|��d|ks4J�|��d|ksHJ�|��d|ks\J�dSr�)r7r8�parentsrur�r?r?r@�test_parents�szTestProcess.test_parentscCs�t��}|��gksJ�|jdd�gks,J�|jdd�}|��}|jdd�}||fD]>}t|�dkshJ�|dj|jks|J�|d��|jksTJ�qTdS)NT��	recursiver)�
creationflagsrf)r7r8�childrenrAr�r9r�)r;r�rvZ	children1Z	children2r�r?r?r@�
test_children�szTestProcess.test_childrencCsft��}|��\}}|��|gks&J�|jdd�||gks>J�|��|��|jdd�gksbJ�dS)NTr�)r7r8rur�rSrKr�r?r?r@�test_children_recursive�sz#TestProcess.test_children_recursivec	Cs�t�t�}t��D]2}z||��d7<WqtjyBYq0qt|��dd�d�dd}t	rx|dkrxt
�d��t�|�}z|j
dd	�}Wntjy�Yn0t|�tt|��ks�J�dS)
NrfcSs|dS)Nrfr?)r�r?r?r@rW�r�z6TestProcess.test_children_duplicates.<locals>.<lambda>)�keyryrzPID 0Tr�)�collections�defaultdictrr7�process_iterr��Errorri�itemsrr,r�r8r�rar�r�)r;�tablerHr9�cr?r?r@�test_children_duplicates�s


z$TestProcess.test_children_duplicatescCs|t��}|��\}}|jdd�}t|�dks0J�|d|ks@J�|d|ksPJ�|��}|d|kshJ�|d|ksxJ�dS)NTr�r�rrf)r7r8rur�r�r�)r;r�rvrwr�r�r?r?r@�test_parents_and_children�sz%TestProcess.test_parents_and_childrencCsX|��}|��td�D] }|��tjkr.q:t�d�q|��|��tjksTJ�dS)Nr�rt)	rArqr�r.r7ZSTATUS_STOPPEDr}rrrr)r;rHr�r?r?r@�test_suspend_resume�szTestProcess.test_suspend_resumecCslt�t��t�d�Wd�n1s*0Yt�t��t�d�Wd�n1s^0YdS)Nrcry)r,rEr�r7r8r{�r;r?r?r@�test_invalid_pid�s(zTestProcess.test_invalid_pidc	Cs�t��}|jddgd�}t|���ddgks0J�t�tt����}|jdgdd�}t|dt�sp|ddkspJ�t	j
ddtjd	��,|jd
gdd�d
diks�J�Wd�n1s�0Yt	j
ddt�|j
d�d	��Lt�tj��|jd
gd�Wd�n1�s0YWd�n1�s,0Yt	j
ddt�|j
d�d	��.|jd
gdd�d
dik�spJ�Wd�n1�s�0Yt	j
ddtd	��h|��}d
t|���v�s�J�t�t��|jd
gd�Wd�n1�s�0YWd�n1�s0Yt�t��|�d�Wd�n1�sF0Yt�t��|�dg�Wd�n1�s~0Yt�t��|�ddg�Wd�n1�s�0YdS)
Nrrz)�attrsZnet_connections�foo)r�Zad_valuezpsutil.Process.niceT)�creater\rArf�bar)r7r8Zas_dictri�keysr�r�r�r]r*r]rar:r9r,rEr%�NotImplementedErrorr�r{)r;rH�dr?r?r@�test_as_dict�sJ�:�N�>�N*,zTestProcess.test_as_dictc	Cs�t��}t�d��V}|��� |��|��Wd�n1sB0Y|jdksZJ�Wd�n1sn0Yt�d�� }|��|��Wd�n1s�0Y|jdks�J�dS)N�$psutil._psplatform.Process.cpu_timesrfr��r7r8r*r]�oneshotr�Z
call_count�r;rHr�r?r?r@�test_oneshot/s
&,&zTestProcess.test_oneshotcCs8t��}t�d���}t�d���}|���X|��|��|��� |��|��Wd�n1sh0YWd�n1s�0Y|jdks�J�|jdks�J�Wd�n1s�0YWd�n1s�0Yt�d�� }|��|��Wd�n1�s0Y|jdk�s4J�dS)Nr�z(psutil._psplatform.Process.oneshot_enterrfr�r�)r;rH�m1�m2r�r?r?r@�test_oneshot_twice<s

DJ(zTestProcess.test_oneshot_twicecCs�|��\}}|��}|��}||ks(J�|���0|��|ksBJ�|��|ksRJ�Wd�n1sf0Y|���0|��|ks�J�|��|ks�J�Wd�n1s�0YdSr5)rur�r�)r;�p1�p2Zp1_ppidZp2_ppidr?r?r@�test_oneshot_cachePs
.
zTestProcess.test_oneshot_cachecsn�fdd�}����������tr8t�fdd������t��}|�|j�D]\}}|||�qVdS)Ncs�z
|�}WnNtjy �Yn\tjy2YnJtjyXtrR|dvrRYdS�Yn$0trj|dvrjdS��d||f��dS)N)r�r�)rrzz+%r didn't raise NSP and returned %r instead)r7r%r:rarrr~)�funZfun_namer�r�r?r@�assert_raises_nspgs

�zFTestProcess.test_halfway_terminated_process.<locals>.assert_raises_nspcs�jt��vSr5)r9r7r�r?r�r?r@rW~r�z=TestProcess.test_halfway_terminated_process.<locals>.<lambda>)	rArSrKrr&rOr+�iter�all)r;r��nsr�rzr?)rHr;r@�test_halfway_terminated_process_s
z+TestProcess.test_halfway_terminated_processcCs|��\}}|�|�dSr5)Zspawn_zombieZassertProcessZombie)r;�_parentZzombier?r?r@�test_zombie_process�szTestProcess.test_zombie_processcCsVt��}tjdt�d�d��&}|��s*J�|js4J�Wd�n1sH0YdS)Nzpsutil.Processrr[)r7r8r*r]r%rr�r�r?r?r@�$test_zombie_process_is_running_w_exc�s
�z0TestProcess.test_zombie_process_is_running_w_exccCs\t��}tjdt�d�d��,}|��tjks0J�|js:J�Wd�n1sN0YdS)Nz!psutil._psplatform.Process.statusrr[)r7r8r*r]r%r.r/r�r�r?r?r@� test_zombie_process_status_w_exc�s�z,TestProcess.test_zombie_process_status_w_excc	
Cs�trddlm}nddlm}|��}t�|j�}|j|��df|_t	t�
��|jtjvsbJ�|��rnJ�t
j�tjdd��Ft|���}t	t�
��Wd�n1s�0YWd�n1s�0Yd|j|��vs�J�|jtjvs�J�|t�|j�k�sJ�d}t|�}|j|j|jdd	�D]p\}}|j|d
��Htjtj|d��|�Wd�n1�sx0YWd�n1�s�0Y�q4dt|�v�s�J�dt|�v�s�J�tjtj|d��|��Wd�n1�s�0Ytjtj|d��|��Wd�n1�s40Ytjtj|d��|��Wd�n1�sn0Ytjtj|d��|� �Wd�n1�s�0YdS)
Nr)�StringIOr�ZPSUTIL_DEBUGTz-refreshing Process instance for reused PID %sz4process no longer exists and its PID has been reusedF)�clear_cache)rzr�zterminated + PID reused)!r�ior�r6r7r8r9r��_identr]r�Z_pmaprr*r]�object�_commonr�getvaluer+r��settersZkillersrEr,rEr:rBryr�r�r�r�)	r;r�ZsubprHr��msgr�r�rzr?r?r@�test_reused_pid�sDH��J(((zTestProcess.test_reused_pidc	Cs�dt��vrjt�tj��t�d�Wd�n1s80Yt�d�rPJ�t�d���dksfJ�dSt�d�}tr~tj	nt
}t�|��|��Wd�n1s�0Yt�|��|��Wd�n1s�0Yt�|��|�
�Wd�n1�s0Yt�|��|��Wd�n1�sD0Yt�|��|��Wd�n1�sx0Yt�|��|�tj�Wd�n1�s�0Yt|�}|�|j|j�D]�\}}z
|�}Wntj	�y�Ynb0|dv�r|jdk�s^J�nD|dk�rFt�r.dnd}|��|k�s^J�n|dk�r�|�s�J|���q�t�s�dt��v�szJ�t�d��s�J�dS)Nrrf)r5r<rKzNT AUTHORITY\SYSTEM�rootrz)r7r�r,rEr:r8Z
pid_existsr�rrar{rKrSrqrrrJrUrLrMr+r�Zgettersr�r:rKr)r;rHr�r�r�rzr�r�r?r?r@�
test_pid_0�sH(
&&(((,



zTestProcess.test_pid_0cCsHdd�}d|_t��}||���}|tj���}tsDtrD||ksDJ�dS)NcSsFgd�}tr|�gd��|D]}|�|d�qtdd�|��D��S)N)�PLAT�HOMEZPYTEST_CURRENT_TESTZPYTEST_VERSION)Z__CF_USER_TEXT_ENCODINGZVERSIONER_PYTHON_PREFER_32_BIT�VERSIONER_PYTHON_VERSIONr�cSs8g|]0\}}|�dd��dd�|�dd��dd�f�qS)�
rZ�
)r)r��k�vr?r?r@r�
s��z@TestProcess.test_environ.<locals>.clean_dict.<locals>.<listcomp>)rr$�pop�dictr�)r��excluderzr?r?r@�
clean_dict�s�z,TestProcess.test_environ.<locals>.clean_dict)ZmaxDiffr7r8rPrC�copyr	r)r;r�rHZd1Zd2r?r?r@�test_environ�szTestProcess.test_environz<macOS 11+ can't get another process environment, issue #2084z(sometimes fails on `assert is_running()`cCs�t�d�}t|��|d�}|j|gtjtjd�}t�|j	�}t
|j	�|��sRJ�|j�
�dksdJ�tr�tr�z|��}Wq�tjy�YdS0n|��}|ddd�ks�J�|��|jdks�J�dS)	Na�
            #include <unistd.h>
            #include <fcntl.h>

            char * const argv[] = {"cat", 0};
            char * const envp[] = {"A=1", "X", "C=3", 0};

            int main(void) {
                // Close stderr on exec so parent can wait for the
                // execve to finish.
                if (fcntl(2, F_SETFD, FD_CLOEXEC) != 0)
                    return 0;
                return execve("/bin/cat", argv, envp);
            }
            )Zc_code)�stdinrer�rc�3)�A�Cr)�textwrap�dedentr(r�r6rhrir7r8r9r3rrer�rrrPra�communicate�
returncode)r;rQZcexer>rH�envr?r?r@�test_weird_environs$
�

zTestProcess.test_weird_environN)m�__name__�
__module__�__qualname__�__doc__rArIrRrTrWr,�mark�skipifr
rbrkrrsrxr|rr�r�r#r�r�rr�r�r�rr2rr�rr�rr�rr�r�r�r�r�r�r�rr�r/r1rr�r�r�rr
rrrrr"r r&r)r1rrr2r;r@rGrHrRrUrXrrardrjrrrur{r�rr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rr�rr�r?r?r?r@r4Ps 










)+�








/
	





B

&

&

�



4
&



..
��r4csreZdZdZeed�r&e��Ze��Z	�fdd�Z
�fdd�Z�fdd�Zd	d
�Z
ejjddd
�dd��Z�ZS)�LimitedUserTestCasez�Repeat the previous tests by using a limited user.
        Executed only on UNIX and only if the user who run the test script
        is root.
        r6csXt�j|i|��dd�t|�D�D].}t||���fdd�}t||t�||��q$dS)NcSsg|]}|�d�r|�qS)�testr�r�r?r?r@r�`r�z0LimitedUserTestCase.__init__.<locals>.<listcomp>cs$z
��WntjyYn0dSr5)r7rar���methr?r@�test_cs
z+LimitedUserTestCase.__init__.<locals>.test_)r�__init__r�r��setattr�types�
MethodType)r;r<r=�attrr���	__class__r�r@r�\s

zLimitedUserTestCase.__init__cs"t���t�d�t�d�dS)Ni�)r�setUprC�setegid�seteuidr�r�r?r@r�ks

zLimitedUserTestCase.setUpcs&t�|j�t�|j�t���dSr5)rCr��PROCESS_UIDr��PROCESS_GIDr�tearDownr�r�r?r@r�pszLimitedUserTestCase.tearDowncCs6zt���d�Wntjy&Yn0|�d��dS)Nryzexception not raised)r7r8rArar~r�r?r?r@rGus
zLimitedUserTestCase.test_niceTzcauses problem as rootrXcCsdSr5r?r�r?r?r@r�}sz'LimitedUserTestCase.test_zombie_process)r�r�r�r�r8rCr6r�r=r�r�r�r�rGr,r�r�r��
__classcell__r?r?r�r@r�Qs
r�c@s4eZdZdZedd��Zdd�Zdd�Zdd	�Zd
S)�	TestPopenzTests for psutil.Popen class.cCs
t�dSr5r-)�clsr?r?r@�
tearDownClass�szTestPopen.tearDownClassc	Cs�tddg}tj|tjtjtd��j}|��|��|jt	|�sDJ�t
�t��|j
Wd�n1sj0Y|��Wd�n1s�0Ytr�|�d�tjks�J�n|�d�tjks�J�dS)Nrc�3import time; [time.sleep(0.1) for x in range(100)];��stdoutrer�rg)r!r7�Popenrhrir"rzr�r�r�r,rErFr�rSr
rKrLrM�r;rj�procr?r?r@�	test_misc�s*��$&zTestPopen.test_misccCs|tjtdgtjtjtjtd��}|��Wd�n1s<0Y|jjsRJ�|j	js^J�|j
jsjJ�|jdksxJ�dS)Nz-V)r�rer�r�r)r7rr!rhrir"r�r��closedrer�r�)r;rr?r?r@�test_ctx_manager�s�&zTestPopen.test_ctx_managerc	Csrtddg}tj|tjtjtd���:}|��|��t�	tj
��|��Wd�n1s^0Yt�	tj
��|��Wd�n1s�0Yt�	tj
��|�t
j�Wd�n1s�0Yt�rNt�	tj
��|�t
j�Wd�n1�s
0Yt�	tj
��|�t
j�Wd�n1�sD0YWd�n1�sd0YdS)Nrcr�r�)r!r7rrhrir"rSrKr,rEr:rJrUrLrMrZCTRL_C_EVENTZCTRL_BREAK_EVENTrr?r?r@�test_kill_terminate�s0��&&*,zTestPopen.test_kill_terminateN)	r�r�r�r��classmethodr�rrrr?r?r?r@r��s
r�)Gr�r�r_rMrfrCrLr}rr,rhrr�r}r�r7rrrrrrr	r
rrZpsutil._commonr
Zpsutil._compatrrrrrZpsutil.testsrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r.r/r0r1r2r3r4r6r�r�r?r?r?r@�<module>s�6PKok\��yZ556psutil/tests/__pycache__/test_contracts.cpython-39.pycnu�[���a

��?h!1�@s�dZddlZddlZddlZddlmZddlmZddlmZddlmZddlmZddlm	Z	dd	lm
Z
dd
lmZddlmZddl
mZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZGdd�de�ZGdd�de�ZGdd �d e�Z Gd!d"�d"e�Z!Gd#d$�d$e�Z"dS)%z�Contracts tests. These tests mainly check API sanity in terms of
returned types and APIs availability.
Some of these are duplicates of tests test_system.py and test_process.py.
�N)�AIX)�FREEBSD)�LINUX)�MACOS)�NETBSD)�OPENBSD)�POSIX)�SUNOS)�WINDOWS)�long)�GITHUB_ACTIONS)�HAS_CPU_FREQ)�HAS_NET_IO_COUNTERS)�HAS_SENSORS_FANS)�HAS_SENSORS_TEMPERATURES)�PYPY)�	QEMU_USER)�SKIP_SYSCONS)�PsutilTestCase)�create_sockets)�enum)�
is_namedtuple)�kernel_version)�pytestc@sHeZdZdd�Zdd�Zdd�Zdd�Zejj	e
o4ed	d
�dd��Zd
S)�TestAvailConstantsAPIscCsttd�tptptksJ�dS)NZPROCFS_PATH)�hasattr�psutilrr	r��self�r�G/usr/local/lib64/python3.9/site-packages/psutil/tests/test_contracts.py�test_PROCFS_PATH3sz'TestAvailConstantsAPIs.test_PROCFS_PATHcCsj|j}|ttd�t�|ttd�t�|ttd�t�|ttd�t�|ttd�t�|ttd�t�dS)NZABOVE_NORMAL_PRIORITY_CLASSZBELOW_NORMAL_PRIORITY_CLASSZHIGH_PRIORITY_CLASSZIDLE_PRIORITY_CLASSZNORMAL_PRIORITY_CLASSZREALTIME_PRIORITY_CLASS��assertEqualrrr
�rZaerrr �test_win_priority6sz(TestAvailConstantsAPIs.test_win_prioritycCsJ|j}|ttd�t�|ttd�t�|ttd�t�|ttd�t�dS)NZIOPRIO_CLASS_NONEZIOPRIO_CLASS_RTZIOPRIO_CLASS_BEZIOPRIO_CLASS_IDLE)r#rrrr$rrr �test_linux_ioprio_linux?s
z.TestAvailConstantsAPIs.test_linux_ioprio_linuxcCsJ|j}|ttd�t�|ttd�t�|ttd�t�|ttd�t�dS)NZIOPRIO_HIGHZ
IOPRIO_NORMALZ
IOPRIO_LOWZIOPRIO_VERYLOWr"r$rrr �test_linux_ioprio_windowsFs
z0TestAvailConstantsAPIs.test_linux_ioprio_windows�%unsupported on GITHUB_ACTIONS + LINUX��reasoncCs�|j}|ttd�tpt�|ttd�tp*t�|ttd�tp>t�|ttd�tpRt�|ttd�tpft�|ttd�tpzt�|ttd�tp�t�|ttd�tp�t�|ttd	�tp�t�|ttd
�tp�t�|ttd�tp�t�|ttd�t�t�r�t�d
k�r|ttd�t�t�dk�r0|ttd�t�t�dk�rL|ttd�t�t�dk�rh|ttd�t�t�d
k�r�|ttd�t�|ttd�t�|ttd�t�|ttd�t�dS)NZ
RLIM_INFINITYZ	RLIMIT_ASZRLIMIT_COREZ
RLIMIT_CPUZRLIMIT_DATAZRLIMIT_FSIZEZRLIMIT_MEMLOCKZ
RLIMIT_NOFILEZRLIMIT_NPROCZ
RLIMIT_RSSZRLIMIT_STACKZRLIMIT_LOCKS)���ZRLIMIT_MSGQUEUE)r+r,�ZRLIMIT_NICEZ
RLIMIT_RTPRIO)r+r,�Z
RLIMIT_RTTIMEZRLIMIT_SIGPENDINGZRLIMIT_SWAPZ
RLIMIT_SBSIZEZRLIMIT_NPTS)r#rrrrrrr$rrr �test_rlimitMs6z"TestAvailConstantsAPIs.test_rlimitN)
�__name__�
__module__�__qualname__r!r%r&r'r�mark�skipifrrr0rrrr r2s	�rc@s<eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
S)�TestAvailSystemAPIscCsttd�tksJ�dS)NZwin_service_iter�rrr
rrrr �test_win_service_iterrsz)TestAvailSystemAPIs.test_win_service_itercCsttd�tksJ�dS)NZwin_service_getr7rrrr �test_win_service_getusz(TestAvailSystemAPIs.test_win_service_getcCs&ttd�tptptptptks"J�dS)N�cpu_freq)rrrrr
rrrrrr �
test_cpu_freqxs�z!TestAvailSystemAPIs.test_cpu_freqcCsttd�tptksJ�dS)N�sensors_temperatures)rrrrrrrr �test_sensors_temperatures}sz-TestAvailSystemAPIs.test_sensors_temperaturescCsttd�tksJ�dS)N�sensors_fans)rrrrrrr �test_sensors_fans�sz%TestAvailSystemAPIs.test_sensors_fanscCs"ttd�tptptptksJ�dS)NZsensors_battery)rrrr
rrrrrr �test_battery�s�z TestAvailSystemAPIs.test_batteryN)	r1r2r3r8r9r;r=r?r@rrrr r6qsr6c@s�eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zej	j
eo<edd�d
d��Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�ZdS)�TestAvailProcessAPIscCs4ttjd�tp(tp(tp(tp(tp(tp(t	p(t
ks0J�dS)N�environ)rr�Processrrr
rr	rrrrrrr �test_environ�s 
�������z!TestAvailProcessAPIs.test_environcCsttjd�tksJ�dS�NZuids�rrrCrrrrr �	test_uids�szTestAvailProcessAPIs.test_uidscCsttjd�tksJ�dSrErFrrrr �	test_gids�szTestAvailProcessAPIs.test_gidscCsttjd�tksJ�dS)N�terminalrFrrrr �
test_terminal�sz"TestAvailProcessAPIs.test_terminalcCsttjd�tptksJ�dS)NZionice)rrrCrr
rrrr �test_ionice�sz TestAvailProcessAPIs.test_ionicer(r)cCsttjd�tptksJ�dS)NZrlimit)rrrCrrrrrr r0�sz TestAvailProcessAPIs.test_rlimitcCs"ttjd�}|tptksJ�dS)NZio_counters)rrrCrr	�rZhasitrrr �test_io_counters�sz%TestAvailProcessAPIs.test_io_counterscCsttjd�tksJ�dS)NZnum_fdsrFrrrr �test_num_fds�sz!TestAvailProcessAPIs.test_num_fdscCsttjd�tksJ�dS)NZnum_handles)rrrCr
rrrr �test_num_handles�sz%TestAvailProcessAPIs.test_num_handlescCs ttjd�tptptksJ�dS)NZcpu_affinity)rrrCrr
rrrrr �test_cpu_affinity�s

�z&TestAvailProcessAPIs.test_cpu_affinitycCs ttjd�tptptksJ�dS)NZcpu_num)rrrCrrr	rrrr �test_cpu_num�s

�z!TestAvailProcessAPIs.test_cpu_numcCs*ttjd�}|tptptptks&J�dS)NZmemory_maps)rrrCrrrrrLrrr �test_memory_maps�sz%TestAvailProcessAPIs.test_memory_mapsN)r1r2r3rDrGrHrJrKrr4r5rrr0rMrNrOrPrQrRrrrr rA�s �
rAc@s&eZdZdZedd��Zedfdd�Zdd�Zd	d
�Z	dd�Z
d
d�Zej
jeoZe��dkdd�ej
jedd�dd���Zdd�Zdd�Zej
jedd�dd��Zdd�Zej
jedd�dd ��Zej
jedd�d!d"��Zej
jedd�d#d$��Zej
jedd�d%d&��Z d'd(�Z!d)d*�Z"d+S),�TestSystemAPITypesz�Check the return types of system related APIs.
    Mainly we want to test we never return unicode on Python 2, see:
    https://github.com/giampaolo/psutil/issues/1039.
    cCst��|_dS�N)rrC�proc)�clsrrr �
setUpClass�szTestSystemAPITypes.setUpClassTcCs8t|�sJ�|D]"}t||�s"J�|r|dksJ�qdS)Nr)r�
isinstance)r�nt�type_Zgezero�nrrr �assert_ntuple_of_nums�s
z(TestSystemAPITypes.assert_ntuple_of_numscCs.|�t���tjdd�D]}|�|�qdS)NT)Zpercpu)r\rZ	cpu_times)rrYrrr �test_cpu_times�sz!TestSystemAPITypes.test_cpu_timescCs0ttjdd�t�sJ�ttjdd�t�s,J�dS)N��intervalg�h㈵��>)rXrZcpu_percent�floatrrrr �test_cpu_percent�sz#TestSystemAPITypes.test_cpu_percentcCs(|�tjdd��|�tjdd��dS)Nr^g-C��6?)r\rZcpu_times_percentrrrr �test_cpu_times_percent�sz)TestSystemAPITypes.test_cpu_times_percentcCstt��t�sJ�dSrT)rXr�	cpu_count�intrrrr �test_cpu_count�sz!TestSystemAPITypes.test_cpu_count�arm64zskipped due to #1892r)z
not supportedcCs2t��durt�d��|jt��tttfd�dS)Nzcpu_freq() returns None�rZ)rr:r�skipr\r`rdrrrrr r;�s
z TestSystemAPITypes.test_cpu_freqcCs>tjdd���D](\}}t|t�s&J�|j|ttfd�qdS)NT)Zperdiskrg)rZdisk_io_counters�itemsrX�strr\rdr)r�k�vrrr �test_disk_io_counters�sz(TestSystemAPITypes.test_disk_io_counterscCsRt��D]D}t|jt�sJ�t|jt�s,J�t|jt�s<J�t|jt�sJ�qdSrT)rZdisk_partitionsrXZdevicerjZ
mountpointZfstype�opts)rZdiskrrr �test_disk_partitions�s
z'TestSystemAPITypes.test_disk_partitionsz
requires rootcCsbt��Ht�d�}t|�tt|��ks*J�|D]}t|�s.J�q.Wd�n1sT0YdS)N�all)rrZnet_connections�len�setr)r�ret�connrrr �test_net_connectionss

z'TestSystemAPITypes.test_net_connectionscCs�t����D]�\}}t|t�s"J�|D]t}tdurJtsJt|jtj�sZJ�nt|jt	�sZJ�t|j
t�sjJ�t|jttd�f�s�J�t|j
ttd�f�s&J�q&qdSrT)rZnet_if_addrsrirXrjrr�family�IntEnumrd�address�netmask�type�	broadcast)r�ifname�addrs�addrrrr �test_net_if_addrssz$TestSystemAPITypes.test_net_if_addrszQEMU user not supportedcCs�t����D]r\}}t|t�s"J�t|jt�s2J�tdurNt|jtj	�s^J�nt|jt
�s^J�t|jt
�snJ�t|jt
�sJ�qdSrT)
rZnet_if_statsrirXrjZisup�boolrZduplexrwrd�speedZmtu)rr|�inforrr �test_net_if_statssz$TestSystemAPITypes.test_net_if_statscCs$tjdd�D]}t|t�sJ�qdS)NT)Zpernic)rZnet_io_countersrXrj)rr|rrr �test_net_io_counters"sz'TestSystemAPITypes.test_net_io_counterscCs\t����D]J\}}t|t�s"J�|D].}t|jt�s:J�t|jttt	d�f�s&J�q&qdSrT)
rr>rirXrj�label�currentr`rdrz�r�nameZunits�unitrrr r?(s
z$TestSystemAPITypes.test_sensors_fanscCs�t����D]~\}}t|t�s"J�|D]b}t|jt�s:J�t|jttt	d�f�sTJ�t|j
ttt	d�f�snJ�t|jttt	d�f�s&J�q&qdSrT)rr<rirXrjr�r�r`rdrz�high�criticalr�rrr r=1sz,TestSystemAPITypes.test_sensors_temperaturescCstt��t�sJ�dSrT)rXrZ	boot_timer`rrrr �test_boot_time<sz!TestSystemAPITypes.test_boot_timecCsjt��D]\}t|jt�sJ�t|jttd�f�s4J�t|jttd�f�sLJ�t|jt	td�f�sJ�qdSrT)
rZusersrXr�rjrIrz�host�pidrd)r�userrrr �
test_users@s
zTestSystemAPITypes.test_usersN)#r1r2r3�__doc__�classmethodrWr`r\r]rarbrerr4r5r�platform�machiner
r;rmrorrurrr�rr�rr?rr=r�r�rrrr rS�s8
�






rSc@s&eZdZejjedd�dd��ZdS)�TestProcessWaitTypez	not POSIXr)cCs\t�|��j�}|��|��}|tjks0J�tdurJt	|tj
�sXJ�nt	|t�sXJ�dSrT)rrCZspawn_testprocr��	terminate�wait�signal�SIGTERMrrXrwrd)r�p�coderrr �test_negative_signalJsz(TestProcessWaitType.test_negative_signalN)r1r2r3rr4r5rr�rrrr r�Isr�)#r�r�r�rrrrrrrrr	r
Zpsutil._compatrZpsutil.testsrr
rrrrrrrrrrrrrr6rArSr�rrrr �<module>sB?>PKok\R4�(||1psutil/tests/__pycache__/test_misc.cpython-39.pycnu�[���a

��?h���@sfdZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZ
ddl
mZddl
m
Z
ddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*dd lm+Z+dd!lm,Z,dd"lm-Z-Gd#d$�d$e'�Z.Gd%d&�d&e'�Z/Gd'd(�d(e'�Z0Gd)d*�d*e'�Z1e�2d+d,�Z3Gd-d.�d.e'�Z4e*j5j6ej7�8e&�d/d0�Gd1d2�d2e'��Z9dS)3zMiscellaneous tests.�N)�POSIX)�WINDOWS)�bcat)�cat)�debug)�
isfile_strict)�memoize)�memoize_when_activated��parse_environ_block)�
supports_ipv6��wrap_numbers)�PY3)�FileNotFoundError)�redirect_stderr)�
CI_TESTING)�HAS_BATTERY)�HAS_MEMORY_MAPS)�HAS_NET_IO_COUNTERS)�HAS_SENSORS_BATTERY)�HAS_SENSORS_FANS)�HAS_SENSORS_TEMPERATURES)�
PYTHON_EXE)�PYTHON_EXE_ENV)�	QEMU_USER)�SCRIPTS_DIR)�PsutilTestCase)�mock)�process_namespace)�pytest)�
reload_module)�sh)�system_namespacec@s�eZdZdd�Zefdd�Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�ZdS) �TestSpecialMethodscCszt�t��"tjj�dd�Wd�n1s20Yt�tj��t�dd�Wd�n1sl0YdS)N��)	r �raises�
OverflowError�psutilZ_psplatformZcextZcheck_pid_range�
NoSuchProcess�Process��self�r.�B/usr/local/lib64/python3.9/site-packages/psutil/tests/test_misc.py�test_check_pid_range>s0z'TestSpecialMethods.test_check_pid_rangecCst�|��j�}||�}d|vs$J�d|j|vs6J�dt|���|�dd�vsVJ�d|vsbJ�d|vsnJ�|��|��||�}d|vs�J�d|vs�J�t	j
jtjd	t�t
���d
��Jt��}||�}d|j|vs�J�d|vs�J�d|vs�J�Wd�n1�s0Yt	j
jtjd	t�t
���d
��Pt��}||�}d|j|v�s\J�d
|v�sjJ�d|v�sxJ�Wd�n1�s�0Yt	j
jtjd	t�t
���d
��Bt��}||�}d|j|v�s�J�d|v�s�J�Wd�n1�s0YdS)Nzpsutil.Processzpid=%sz	name='%s'zname=u'zname='zstatus=z	exitcode=zstatus='terminated'�name�Zside_effectzstatus='zombie'zname=Z
terminated)r)r+Zspawn_testproc�pid�strr1�replace�	terminate�waitr�patch�object�
ZombieProcess�os�getpidr*�AccessDenied)r-�func�p�rr.r.r/�test_process__repr__DsR �,�.�z'TestSpecialMethods.test_process__repr__cCs|jtd�dS)N)r>)rAr4r,r.r.r/�test_process__str__psz&TestSpecialMethods.test_process__str__cCstt���dksJ�dS)Nzpsutil.Error())�reprr)�Errorr,r.r.r/�test_error__repr__ssz%TestSpecialMethods.test_error__repr__cCstt���dksJ�dS)N�)r4r)rDr,r.r.r/�test_error__str__vsz$TestSpecialMethods.test_error__str__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)N�Az=psutil.NoSuchProcess(pid=321, msg='process no longer exists')r1�msg�r1rIz5psutil.NoSuchProcess(pid=321, name='name', msg='msg'))rCr)r*r,r.r.r/�test_no_such_process__repr__ys����z/TestSpecialMethods.test_no_such_process__repr__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)NrHz"process no longer exists (pid=321)r1rIrJ�msg (pid=321, name='name'))r4r)r*r,r.r.r/�test_no_such_process__str__�s����z.TestSpecialMethods.test_no_such_process__str__cCs8tt�d��dksJ�ttjddddd��dks4J�dS)NrHzGpsutil.ZombieProcess(pid=321, msg="PID still exists but it's a zombie")r1�@�foo�r1�ppidrIz?psutil.ZombieProcess(pid=321, ppid=320, name='name', msg='foo'))rCr)r:r,r.r.r/�test_zombie_process__repr__�s����z.TestSpecialMethods.test_zombie_process__repr__cCs8tt�d��dksJ�ttjddddd��dks4J�dS)NrHz,PID still exists but it's a zombie (pid=321)r1rNrOrPz$foo (pid=321, ppid=320, name='name'))r4r)r:r,r.r.r/�test_zombie_process__str__�s����z-TestSpecialMethods.test_zombie_process__str__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)NrHzpsutil.AccessDenied(pid=321)r1rIrJz4psutil.AccessDenied(pid=321, name='name', msg='msg'))rCr)r=r,r.r.r/�test_access_denied__repr__�s
��z-TestSpecialMethods.test_access_denied__repr__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)NrHz	(pid=321)r1rIrJrL)r4r)r=r,r.r.r/�test_access_denied__str__�s
��z,TestSpecialMethods.test_access_denied__str__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)N�z?psutil.TimeoutExpired(seconds=5, msg='timeout after 5 seconds')rHr1�r3r1zUpsutil.TimeoutExpired(pid=321, name='name', seconds=5, msg='timeout after 5 seconds'))rCr)�TimeoutExpiredr,r.r.r/�test_timeout_expired__repr__�s����z/TestSpecialMethods.test_timeout_expired__repr__cCs6tt�d��dksJ�ttjdddd��dks2J�dS)NrVztimeout after 5 secondsrHr1rWz.timeout after 5 seconds (pid=321, name='name'))r4r)rXr,r.r.r/�test_timeout_expired__str__�s
��z.TestSpecialMethods.test_timeout_expired__str__cCs>t��}t��}||ksJ�d|_||ks.J�|dks:J�dS)N)rrrO)r)r+�_ident)r-�p1�p2r.r.r/�test_process__eq__�sz%TestSpecialMethods.test_process__eq__cCs(tt��t��g�}t|�dks$J�dS)N�)�setr)r+�len)r-�sr.r.r/�test_process__hash__�sz'TestSpecialMethods.test_process__hash__N)�__name__�
__module__�__qualname__r0rCrArBrErGrKrMrRrSrTrUrYrZr^rcr.r.r.r/r$=s,


r$c@s<eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
S)�TestMiscc	Cs�tt�}|D]~}|dvrq|�d�szt|�Wqty�|tjvr�tt|�}|dur^Yq|jdur�d|j��vr�|�	d|��Yq0qtjD]}||vs�J�q�dS)N)r�long�tests�test�PermissionError�ProcessLookupError�_�
deprecatedz%r not in psutil.__all__)
�dirr)�
startswith�
__import__�ImportError�__all__�getattr�__doc__�lower�fail)r-Z
dir_psutilr1�funr.r.r/�test__all__�s&


��
zTestMisc.test__all__cCs$d�dd�tjD��tjks J�dS)N�.cSsg|]}t|��qSr.)r4)�.0�xr.r.r/�
<listcomp>��z)TestMisc.test_version.<locals>.<listcomp>)�joinr)�version_info�__version__r,r.r.r/�test_version�s��zTestMisc.test_versioncCs"t��}d|_d|��vsJ�dS)N�1rO)r)r+rO�as_dict)r-r?r.r.r/�!test_process_as_dict_no_new_names�sz*TestMisc.test_process_as_dict_no_new_namesc
Cs�dd�}t��}|t�����t|�}|j|jdd�D]^\}}|j||d��8z
|�}WntjynYn
0||�Wd�q81s�0Yq8t�}|�|j�D]v\}}|dvr�q�t	r�|dkr�q�|j|d��8z
|�}Wntj
y�Yn
0||�Wd�q�1�s0Yq�t�t�
tjd	d
dd���}t|tj��sPJ�|jd	k�s`J�|jd
k�spJ�|jdk�s�J�t�t�
tjd	d
d
dd���}t|tj��s�J�|jd	k�s�J�|jd
k�s�J�|jd
k�s�J�|jdk�s�J�t�t�
tj
dd
dd���}t|tj
��sJ�|jdk�s.J�|jd
k�s>J�|jdk�sNJ�t�t�
tjdd	d
d���}t|tj��s|J�|jdk�s�J�|jd	k�s�J�|jd
k�s�J�dS)NcSs4t�t�|��t�|�}t�|�}||ks0J�dS�N)�json�loads�dumps�pickle)�ret�a�br.r.r/�checks

z*TestMisc.test_serialization.<locals>.checkT)�clear_cache)�procr1>Zwin_service_iterZwin_service_getZnet_if_stats)r1i�r1rI)r3r1rI�*)r3r1rQrI�{�!)�secondsr3r1)r)r+r�r�iterZgettersZsubTestrDr#rr=r�r�r�r*�
isinstancer3r1rIr:rQrXr�)r-r�r��nsrxr1r�r�r.r.r/�test_serializationst	
(
*�������zTestMisc.test_serializationc	Cs�tjjtjdtjd��"}t��|js*J�Wd�n1s>0Ytjjtjdt�d�d��"}t��|jsvJ�Wd�n1s�0Ytjjtjdtd��L}t	�
t��t��Wd�n1s�0Y|js�J�Wd�n1s�0Ytjjtjdt�d�d��R}|�tj��t��Wd�n1�sL0Y|j�sbJ�Wd�n1�sx0YdS)NZ
_get_identr2r_)
rr8r9r)r+r=�calledr:�
ValueErrorr r'r*�assertRaises)r-�methr.r.r/�test_ad_on_process_creationas4
�(�(�&(�(z$TestMisc.test_ad_on_process_creationc	Csztjddd��Xt�t��}tt�Wd�n1s80Ydt|j��	�vsXJ�Wd�n1sl0YdS)Nzpsutil._psplatform.cext.versionz0.0.0�Zreturn_valuezversion conflict)
rr8r r'rrr!r)r4�valuerv)r-�cmr.r.r/�test_sanity_version_check~s�&z"TestMisc.test_sanity_version_checkN)	rdrerfryr�r�r�r�r�r.r.r.r/rg�s!]rgc@sReZdZdd�ZeZddd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dd�ZdS)�TestMemoizeDecoratorcCs
g|_dSr���callsr,r.r.r/�setUp�szTestMemoizeDecorator.setUpNcCs2td�D]2}|�}|jdifgks&J�|dur||ksJ�qtd�D]:}|d�}|jdifdifgksjJ�|durD||ksDJ�qDtd�D]H}|ddd�}|jdifdifdddifgks�J�|dur�||ks�J�q�t|j�dks�J�|��|�}|du�r
||k�s
J�t|j�dk�sJ�|jd	k�s.J�dS)
Nr%r.r_�r_��barr����
My docstring.)�ranger�ra�cache_clearru)r-�obj�expected_retvalrmr�r.r.r/�run_against�s,$
z TestMemoizeDecorator.run_againstcs&t�fdd��}|�|j|dd�dS)Ncs�j�||f�dS�r���r��append��args�kwargs�Z	baseclassr.r/rO�sz/TestMemoizeDecorator.test_function.<locals>.foor��r�)rr�)r-rOr.r�r/�
test_function�sz"TestMemoizeDecorator.test_functioncs>tG�fdd�d��}|�|j|dd�|���dks:J�dS)Ncs$eZdZdZ�fdd�Zdd�ZdS)z,TestMemoizeDecorator.test_class.<locals>.Foor�cs�j�||f�dSr�r��r-r�r�r�r.r/�__init__�sz5TestMemoizeDecorator.test_class.<locals>.Foo.__init__cSsdS)Nr�r.r,r.r.r/r��sz0TestMemoizeDecorator.test_class.<locals>.Foo.barN)rdrerfrur�r�r.r�r.r/�Foo�sr�r�r�)rr�r��r-r�r.r�r/�
test_class�s
	zTestMemoizeDecorator.test_classcCs�tGdd�d��}|�|�us"J�t|��t|��ks:J�t|d��t|d��ksVJ�t|ddd��t|ddd��kszJ�t|d��t|d��ks�J�dS)Nc@seZdZdd�ZdS)z6TestMemoizeDecorator.test_class_singleton.<locals>.Barc_sdSr�r.r�r.r.r/r��sz?TestMemoizeDecorator.test_class_singleton.<locals>.Bar.__init__N)rdrerfr�r.r.r.r/�Bar�sr�r_r�)rOr%)r�id)r-r�r.r.r/�test_class_singleton�s$z)TestMemoizeDecorator.test_class_singletoncs,G�fdd�d�}|�|j|�jdd�dS)Ncs eZdZee�fdd���ZdS)z3TestMemoizeDecorator.test_staticmethod.<locals>.Foocs�j�||f�dSr�r�r�r�r.r/r��sz7TestMemoizeDecorator.test_staticmethod.<locals>.Foo.barN)rdrerf�staticmethodrr�r.r�r.r/r��sr�r�r��r�r�r�r.r�r/�test_staticmethod�sz&TestMemoizeDecorator.test_staticmethodcs,G�fdd�d�}|�|j|�jdd�dS)Ncs eZdZee�fdd���ZdS)z2TestMemoizeDecorator.test_classmethod.<locals>.Foocs�j�||f�dSr�r�)�clsr�r�r�r.r/r��sz6TestMemoizeDecorator.test_classmethod.<locals>.Foo.barN)rdrerf�classmethodrr�r.r�r.r/r��sr�r�r�r�r�r.r�r/�test_classmethod�sz%TestMemoizeDecorator.test_classmethodcst�fdd��}g�td�D].}|�}dif}||ks:J�t��dksJ�qtd�D]0}|d�}dif}||kstJ�t��dksTJ�qTtd�D]8}|ddd�}dddif}||ks�J�t��d	ks�J�q�|��|�}dif}||ks�J�t��d
ks�J�|jdk�s
J�dS)Ncs��d�||fS)�Foo docstring.N�r�r�r�r.r/rO�s
z/TestMemoizeDecorator.test_original.<locals>.foor%r.r_r�r�r�r�r�r�)rr�rar�ru)r-rOrmr��expectedr.r�r/�
test_original�s0z"TestMemoizeDecorator.test_original)N)rdrerfr��tearDownr�r�r�r�r�r�r�r.r.r.r/r��s


r�c@s<eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
S)�TestCommonModulecs�G�fdd�d�}|�}g�|��|��t��dks<J�g�|j�|�|��|��t��dkslJ�g�|j�|�|��|��t��dks�J�dS)NcseZdZe�fdd��ZdS)z9TestCommonModule.test_memoize_when_activated.<locals>.Foocs��d�dSr�r�r,r�r.r/rOsz=TestCommonModule.test_memoize_when_activated.<locals>.Foo.fooN)rdrerfr	rOr.r�r.r/r�sr�r%r_)rOraZcache_activateZcache_deactivate)r-r��fr.r�r/�test_memoize_when_activateds z,TestCommonModule.test_memoize_when_activatedcCs�dd�}td�|d�diks J�td�|d�d|d�diks@J�td	�|d�d|d�d
iks`J�td�|d�d|d�diks�J�td�|d�diks�J�td
�|d�diks�J�td�|d�diks�J�dS)NcSstr|��S|Sr�)r�upper)rbr.r.r/�k0sz4TestCommonModule.test_parse_environ_block.<locals>.kza=1r�r�z	a=1b=2r��2za=1b=rFz
a=1b=2c=3zxxxa=1z	a=1=b=2za=1b=2r
)r-r�r.r.r/�test_parse_environ_block/s�
 �
z)TestCommonModule.test_parse_environ_blockc	Cs�|�tj�t��rRt�d��(}d|_t��t�r8J�Wd�n1sL0Yt��tjdtjd��$}t�rzJ�|js�J�Wd�n1s�0Yt��tjdtj	d��,}t�r�J�t��|js�J�Wd�n1s�0Yt��tjdtj	d��0}t��rJ�t��|j�s0J�Wd�n1�sF0Yn`t
�tj��Bt�tjtj
�}z|�d�W|��n
|��0Wd�n1�s�0YdS)Nzpsutil._common.socketFzpsutil._common.socket.socketr2z!psutil._common.socket.socket.bind)z::1r)Z
addCleanuprr�rr8�has_ipv6�socket�errorr��gaierrorr r'�AF_INET6�SOCK_STREAM�bind�close)r-rb�sockr.r.r/�test_supports_ipv6DsF(�
(�
(�.z#TestCommonModule.test_supports_ipv6c	Cs�tj�t�}t|�sJ�ttj�|��r,J�tjdtt	j
d�d��Bt�t��t|�Wd�n1sl0YWd�n1s�0Ytjdtt	j
d�d��Bt�t��t|�Wd�n1s�0YWd�n1s�0Ytjdtt	jd�d��t|��r"J�Wd�n1�s80Ytjddd��t|��r`J�Wd�n1�sv0YdS)Nzpsutil._common.os.statrOr2zpsutil._common.stat.S_ISREGFr�)r;�path�abspath�__file__r�dirnamerr8�OSError�errno�EPERMr r'�EACCES�ENOENT)r-Z	this_filer.r.r/�test_isfile_strictks&�D�D�.z#TestCommonModule.test_isfile_strictc	Cs�trddlm}nddlm}tj�tjdd��Lt|���"}t	d�t
j��Wd�n1sd0YWd�n1s�0Y|�
�}|�d�s�J|��d|vs�J�t�dd�|vs�J�tj�tjdd��Ht|���}t	td	��Wd�n1�s0YWd�n1�s(0Y|�
�}d
|v�sHJ�d|v�sVJ�tj�tjdd��Tt|���(}tdd
�}d|_t	|�Wd�n1�s�0YWd�n1�s�0Y|�
�}d
|v�s�J�d|v�s�J�dS)Nr)�StringIOZPSUTIL_DEBUGTZhellozpsutil-debugz.pyc�.pyzthis is an errorzignoring ValueErrorz'this is an error'r%zno such filez/foo)r�ior�rr8r9r)�_commonrr�sys�stderr�flush�getvaluerpr�r5r�r��filename)r-r�r�rI�excr.r.r/�
test_debug�s2FL
HzTestCommonModule.test_debugcCs�|��}t|d��}|�d�Wd�n1s20Yt|�dksLJ�t|�dks\J�t�t��t|d�Wd�n1s�0Yt�t��t|d�Wd�n1s�0Yt|ddd�dks�J�t|ddd�dks�J�dS)N�wrOsfooz-invalidr�)�fallback)Z
get_testfn�open�writerrr r'r)r-Ztestfnr�r.r.r/�
test_cat_bcat�s(**zTestCommonModule.test_cat_bcatN)	rdrerfr�r�r�r�r�r�r.r.r.r/r�s'!r�rOza b cc@s�eZdZdd�ZeZdd�Zdd�Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zejjedd�dd��ZdS) �TestWrapNumberscCst��dSr�)rr�r,r.r.r/r��szTestWrapNumbers.setUpcCs&dtddd�i}t|d�|ks"J�dS�N�disk1rV�disk_io��ntr�r-�inputr.r.r/�test_first_call�szTestWrapNumbers.test_first_callcCs8dtddd�i}t|d�|ks"J�t|d�|ks4J�dSr�r�r�r.r.r/�test_input_hasnt_changed�sz(TestWrapNumbers.test_input_hasnt_changedcCs�dtddd�i}t|d�|ks"J�dtddd�i}t|d�|ksDJ�dtddd�i}t|d�|ksfJ�dtddd�i}t|d�|ks�J�dS)	Nr�rVr��
����r�r�r.r.r/�test_increase_but_no_wrap�sz)TestWrapNumbers.test_increase_but_no_wrapcCs�dtddd�i}t|d�|ks"J�dtddd�i}t|d�dtddd�iksPJ�dtddd�i}t|d�dtddd�iks~J�dtddd�i}t|d�dtddd�iks�J�dtddd�i}t|d�dtddd	�iks�J�dtddd�i}t|d�dtddd	�ik�s
J�dtd
dd�i}t|d�dtddd	�ik�s:J�dtddd�i}t|d�dtddd	�ik�sjJ�dtddd�i}t|d�dtddd	�ik�s�J�dS)
Nr��dr�r�n�Z�r���2��(r�r�r.r.r/�	test_wrap�s$   zTestWrapNumbers.test_wrapcCstdtddd�i}t|d�|ks"J�tddd�tddd�d�}t|d�|ksNJ�dtddd�i}t|d�|kspJ�dS)Nr�rVr���r�Zdisk2�r�r�r.r.r/�test_changing_keys�sz"TestWrapNumbers.test_changing_keyscCs0tddd�tddd�d�}t|d�|ks,J�tddd�tddd�d�}t|d�tddd�tddd�d�ksnJ�dtddd�i}t|d�|ks�J�tddd�tddd�d�}t|d�|ks�J�tddd�tddd�d�}t|d�|ks�J�tddd�tddd�d�}t|d�tddd�tddd�d�k�s,J�dS)Nrr	rr�rr
r�r�r�r.r.r/�test_changing_keys_w_wrap�s$

�

�z)TestWrapNumbers.test_changing_keys_w_wrapcCsbddddd�}t|d�|ks J�t|d�|ks2J�ddddd�}t|d�}|dd	d
ks^J�dS)N)	i,���#�R������ȷ)	i�r%itUiirrrr)	�6ri�$i�Nr��ri��)	iU	i�i"ri�i4i�i�i\)�nvme0n1Z	nvme0n1p1Z	nvme0n1p2Z	nvme0n1p3r�)	r	rrrrrrrrr"ri�r
)r-�d�outr.r.r/�test_real_datas��
zTestWrapNumbers.test_real_datacCsbdtddd�i}t|d�t��}|dd|iks6J�|ddiiksJJ�|ddiiks^J�dS)Nr�rVr�rr_r%�r�r�
cache_info�r-r�cacher.r.r/�test_cache_first_call(s
z%TestWrapNumbers.test_cache_first_callcCs�dtddd�i}t|d�dtddd�i}t|d�t��}|dd|iksPJ�|dddddd�ikslJ�|ddiiks�J�dS)	Nr�rVr�rrr_�)r�r)r�r_�r�r%r%r&r(r.r.r/�test_cache_call_twice0s

�
z%TestWrapNumbers.test_cache_call_twicecCs�dtddd�i}t|d�dtddd�i}t|d�t��}|dd|iksPJ�|dddddd�ikslJ�|dddtd	g�iiks�J�d
d�}dtddd�i}t|d�t��}|dd|iks�J�|�dtddd�i}t|d�t��}|dd|ik�sJ�|�dtddd
�i}t|d�t��}|dd|ik�sDJ�|dddddd�ik�sbJ�|dddtd	g�iik�s�J�dS)Nr�r	r�rrr_r+r%r,cSsFt��}|dddddd�iks$J�|dddtdg�iiksBJ�dS)	Nr_r�rr	r+r%r�r,)rr'r`)r)r.r.r/�check_cache_infoKs��
z9TestWrapNumbers.test_cache_wrap.<locals>.check_cache_inforrr)r�rr'r`)r-rr)r.r.r.r/�test_cache_wrap<s:

�



�zTestWrapNumbers.test_cache_wrapcCs�dtddd�i}t|d�tddd�tddd�d�}t|d�t��}|dd|iksZJ�|dddddd�iksvJ�|d	diiks�J�dS)
Nr�rVr�rrrr_r+r%r&r(r.r.r/�test_cache_changing_keysns

�
z(TestWrapNumbers.test_cache_changing_keyscCs\dtddd�i}t|d�t|d�t�d�t��iiifksDJ�t�d�t�d�dS)Nr�rVr�z?!?)r�rr�r'r�r.r.r/�test_cache_clearzs



z TestWrapNumbers.test_cache_clear�
not supported��reasoncCs�t��rt��st�d��t��t��t��}|D]}d|vsFJ�d|vs6J�q6tj��t��}|D]}d|vszJ�d|vsjJ�qjtj��t��}|iiifks�J�dS)Nzno disks or NICs availablezpsutil.disk_io_counterszpsutil.net_io_counters)r)Zdisk_io_countersZnet_io_countersr �skiprr'r�)r-�cachesr)r.r.r/�test_cache_clear_public_apis�s 


z,TestWrapNumbers.test_cache_clear_public_apisN)rdrerfr�r�rrrrrrr%r*r-r/r0r1r �mark�skipifrr7r.r.r.r/r��s 
2	r�zcan't locate scripts directoryr3c@s�eZdZdZedd��Zedd��Zdd�Zej	j
edd	�d
d��Zdd
�Z
dd�Zdd�Zdd�Zej	j
eoxe��dd	�dd��Zdd�Zdd�Zdd�Zej	j
edd	�dd��Zej	j
ed d	�d!d"��Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Z d-d.�Z!ej	j
e"d/d	�d0d1��Z#d2d3�Z$ej	j
e%d d	�d4d5��Z&ej	j
e'd d	�d6d7��Z(ej	j
e)d d	�ej	j
e*d8d	�d9d:���Z+ej	j
e)d d	�ej	j
e*d8d	�d;d<���Z,d=S)>�TestScriptsz-Tests for scripts in the "scripts" directory.c
Os�|�dt�dtj�t|�}t|g}|D]}|�|�q*zt|fi|���	�}WnFt
y�}z.dt|�vr�t|�WYd}~S�WYd}~n
d}~00|s�J|��|S)N�envz%sr=)�
setdefaultrr;r�rrrr�r"�strip�RuntimeErrorr4)�exer�r��cmd�argr$�errr.r.r/�
assert_stdout�szTestScripts.assert_stdoutcCs\tj�t|�}trt|dd�nt|��}|��}Wd�n1sD0Yt�|�dS)N�utf8)�encoding)	r;r�rrrr��read�ast�parse)r?r��srcr.r.r/�
assert_syntax�s&zTestScripts.assert_syntaxcCsVt|�}t�t�D]>}|�d�rdtj�|�d|vr|�dtj�t|���qdS)Nr�Ztest_rzno test defined for %r script)	ror;�listdirr�endswithr��splitextrwr)r-Zmethsr1r.r.r/�
test_coverage�s
��zTestScripts.test_coveragez
POSIX onlyr3cCs`t�t�D]P\}}}|D]@}|�d�rtj�||�}tjt�|�tj@s|�	d|��qq
dS)Nr�z%r is not executable)
r;�walkrrLr�r�stat�S_IXUSR�ST_MODErw)r-�root�dirs�files�filer�r.r.r/�test_executable�s
zTestScripts.test_executablecCs|�d�dS)Nz
disk_usage.py�rCr,r.r.r/�test_disk_usage�szTestScripts.test_disk_usagecCs|�d�dS)Nzfree.pyrXr,r.r.r/�	test_free�szTestScripts.test_freecCs|�d�dS)Nz
meminfo.pyrXr,r.r.r/�test_meminfo�szTestScripts.test_meminfocCs|�dtt����dS)Nzprocinfo.py�rCr4r;r<r,r.r.r/�
test_procinfo�szTestScripts.test_procinfozno userscCs|�d�dS)Nzwho.pyrXr,r.r.r/�test_who�szTestScripts.test_whocCs|�d�dS)Nzps.pyrXr,r.r.r/�test_ps�szTestScripts.test_pscCs|�d�dS)Nz	pstree.pyrXr,r.r.r/�test_pstree�szTestScripts.test_pstreecCs|�d�dS)Nz
netstat.pyrXr,r.r.r/�test_netstat�szTestScripts.test_netstatzQEMU user not supportedcCs|�d�dS)Nzifconfig.pyrXr,r.r.r/�
test_ifconfig�szTestScripts.test_ifconfigr2cCs|�dtt����dS)Nzpmap.pyr\r,r.r.r/�	test_pmap�szTestScripts.test_pmapcCs*dt����jvrt�d��|�d�dS)NZussr2zprocsmem.py)r)r+Zmemory_full_info�_fieldsr r5rCr,r.r.r/�
test_procsmem�s
zTestScripts.test_procsmemcCs|�d�dS)Nz
killall.py�rJr,r.r.r/�test_killall�szTestScripts.test_killallcCs|�d�dS)Nz	nettop.pyrfr,r.r.r/�test_nettop�szTestScripts.test_nettopcCs|�d�dS)Nztop.pyrfr,r.r.r/�test_top�szTestScripts.test_topcCs|�d�dS)Nziotop.pyrfr,r.r.r/�
test_iotopszTestScripts.test_iotopcCs,|�dt�����}tt���|vs(J�dS)Nzpidof.py)rCr)r+r1r4r;r<)r-�outputr.r.r/�
test_pidofszTestScripts.test_pidofzWINDOWS onlycCs|�d�dS)Nzwinservices.pyrXr,r.r.r/�test_winservicesszTestScripts.test_winservicescCs|�d�dS)Nzcpu_distribution.pyrfr,r.r.r/�test_cpu_distributionsz!TestScripts.test_cpu_distributioncCs t��st�d��|�d�dS)Nzno temperaturesztemperatures.py)r)Zsensors_temperaturesr r5rCr,r.r.r/�test_temperaturess
zTestScripts.test_temperaturescCs t��st�d��|�d�dS)Nzno fanszfans.py)r)Zsensors_fansr r5rCr,r.r.r/�	test_fanss
zTestScripts.test_fansz
no batterycCs|�d�dS)Nz
battery.pyrXr,r.r.r/�test_batteryszTestScripts.test_batterycCs|�d�dS)Nz
sensors.pyrXr,r.r.r/�test_sensorsszTestScripts.test_sensorsN)-rdrerfrur�rCrJrNr r8r9rrWrYrZr[r]rr)Zusersr^r_r`rarrbrrcrergrhrirjrlrrmrnrrorrprrrqrrr.r.r.r/r:�sP








r:):rurG�collectionsr�r�r;r�r�rPr�r)Zpsutil.testsrrZpsutil._commonrrrrrr	rrrZpsutil._compatrrrrrrrrrrrrrrrrrr r!r"r#r$rgr�r��
namedtupler�r�r8r9r��existsr:r.r.r.r/�<module>st8!h�PKok\�6�r�r3psutil/tests/__pycache__/test_system.cpython-39.pycnu�[���a

��?hO��@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlm
Z
ddlmZddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*ddlm+Z+dd lm,Z,dd!lm-Z-dd"lm.Z.dd#lm/Z/dd$lm0Z0dd%lm1Z1dd&lm2Z2Gd'd(�d(e-�Z3Gd)d*�d*e-�Z4Gd+d,�d,e-�Z5Gd-d.�d.e-�Z6Gd/d0�d0e-�Z7Gd1d2�d2e-�Z8Gd3d4�d4e-�Z9Gd5d6�d6e-�Z:dS)7zTests for system APIS.�N)�AIX)�BSD)�FREEBSD)�LINUX)�MACOS)�NETBSD)�OPENBSD)�POSIX)�SUNOS)�WINDOWS)�PY3)�FileNotFoundError)�long)�ASCII_FS)�
CI_TESTING)�DEVNULL)�GITHUB_ACTIONS)�GLOBAL_TIMEOUT)�HAS_BATTERY)�HAS_CPU_FREQ)�HAS_GETLOADAVG)�HAS_NET_IO_COUNTERS)�HAS_SENSORS_BATTERY)�HAS_SENSORS_FANS)�HAS_SENSORS_TEMPERATURES)�IS_64BIT)�MACOS_12PLUS)�PYPY)�	QEMU_USER)�UNICODE_SUFFIX)�PsutilTestCase)�check_net_address)�enum)�mock)�pytest)�retry_on_failurec@s<eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
S)�TestProcessItercCs~t��dd�t��D�vsJ�|��}|jdd�t��D�vsBJ�t�|j�}|��|��|jdd�t��D�vszJ�dS)NcSsg|]
}|j�qS���pid��.0�xr'r'�D/usr/local/lib64/python3.9/site-packages/psutil/tests/test_system.py�
<listcomp>C�z5TestProcessIter.test_pid_presence.<locals>.<listcomp>cSsg|]
}|j�qSr'r(r*r'r'r-r.Er/cSsg|]
}|j�qSr'r(r*r'r'r-r.Ir/)	�os�getpid�psutil�process_iter�spawn_testprocr)�Process�kill�wait��selfZsproc�pr'r'r-�test_pid_presenceBsz!TestProcessIter.test_pid_presencecCs>dd�t��D�}t|dd�d�tt|�dd�d�ks:J�dS)NcSsg|]}|�qSr'r'r*r'r'r-r.Lr/z6TestProcessIter.test_no_duplicates.<locals>.<listcomp>cSs|jS�Nr(�r,r'r'r-�<lambda>Mr/z4TestProcessIter.test_no_duplicates.<locals>.<lambda>)�keycSs|jSr<r(r=r'r'r-r>Nr/)r2r3�sorted�set)r9�lsr'r'r-�test_no_duplicatesKs�z"TestProcessIter.test_no_duplicatesc	Csztt���td�D]`}tjdt�t���d��*ttjdgd��gksLJ�Wd�n1s`0Ytj�	�qdS�N�zpsutil.Process.as_dict�Zside_effect�	cpu_times��attrs)
�listr2r3�ranger#�patchZ
NoSuchProcessr0r1�cache_clear�r9r,r'r'r-�test_emulate_nspQs�8z TestProcessIter.test_emulate_nspc
Cs�tt���td�D]�}tjdt�t���d��Nt	�
tj��"ttjdgd��Wd�n1sf0YWd�n1s�0Ytj��qdSrD)rJr2r3rKr#rL�AccessDeniedr0r1r$�raisesrMrNr'r'r-�test_emulate_access_denied[s�Nz*TestProcessIter.test_emulate_access_deniedcCs�tjdgd�D]}t|j���dgksJ�qtjdgd�D]}t|j���dgks:J�q:t�t��"ttjdgd��Wd�n1s�0Ytj	dt�
dd�d��T}tjddgd�D](}|jddus�J�|jddks�J�q�|js�J�Wd�n1�s0Ytj	dt�
dd�d��d}t�}tjddg|d	�D].}|jd|u�sXJ�|jddk�s@J��q@|j�s|J�Wd�n1�s�0YdS)
Nr)rHZfooz$psutil._psplatform.Process.cpu_timesr�rFrG)rIZad_value)
r2r3rJ�info�keysr$rQ�
ValueErrorr#rLrP�called�object)r9r:�m�flagr'r'r-�
test_attrsfs60
�*
��
zTestProcessIter.test_attrscCs.tt���tjsJ�tj��tjr*J�dSr<)rJr2r3Z_pmaprM�r9r'r'r-�test_cache_clear�s

z TestProcessIter.test_cache_clearN)	�__name__�
__module__�__qualname__r;rCrOrRr[r]r'r'r'r-r&As	
r&c@sTeZdZejjeoedd�dd��Zejjeo0edd�dd��Z	dd�Z
d	d
�ZdS)�TestProcessAPIsz-spawn_testproc() unreliable on PYPY + WINDOWS��reasoncs4�fdd�}g�|��}|��}|��}dd�|||fD�}t�t��tj|dd�Wd�n1sj0Yt�t��tj|dd�Wd�n1s�0Yt��}tj|d	|d
�\}}t��|dks�J�|gks�J�t|�dks�J��gk�sJ�|D]}	t	|	d
��r
J��q
t
d�dd��}
|��|
||�\}}|jdd�|D�v�sbJ�t
�r�|��jtjk�s�J�n|��jdk�s�J��|jgk�s�J�|D]}	t	|	d
��r�J��q�t
d�dd��}|��|��|||�\}}t��t|j|j|jg�k�sJ�|D]}	t	|	d
��sJ��qdS)Ncs��|j�dSr<)�appendr))r:��pidsr'r-�callback�sz1TestProcessAPIs.test_wait_procs.<locals>.callbackcSsg|]}t�|j��qSr'�r2r5r)r*r'r'r-r.�r/z3TestProcessAPIs.test_wait_procs.<locals>.<listcomp>���)�timeout�)rgg{�G�z�?�rjrgg�?��
returncode�cSs<tj|d|d�\}}t|�dks$J�t|�dks4J�||fS)N���Q��?rlrkrE�r2�
wait_procs�len��procsrg�gone�aliver'r'r-�test_1�s�
z/TestProcessAPIs.test_wait_procs.<locals>.test_1cSsg|]
}|j�qSr'r(r*r'r'r-r.�r/cSs<tj|d|d�\}}t|�dks$J�t|�dks4J�||fS)Nrprlrmrrqrtr'r'r-�test_2�s�
z/TestProcessAPIs.test_wait_procs.<locals>.test_2)r4r$rQrVr2rr�	TypeError�timers�hasattrr%�	terminater)r	�poprn�signal�SIGTERMrA)r9rg�sproc1�sproc2�sproc3ru�trvrwr:rxryr'rer-�test_wait_procs�sJ,,

"zTestProcessAPIs.test_wait_procscCsL|��}|��}|��}dd�|||fD�}|D]}|��q0t�|�dS)NcSsg|]}t�|j��qSr'rhr*r'r'r-r.�r/z>TestProcessAPIs.test_wait_procs_no_timeout.<locals>.<listcomp>)r4r}r2rr)r9r�r�r�rur:r'r'r-�test_wait_procs_no_timeout�s
z*TestProcessAPIs.test_wait_procs_no_timeoutcCsp|��}t�|j�sJ�t�|j�}|��|��t�|j�rDJ�t�d�rRJ�t�d�dt��vkslJ�dS)Nrir)r4r2�
pid_existsr)r5r6r7rfr8r'r'r-�test_pid_exists�szTestProcessAPIs.test_pid_existsc	Cs�t��}|D]D}zt�|�s J�WqtyNt�d�|t��vsJJ�Yq0qtt|�dt|�d�}|D]}t�|�rpJ�qpdS)Ng�������?i�:i�>)r2rfr��AssertionErrorr{�sleeprK�max)r9rfr)r'r'r-�test_pid_exists_2�s
z!TestProcessAPIs.test_pid_exists_2N)r^r_r`r$�mark�skipifrrr�r�r�r�r'r'r'r-ra�s�
;�
	
rac@sFeZdZdd�Zejjeo"e�	�dd�dd��Z
dd�Zd	d
�ZdS)�TestMiscAPIscCs6t��}t|t�sJ�|dks"J�|t��ks2J�dS�Nr)r2Z	boot_time�
isinstance�floatr{)r9Zbtr'r'r-�test_boot_time�szTestMiscAPIs.test_boot_time�unreliable on CIrbc	Cs�t��}|gksJ�|D]�}|j|d���|js4J�t|jt�sDJ�t|jttd�f�s\J�|jdur~t|jttd�f�s~J�|j|j|j	dks�J�t
j
�|j	�ts�t
r�|jdus�J�nt�|j�Wd�q1s�0YqdS)N)�user�)r2�users�subTest�namer��strZterminal�type�host�started�datetime�
fromtimestamprrr)r5)r9r�r�r'r'r-�
test_users�s 

zTestMiscAPIs.test_userscCs,tj}tt_zt��W|t_n|t_0dSr<)�sys�stdoutrr2�test)r9r�r'r'r-�	test_tests

zTestMiscAPIs.test_testcCs|gd�}|D]}ttt|�t�sJ|��qtjdk�r6tjs@J�tjrJJ�|�d�dt	j
��vrxtjslJ�|�d�n�dt	j
��vr�tj
s�J�tjtjtjg�d�dks�J�|�d	�|�d
�|�d�|�d�n\d
t	j
��vs�dt	j
��v�rtj�sJ�|�d�n&dt	j
��v�rXtj�s*J�|�d�n"tj�sBJ�tj�rNJ�|�d�|D]}tt|��r\J|���q\dS)N)	r	rrrrrrrr
�posixr	�linuxrZbsdTrkrrrr�sunos�solarisr
�darwinrr)r��getattrr2�boolr0r�r	r�remover��platform�lowerrrrrr�countr
r)r9�namesr�r'r'r-�test_os_constantssF




��


��
zTestMiscAPIs.test_os_constantsN)
r^r_r`r�r$r�r�rr2r�r�r�r�r'r'r'r-r��s�
	r�c@seZdZdd�Zdd�ZdS)�TestMemoryAPIscCs�t��}|jdksJ|��|jdks,J|��d|jkrBdksLnJ|��|jdks^J|��|jdkspJ|��|jD]l}t||�}|dkr�t	|t
tf�s�J�|dkrv|dks�|�d||f��||jkrv|�d||j||f��qvdS)Nr�d�percent�totalz%r < 0 (%s)z%r > total (total=%s, %s=%s))
r2Zvirtual_memoryr��	availabler��used�free�_fieldsr�r��intr�fail)r9�memr��valuer'r'r-�test_virtual_memoryHs& 


��z"TestMemoryAPIs.test_virtual_memorycCs�t��}|jdksJ�|jdks(J|��|jdks:J|��|jdkrX|jdksjJ|��n|jdksjJ|��d|jkr�dks�nJ|��|jdks�J|��|jdks�J|��dS)N)r�r�r�r��sin�soutrr�)	r2Zswap_memoryr�r�r�r�r�r�r�)r9r�r'r'r-�test_swap_memory\s	
 zTestMemoryAPIs.test_swap_memoryN)r^r_r`r�r�r'r'r'r-r�Gsr�c@s�eZdZdd�Zdd�Zdd�Zdd�Zd	d
�Zdd�Zd
d�Z	e
jje
oLedd�dd��Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Ze
jjeo�e��d!kd"d�e
jjed#d�d$d%���Ze
jjed#d�d&d'��Zd(S))�TestCpuAPIscCs�t��}|dusJ�|ttjdd��ks,J�|dks8J�tj�d�r�td��}|��}Wd�n1sj0Yd|vr�t	�
d��dS)NT��percpurkz
/proc/cpuinfozphysical idz#cpuinfo doesn't include physical id)r2�	cpu_countrsrGr0�path�exists�open�readr$�skip)r9�logical�fdZcpuinfo_datar'r'r-�test_cpu_count_logicalts
&z"TestCpuAPIs.test_cpu_count_logicalcCsht��}tjdd�}|dur&t�d��trLt��dd�dkrL|dusdJ�n|dksXJ�||ksdJ�dS)NF�r�zcpu_count_cores() is NonerE)�rkrk)r2r�r$r�rr��getwindowsversion)r9r�Zcoresr'r'r-�test_cpu_count_cores�s
z TestCpuAPIs.test_cpu_count_coresc	Cs�dD]�}tjd|d��*}t��dus(J�|js2J�Wd�n1sF0Ytjd|d��.}tjdd�dustJ�|js~J�Wd�q1s�0YqdS)N)rirNz$psutil._psplatform.cpu_count_logical�Zreturn_valuez"psutil._psplatform.cpu_count_coresFr�)r#rLr2r�rW)r9�valrYr'r'r-�test_cpu_count_none�s�(�zTestCpuAPIs.test_cpu_count_nonecCsjd}t��}t|�|D]&}t|t�s*J�|dks6J�||7}qtt|t|��d�dks^J�t|�dS)Nrr�r�)r2rG�sumr�r��round�absr�)r9r��times�cp_timer'r'r-�test_cpu_times�s
zTestCpuAPIs.test_cpu_timescCsLtt���}t��t}t��|kr>tt���}||krdSq|�d��dS)Nztime remained the same)r�r2rGr{rr�)r9�t1Zstop_at�t2r'r'r-�test_cpu_times_time_increases�sz)TestCpuAPIs.test_cpu_times_time_increasescCs�tjdd�D]b}d}t|�|D]&}t|t�s2J�|dks>J�||7}q tt|t|��d�dksfJ�t|�qttjdd�d�ttjdd��ks�J�dS)NTr�rr�r�F)	r2rGr�r�r�r�r�r�rs)r9r�r�r�r'r'r-�test_per_cpu_times�s


�zTestCpuAPIs.test_per_cpu_timescCs�tjdd�}t��t}t��|kr.|�d�Stjdd�}t||�D]4\}}t�|�t�|�}}||}|dkrDdSqDqdS)NTr�rjg�������?)r2rGr{rr��zipZ_cpu_busy_time)r9Ztot1Z	giveup_atZtot2r�r��
differencer'r'r-�test_per_cpu_times_2�s
z TestCpuAPIs.test_per_cpu_times_2zunreliable on OPENBSD + CIrbc	Cs�t��}tjdd�}|�dd�t|�D��}|jD]T}|j|||d��0tt||�t||��dkshJ�Wd�q21s|0Yq2dS)NTr�cSsg|]}t|��qSr')r�)r+�numr'r'r-r.�r/z9TestCpuAPIs.test_cpu_times_comparison.<locals>.<listcomp>)�field�base�per_cpurk)r2rG�_maker�r�r�r�r�)r9r�r�Z
summed_valuesr�r'r'r-�test_cpu_times_comparison�s
��z%TestCpuAPIs.test_cpu_times_comparisonc
Cs�z>t|t�sJ�|dksJ�|dus(J�|dt��ks<J�WnBty�}z*td|t�|�t�|�f��WYd}~n
d}~00dS)Nr�g�gY@z
%s
last=%s
new=%s)r�r�r2r�r��pprint�pformat)r9r�Zlast_retZnew_ret�errr'r'r-�_test_cpu_percents��zTestCpuAPIs._test_cpu_percentcCsrtjdd�}td�D]"}tjdd�}|�|||�|}qt�t��tjdd�Wd�n1sd0YdS�N���MbP?)�intervalr�ri)r2�cpu_percentrKr�r$rQrV)r9�last�_�newr'r'r-�test_cpu_percentszTestCpuAPIs.test_cpu_percentcCs�tjddd�}t|�t��ks"J�td�D].}tjddd�}|D]}|�|||�q@|}q*t�t��tjddd�Wd�n1s�0YdS)Nr�T�r�r�r�ri)	r2r�rsr�rKr�r$rQrV�r9r�r�r�r�r'r'r-�test_per_cpu_percentsz TestCpuAPIs.test_per_cpu_percentcCs�tjdd�}td�D]>}tjdd�}|D]}|�|||�q(|�t|�||�|}qt�t��tjdd�Wd�n1s�0YdSr�)r2�cpu_times_percentrKr�r�r$rQrVr�r'r'r-�test_cpu_times_percent"sz"TestCpuAPIs.test_cpu_times_percentcCsztjddd�}t|�t��ks"J�td�D]J}tjddd�}|D].}|D]}|�|||�qH|�t|�||�q@|}q*dS)Nr�Tr�r�)r2r�rsr�rKr�r�)r9r�r�r��cpur�r'r'r-�test_per_cpu_times_percent-sz&TestCpuAPIs.test_per_cpu_times_percentcCs~tjdd�dd�tjdd�D�}tjd|d��:tjdd�D]}|D]}|�|dd�qFq>Wd�n1sp0YdS)NTr�cSs*g|]"}|�dd�tt|j��D���qS)cSsg|]}d�qS)rr'r*r'r'r-r.<r/zNTestCpuAPIs.test_per_cpu_times_percent_negative.<locals>.<listcomp>.<listcomp>)r�rKrsr�r*r'r'r-r.;s�zCTestCpuAPIs.test_per_cpu_times_percent_negative.<locals>.<listcomp>zpsutil.cpu_timesr�)r2r�rGr#rLr�)r9Z
zero_timesr�r�r'r'r-�#test_per_cpu_times_percent_negative8s
�z/TestCpuAPIs.test_per_cpu_times_percent_negativecCsTt��}|jdksJ�|jD]2}t||�}|dks6J�ts|dvr|dksJ�qdS)N)�ctx_switches�
interruptsZsoft_interruptsZsyscallsr)r�r�)r2Z	cpu_statsr�r�r)r9�infosr�r�r'r'r-�test_cpu_statsDs

zTestCpuAPIs.test_cpu_stats�arm64zskipped due to #1892�
not supportedcCs`dd�}tjdd�}tr&|s&t�d��|s2J|��|tjdd�g�tr\t|�t��ks\J�dS)NcSsl|D]b}|jdksJ�|jdkr0|j|jks0J�|jD].}t||�}t|tttf�sXJ�|dks6J�q6qdS)N)�current�minr�r�r)r�r�rr�r�r�rr�)rB�ntr�r�r'r'r-�check_lsZs


z+TestCpuAPIs.test_cpu_freq.<locals>.check_lsTr�zreturns empty list on FreeBSDF)r2Zcpu_freqrr$r�rrsr�)r9rrBr'r'r-�
test_cpu_freqUs

zTestCpuAPIs.test_cpu_freqcCs@t��}t|�dksJ�|D]}t|t�s.J�|dksJ�qdS)Nrmr�)r2�
getloadavgrsr�r�)r9Zloadavg�loadr'r'r-�test_getloadavgns
zTestCpuAPIs.test_getloadavgN)r^r_r`r�r�r�r�r�r�r�r$r�r�rrr�r�r�r�r�r�r�r�rr��machinerrrr	r'r'r'r-r�ss2
"�
	�r�c@s�eZdZejjeoedd�dd��Zejje	dd�dd��Z
dd	�Zd
d�Zejje
ofej�d�d
d�ejjeo~e��dd�dd���Zdd�ZdS)�TestDiskAPIszunreliable on PYPY32 + 32BITrbcCs>t�t���}|jdksJ�|jdks.J|��|jdks@J|��|jdksRJ|��|j|jksfJ|��|j|jkszJ|��d|jkr�dks�nJ|j��t	t
d�r�t
�t���}d}|j|jks�J�t|j|j�|ks�J�ts�t|j|j�|ks�J�|�
�}t�t��t�|�Wd�n1�s00YdS)N)r�r�r�r�rr��
disk_usageiP)r2rr0�getcwdr�r�r�r�r�r|�shutilr�rZ
get_testfnr$rQr
)r9�usageZshutil_usageZ	tolerance�fnamer'r'r-�test_disk_usagexs$"
zTestDiskAPIs.test_disk_usageznot an ASCII fscCs8t�t��t�t�Wd�n1s*0YdSr<)r$rQ�UnicodeEncodeErrorr2rrr\r'r'r-�test_disk_usage_unicode�sz$TestDiskAPIs.test_disk_usage_unicodecCst�d�dS)N�.)r2rr\r'r'r-�test_disk_usage_bytes�sz"TestDiskAPIs.test_disk_usage_bytescCs~dd�}tjdd�}|sJ�|D]b}||�tr<d|jvr<q tsXtj�|j�s^J|��n|jtj�|j	�stJ|��|j
s J|��q tjdd�}|s�J�tjdd�D]�}||�ts�|j	r�zt�|j	�Wnbt�y,}zHt
�rt�r|jtjk�rWYd}~q�|jtjtjfv�r�WYd}~q�d}~00tj�|j	�s�J|��q�dd�}|t�}d	d
�tjdd�D�}||v�szJ�dS)NcSsDt|jt�sJ�t|jt�s J�t|jt�s0J�t|jt�s@J�dSr<)r��devicer��
mountpoint�fstype�opts�rr'r'r-�check_ntuple�sz7TestDiskAPIs.test_disk_partitions.<locals>.check_ntupleF)�allZcdromTcSs.tj�|�}tj�|�s&tj�|�}q|��Sr<)r0r��abspath�ismount�dirnamer�)r�r'r'r-�find_mount_point�sz;TestDiskAPIs.test_disk_partitions.<locals>.find_mount_pointcSsg|]}|jr|j���qSr')rr�r*r'r'r-r.�s�z5TestDiskAPIs.test_disk_partitions.<locals>.<listcomp>)r2Zdisk_partitionsrrr	r0r�r�rrr�stat�OSErrorrr�errno�EIO�EPERM�EACCES�__file__)r9rrBZdiskr�r �mountZmountsr'r'r-�test_disk_partitions�s>

�z!TestDiskAPIs.test_disk_partitionsz/proc/diskstatsz3/proc/diskstats not available on this linux versionr�cCsvdd�}tjdd�}|dus$Jd��||�tjdd�}t|�tt|��ksPJ�|D]}|sdJ|��|||�qTdS)NcSs�|d|jksJ�|d|jks$J�|d|jks6J�|d|jksHJ�ts�ts�|d|jksbJ�|d|jkstJ�tr�|d|j	ks�J�|d|j
ks�J�|d	|jks�J�ntr�|d|jks�J�|j
D]}t||�dks�J|��q�dS)
NrrkrErm��r���)Z
read_countZwrite_count�
read_bytes�write_bytesrrZ	read_timeZ
write_timerZread_merged_countZwrite_merged_countZ	busy_timerr�r�)rr�r'r'r-r�s
z8TestDiskAPIs.test_disk_io_counters.<locals>.check_ntupleF�Zperdiskzno disks on this system?T)r2�disk_io_countersrsrA�r9r�retr?r'r'r-�test_disk_io_counters�sz"TestDiskAPIs.test_disk_io_counterscCsdtjdid��B}tjdd�dus$J�tjdd�iks8J�|jsBJ�Wd�n1sV0YdS)Nz#psutil._psplatform.disk_io_countersr�Fr0T)r#rLr2r1rW�r9rYr'r'r-�test_disk_io_counters_no_disks�s�z+TestDiskAPIs.test_disk_io_counters_no_disksN)r^r_r`r$r�r�rrrrrrr)rr0r�r�rr2r1r4r6r'r'r'r-rws"
�

:��rc@s�eZdZejjedd�dd��Zejjedd�dd��Zejje	dd�dd	��Z
d
d�Zejje	dd�dd
��Zejje
p�ep�edd�dd��ZdS)�TestNetAPIsrrbcCsddd�}tjdd�}||�tjdd�}|gks4J�|D]&}|sDJ�t|t�sRJ�|||�q8dS)NcSs(|d|jksJ�|d|jks$J�|d|jks6J�|d|jksHJ�|d|jksZJ�|d|jkslJ�|d|jks~J�|d|jks�J�|jdks�J|��|jdks�J|��|jdks�J|��|jdks�J|��|jdks�J|��|jdks�J|��|jdk�sJ|��|jdk�s$J|��dS)	NrrkrErmr*r+r�r,)Z
bytes_sentZ
bytes_recvZpackets_sentZpackets_recvZerrinZerroutZdropinZdropoutrr'r'r-r	s z6TestNetAPIs.test_net_io_counters.<locals>.check_ntupleF�ZpernicT)r2�net_io_countersr�r�r2r'r'r-�test_net_io_counterssz TestNetAPIs.test_net_io_counterscCsdtjdid��B}tjdd�dus$J�tjdd�iks8J�|jsBJ�Wd�n1sV0YdS)Nz"psutil._psplatform.net_io_countersr�Fr8T)r#rLr2r9rWr5r'r'r-�test_net_io_counters_no_nics$s�z(TestNetAPIs.test_net_io_counters_no_nicszQEMU user not supportedc
Cs�t��}|sJ|��t��}ttjtjtjg�}|��D�]\}}t	|t
�sPJ�tt|��t|�kshJ�|D�]�}t	|jt
�s�J�t	|jt
�s�J�t	|jt
td�f�s�J�t	|jt
td�f�s�J�|j|vs�J�tr�ts�t	|jtj�s�J�||j�r�|jtjk�rNt�|j�}t�|�� |�|jdf�Wd�n1�sB0Yn�|jtjk�r�t�|jdtjtjdtj�d}|\}	}
}}}
t�|	|
|�}t�|��|�|
�Wd�n1�s�0Y|j|j|j|jfD]*}|du�r�|jtjk�r�t||j��q�|j�r(|jdu�s<J�ql|jrl|jduslJ�qlq8t�sRt �sRt!�rrt"td��r�tjtjk�s�J�n0t#�r�tjtj$k�s�J�nt%�r�tjdk�s�J�dS)Nr�AF_LINKri)&r2�net_if_addrs�net_if_statsrA�socket�AF_INET�AF_INET6r<�itemsr�r�rs�familyr��address�netmaskr��	broadcastrrr"�IntEnum�isup�
contextlib�closing�bind�getaddrinfo�SOCK_STREAM�
AI_PASSIVEZptpr!rrr
r|r�	AF_PACKETr)r9�nicsZ	nic_statsZfamiliesZnic�addrs�addr�srT�af�socktype�protoZ
_canonname�sa�ipr'r'r-�test_net_if_addrs/sl
2��*�
zTestNetAPIs.test_net_if_addrscCs�trdtjddddfg}ndg}tjd|d��L}t��dd}|jsJJ�tr^|jdkslJ�n|jdkslJ�Wd�n1s�0YdS)	N�em1z06:3d:29)rZriz06-3d-29NNNzpsutil._psplatform.net_if_addrsr�rz06:3d:29:00:00:00z06-3d-29-00-00-00)r	r2r<r#rLr=rWrD)r9r3rYrRr'r'r-� test_net_if_addrs_mac_null_bytesus�
z,TestNetAPIs.test_net_if_addrs_mac_null_bytesc
Cs�t��}|sJ|��tjtjtjf}|��D]p\}}t|t�sBJ�|\}}}}}	t|t�s^J�||vsjJ�||vsvJ�|dks�J�|dks�J�t|	t�s,J�q,dSr�)	r2r>ZNIC_DUPLEX_FULLZNIC_DUPLEX_HALFZNIC_DUPLEX_UNKNOWNrBr�r�r�)
r9rPZall_duplexesr��statsrHZduplex�speedZmtu�flagsr'r'r-�test_net_if_stats�s�zTestNetAPIs.test_net_if_statszLINUX or BSD or MACOS specificcCsXtjdttjd�d��.}t��}|iks,J�|js6J�Wd�n1sJ0YdS)Nzpsutil._psutil_posix.net_if_mturSrF)r#rLr"r#ZENODEVr2r>rW)r9rYr3r'r'r-�test_net_if_stats_enodev�s
�z$TestNetAPIs.test_net_if_stats_enodevN)r^r_r`r$r�r�rr:r;rrYr[r_rrrr`r'r'r'r-r7s



E
�r7c@s�eZdZejjedd�dd��Zejjedd�dd��Zejje	dd�ejje
dd�dd	���Zejjedd�d
d��Z
dS)
�TestSensorsAPIsrrbcCs�t��}|��D]x\}}t|t�s&J�|D]\}t|jt�s>J�|jdurV|jdksVJ�|jdurn|jdksnJ�|jdur*|jdks*J�q*qdSr�)	r2�sensors_temperaturesrBr�r��labelr�high�critical)r9�tempsr��entries�entryr'r'r-�test_sensors_temperatures�s


z)TestSensorsAPIs.test_sensors_temperaturescCs�ddgi}tjd|d��X}tjdd�dd}|js8J�|jdksFJ�|jd	ksTJ�|jd
ksbJ�Wd�n1sv0YdS)NZcoretemp)rcgI@gN@g�Q@z'psutil._psplatform.sensors_temperaturesr�T)Z
fahrenheitrg�^@g�a@g�c@)r#rLr2rbrWrrdre)r9�drYrfr'r'r-�#test_sensors_temperatures_fahreneit�s
�
z3TestSensorsAPIs.test_sensors_temperatures_fahreneitz
no batterycCspt��}|jdksJ�|jdks$J�|jtjtjfvrF|jdks\J�n|jtjkr\|js\J�t|jt�slJ�dS)Nrr�)	r2Zsensors_batteryr�ZsecsleftZPOWER_TIME_UNKNOWNZPOWER_TIME_UNLIMITEDZ
power_pluggedr�r�)r9r3r'r'r-�test_sensors_battery�s�
z$TestSensorsAPIs.test_sensors_batterycCsht��}|��D]R\}}t|t�s&J�|D]6}t|jt�s>J�t|jttf�sRJ�|jdks*J�q*qdSr�)	r2Zsensors_fansrBr�r�rcrr�r)r9Zfansr�rgrhr'r'r-�test_sensors_fans�sz!TestSensorsAPIs.test_sensors_fansN)r^r_r`r$r�r�rrirkrrrlrrmr'r'r'r-ra�s


ra);�__doc__rIr�r#r0r�r�rrr?r�r{r2rrrrrrrr	r
rZpsutil._compatrr
rZpsutil.testsrrrrrrrrrrrrrrrrrr r!r"r#r$r%r&rar�r�r�rr7rar'r'r'r-�<module>sxHfX,#PKok\}��}}2psutil/tests/__pycache__/test_sunos.cpython-39.pycnu�[���a

��?h��@sjdZddlZddlZddlmZddlmZddlmZddlmZejj	edd�Gd	d
�d
e��Z
dS)zSun OS specific tests.�N)�SUNOS)�PsutilTestCase)�pytest)�shz
SUNOS only)�reasonc@seZdZdd�Zdd�ZdS)�SunOSSpecificTestCasec	Cs�tdtjd�}|���d�dd�}|s4td��d}}|D],}|��}t|d�d}t|d	�d}q@||}t��}|j	|ks�J�|j
|ks�J�|j|ks�J�dS)
Nz#env PATH=/usr/sbin:/sbin:%s swap -l�PATH�
�zno swap device(s) configuredr�i�)r�os�environ�strip�split�
ValueError�int�psutilZswap_memory�total�used�free)	�self�out�linesrr�line�fieldsrZpsutil_swap�r�C/usr/local/lib64/python3.9/site-packages/psutil/tests/test_sunos.py�test_swap_memorysz&SunOSSpecificTestCase.test_swap_memorycCs&td�}t��t|�d��ks"J�dS)Nz/usr/sbin/psrinfor	)rr�	cpu_count�lenr)rrrrr�test_cpu_count%sz$SunOSSpecificTestCase.test_cpu_countN)�__name__�
__module__�__qualname__rr!rrrrrsr)�__doc__r
rrZpsutil.testsrrr�markZskipifrrrrr�<module>sPKok\豍BB0psutil/tests/__pycache__/__main__.cpython-39.pycnu�[���a

��?h5�@s"dZddlmZe�gd��dS)z>Run unit tests. This is invoked by:
$ python -m psutil.tests.
�)�pytest)z-vz-sz
--tb=shortN)�__doc__Zpsutil.testsr�main�rr�A/usr/local/lib64/python3.9/site-packages/psutil/tests/__main__.py�<module>sPKok\ށ�,,4psutil/tests/__pycache__/test_unicode.cpython-39.pycnu�[���a

��?h;1�@sdZddlZddlZddlZddlZddlmZddlZddlmZddlm	Z	ddlm
Z
ddlmZddlm
Z
dd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$e�r�dd �Z!d!d"�Z%Gd#d$�d$e�Z&ej'j(d%d&�ej'j)ed'd(�ej'j)e�o�ed)d(�Gd*d+�d+e&����Z*ej'j)ed,d(�Gd-d.�d.e*��Z+Gd/d0�d0e&�Z,dS)1a>	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.cwd()
* Process.environ()
* Process.exe()
* Process.memory_maps()
* Process.name()
* Process.net_connections('unix')
* 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)�POSIX)�WINDOWS)�PY3)�super)�APPVEYOR)�ASCII_FS)�
CI_TESTING)�HAS_ENVIRON)�HAS_MEMORY_MAPS)�HAS_NET_CONNECTIONS_UNIX)�INVALID_UNICODE_SUFFIX)�PYPY��
TESTFN_PREFIX)�UNICODE_SUFFIX)�PsutilTestCase)�bind_unix_socket)�chdir)�copyload_shared_lib)�
create_py_exe)�
get_testfn)�pytest)�
safe_mkdir��safe_rmpath)�skip_on_access_denied)�spawn_testproc)�	terminatecCs6ddlm}z
||�WSty0t��Yn0dS)Nrr)�psutil.testsrZWindowsError�	traceback�	print_exc)�pathZrm�r$�E/usr/local/lib64/python3.9/site-packages/psutil/tests/test_unicode.pyrqs

rc	Cs�d}t|d�}z�z<t|�t|�t|gd�}t�||d�t|d�Wn2ttfy~YW|durrt|�t|�dS0W|dur�t|�t|�dSW|dur�t|�t|�n|dur�t|�t|�0dS)z`Return True if both the fs and the subprocess module can
    deal with a unicode file name.
    N��suffix)�cmdz-2FT)	rrrr�shutil�copyfile�UnicodeEncodeError�IOErrorr)r'�sprocZtestfnr$r$r%�try_unicode�s2
��
�r.cs0eZdZdZe�fdd��Z�fdd�Z�ZS)�BaseUnicodeTestNcsNt���d|_d|_|jdurJt|j�s2d|_nt|jd�|_t|j�dS)NFTr&)r�
setUpClass�
skip_tests�
funky_name�funky_suffixr.rr)�cls��	__class__r$r%r0�s


zBaseUnicodeTest.setUpClasscst���|jrt�d��dS)Nzcan't handle unicode str)r�setUpr1r�skip��selfr5r$r%r7�s
zBaseUnicodeTest.setUp)�__name__�
__module__�__qualname__r3�classmethodr0r7�
__classcell__r$r$r5r%r/�sr/�serial)�namezASCII fs��reasonztoo much trouble on PYPY2c@s�eZdZdZeZdd�Zdd�Zdd�Zdd	�Z	d
d�Z
ejj
eoDedd
�dd��Zejj
edd
�dd��Zejj
edd
�ejj
edd
�e�dd����Zdd�Zejj
edd
�ejj
edd
�ejj
edd
�dd����ZdS)�
TestFSAPIsz1Test FS APIs with a funky, valid, UTF8 path name.cCsZt|jt�rdnd}t���*t�d�|jt�|�vWd�S1sL0YdS)N�.�ignore)�
isinstancer2�str�warnings�catch_warnings�simplefilter�os�listdir)r:�herer$r$r%�expect_exact_path_match�s

z"TestFSAPIs.expect_exact_path_matchcCsb|jddg}|�|�}t�|j�}|��}t|t�s8J�|��r^t	j
�|�t	j
�|j�ks^J�dS�Nz-cz2import time; [time.sleep(0.1) for x in range(100)])r2r�psutil�Process�pid�exerGrHrOrLr#�normcase)r:r(�subp�prTr$r$r%�
test_proc_exe�s�
zTestFSAPIs.test_proc_execCsV|jddg}|�|�}t�|j���}t|t�s4J�|��rR|t	j
�|j�ksRJ�dSrP)r2rrQrRrSrArGrHrOrLr#�basename)r:r(rVrAr$r$r%�test_proc_name�s�
zTestFSAPIs.test_proc_namecCsZ|jddg}|�|�}t�|j�}|��}|D]}t|t�s.J�q.|��rV||ksVJ�dSrP)	r2rrQrRrS�cmdlinerGrHrO)r:r(rVrWr[�partr$r$r%�test_proc_cmdline�s�
zTestFSAPIs.test_proc_cmdlinecCs�|jd}|�t|�t|�t|�� t��}|��}Wd�n1sL0Yt|��t	�shJ�|�
�r|||ks|J�dS�N�2)r2�
addCleanuprrrrQrR�cwdrGrHrO)r:�dnamerWrar$r$r%�
test_proc_cwd�s

&zTestFSAPIs.test_proc_cwdzfails on PYPY + WINDOWSrBcCs�t��}t|���}t|jd��t|���}Wd�n1sB0Y||��j}t|t	�shJ�t
rz|szt�d��|�
�r�tj�|�tj�|j�ks�J�dS)N�rbzopen_files on BSD is broken)rQrR�setZ
open_files�openr2�popr#rGrHrrr8rOrLrU)r:rW�start�newr#r$r$r%�test_proc_open_files�s*
zTestFSAPIs.test_proc_open_filesz
POSIX onlycCs�|j|jd�}zt|�}Wn$ty>tr0�n
t�d��Yn0t|��@t�	��
d�d}t|jt
�slJ�|j|kszJ�Wd�n1s�0YdS)Nr&�
not supported�unixr)rr3rr+rrr8rrQrR�net_connectionsrG�laddrrH)r:rA�sock�connr$r$r%�test_proc_net_connectionss
z$TestFSAPIs.test_proc_net_connectionszcan't list UNIX socketscCs�dd�}|j|jd�}zt|�}Wn$tyFtr8�n
t�d��Yn0t|��Btj	dd�}||�}t
|jt�svJ�|j|ks�J�Wd�n1s�0YdS)NcSs2|D] }tj�|j��t�r|Sqtd��dS)Nzconnection not found)rLr#rYrn�
startswithr�
ValueError)�consrpr$r$r%�	find_socks
z2TestFSAPIs.test_net_connections.<locals>.find_sockr&rkrl)�kind)
rr3rr+rrr8rrQrmrGrnrH)r:rurArortrpr$r$r%�test_net_connectionss
zTestFSAPIs.test_net_connectionscCs,|jd}|�t|�t|�t�|�dSr^)r2r`rrrQ�
disk_usage)r:rbr$r$r%�test_disk_usage/s
zTestFSAPIs.test_disk_usagerkz&ctypes does not support unicode on PY2zunstable on PYPYcs�t|jd��h}dd���fdd�t����D�}dd�|D�}�|�|vsNJ�|D]}t|t�sRJ�qRWd�n1sz0YdS)Nr&cSstj�tj�|��S)N)rLr#�realpathrU)rWr$r$r%�normpath?sz-TestFSAPIs.test_memory_maps.<locals>.normpathcsg|]}�|j��qSr$)r#��.0�x�r{r$r%�
<listcomp>Bsz/TestFSAPIs.test_memory_maps.<locals>.<listcomp>cSsg|]}t|vr|�qSr$rr|r$r$r%r�F�)rr3rQrRZmemory_mapsrGrH)r:Z
funky_pathZlibpathsr#r$rr%�test_memory_maps5s

�zTestFSAPIs.test_memory_mapsN)r;r<r=�__doc__rr3rOrXrZr]rcr�mark�skipifrrrjrrqr
rrwryrrr�r$r$r$r%rD�s0




��rDzunreliable on CIc@seZdZdZeZdd�ZdS)�TestFSAPIsWithInvalidPathz-Test FS APIs with a funky, invalid path name.cCsdS)NTr$r9r$r$r%rORsz1TestFSAPIsWithInvalidPath.expect_exact_path_matchN)r;r<r=r�rr3rOr$r$r$r%r�Lsr�c@sJeZdZdZerendZejj	e
dd�ejj	eo4edd�dd���Z
dS)	�
TestNonFSAPISz&Unicode tests for non fs-related APIs.�èrkrBzsegfaults on PYPY + WINDOWScCsxtj��}|j|d<|j|d�}t�|j�}|��}|��D]$\}}t	|t
�sRJ�t	|t
�s<J�q<|d|jkstJ�dS)NZ	FUNNY_ARG)�env)rL�environ�copyr3rrQrRrS�itemsrGrH)r:r�r-rW�k�vr$r$r%�test_proc_environas

zTestNonFSAPIS.test_proc_environN)r;r<r=r�rrr3rr�r�rrrr�r$r$r$r%r�\s
r�)-r�rLr)r!rI�
contextlibrrQrrrZpsutil._compatrrr rr	r
rrr
rrrrrrrrrrrrrrrrr.r/r�Zxdist_groupr�rDr�r�r$r$r$r%�<module>sZCPKok\7؄؄psutil/tests/test_windows.pynu�[���#!/usr/bin/env python3
# -*- coding: UTF-8 -*

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Windows specific tests."""

import datetime
import errno
import glob
import os
import platform
import re
import signal
import subprocess
import sys
import time
import warnings

import psutil
from psutil import WINDOWS
from psutil._compat import FileNotFoundError
from psutil._compat import super
from psutil._compat import which
from psutil.tests import APPVEYOR
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import HAS_BATTERY
from psutil.tests import IS_64BIT
from psutil.tests import PY3
from psutil.tests import PYPY
from psutil.tests import TOLERANCE_DISK_USAGE
from psutil.tests import TOLERANCE_SYS_MEM
from psutil.tests import PsutilTestCase
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import spawn_testproc
from psutil.tests import terminate


if WINDOWS and not PYPY:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        import win32api  # requires "pip install pywin32"
        import win32con
        import win32process
        import wmi  # requires "pip install wmi" / "make install-pydeps-test"

if WINDOWS:
    from psutil._pswindows import convert_oserror


cext = psutil._psplatform.cext


@pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
@pytest.mark.skipif(PYPY, reason="pywin32 not available on PYPY")
# https://github.com/giampaolo/psutil/pull/1762#issuecomment-632892692
@pytest.mark.skipif(
    GITHUB_ACTIONS and not PY3, reason="pywin32 broken on GITHUB + PY2"
)
class WindowsTestCase(PsutilTestCase):
    pass


def powershell(cmd):
    """Currently not used, but available just in case. Usage:

    >>> powershell(
        "Get-CIMInstance Win32_PageFileUsage | Select AllocatedBaseSize")
    """
    if not which("powershell.exe"):
        raise pytest.skip("powershell.exe not available")
    cmdline = (
        'powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive '
        + '-NoProfile -WindowStyle Hidden -Command "%s"' % cmd
    )
    return sh(cmdline)


def wmic(path, what, converter=int):
    """Currently not used, but available just in case. Usage:

    >>> wmic("Win32_OperatingSystem", "FreePhysicalMemory")
    2134124534
    """
    out = sh("wmic path %s get %s" % (path, what)).strip()
    data = "".join(out.splitlines()[1:]).strip()  # get rid of the header
    if converter is not None:
        if "," in what:
            return tuple([converter(x) for x in data.split()])
        else:
            return converter(data)
    else:
        return data


# ===================================================================
# System APIs
# ===================================================================


class TestCpuAPIs(WindowsTestCase):
    @pytest.mark.skipif(
        'NUMBER_OF_PROCESSORS' not in os.environ,
        reason="NUMBER_OF_PROCESSORS env var is not available",
    )
    def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self):
        # Will likely fail on many-cores systems:
        # https://stackoverflow.com/questions/31209256
        num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
        assert num_cpus == psutil.cpu_count()

    def test_cpu_count_vs_GetSystemInfo(self):
        # Will likely fail on many-cores systems:
        # https://stackoverflow.com/questions/31209256
        sys_value = win32api.GetSystemInfo()[5]
        psutil_value = psutil.cpu_count()
        assert sys_value == psutil_value

    def test_cpu_count_logical_vs_wmi(self):
        w = wmi.WMI()
        procs = sum(
            proc.NumberOfLogicalProcessors for proc in w.Win32_Processor()
        )
        assert psutil.cpu_count() == procs

    def test_cpu_count_cores_vs_wmi(self):
        w = wmi.WMI()
        cores = sum(proc.NumberOfCores for proc in w.Win32_Processor())
        assert psutil.cpu_count(logical=False) == cores

    def test_cpu_count_vs_cpu_times(self):
        assert psutil.cpu_count() == len(psutil.cpu_times(percpu=True))

    def test_cpu_freq(self):
        w = wmi.WMI()
        proc = w.Win32_Processor()[0]
        assert proc.CurrentClockSpeed == psutil.cpu_freq().current
        assert proc.MaxClockSpeed == psutil.cpu_freq().max


class TestSystemAPIs(WindowsTestCase):
    def test_nic_names(self):
        out = sh('ipconfig /all')
        nics = psutil.net_io_counters(pernic=True).keys()
        for nic in nics:
            if "pseudo-interface" in nic.replace(' ', '-').lower():
                continue
            if nic not in out:
                raise self.fail(
                    "%r nic wasn't found in 'ipconfig /all' output" % nic
                )

    def test_total_phymem(self):
        w = wmi.WMI().Win32_ComputerSystem()[0]
        assert int(w.TotalPhysicalMemory) == psutil.virtual_memory().total

    def test_free_phymem(self):
        w = wmi.WMI().Win32_PerfRawData_PerfOS_Memory()[0]
        assert (
            abs(int(w.AvailableBytes) - psutil.virtual_memory().free)
            < TOLERANCE_SYS_MEM
        )

    def test_total_swapmem(self):
        w = wmi.WMI().Win32_PerfRawData_PerfOS_Memory()[0]
        assert (
            int(w.CommitLimit) - psutil.virtual_memory().total
            == psutil.swap_memory().total
        )
        if psutil.swap_memory().total == 0:
            assert psutil.swap_memory().free == 0
            assert psutil.swap_memory().used == 0

    def test_percent_swapmem(self):
        if psutil.swap_memory().total > 0:
            w = wmi.WMI().Win32_PerfRawData_PerfOS_PagingFile(Name="_Total")[0]
            # calculate swap usage to percent
            percentSwap = int(w.PercentUsage) * 100 / int(w.PercentUsage_Base)
            # exact percent may change but should be reasonable
            # assert within +/- 5% and between 0 and 100%
            assert psutil.swap_memory().percent >= 0
            assert abs(psutil.swap_memory().percent - percentSwap) < 5
            assert psutil.swap_memory().percent <= 100

    # @pytest.mark.skipif(wmi is None, reason="wmi module is not installed")
    # def test__UPTIME(self):
    #     # _UPTIME constant is not public but it is used internally
    #     # as value to return for pid 0 creation time.
    #     # WMI behaves the same.
    #     w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
    #     p = psutil.Process(0)
    #     wmic_create = str(w.CreationDate.split('.')[0])
    #     psutil_create = time.strftime("%Y%m%d%H%M%S",
    #                                   time.localtime(p.create_time()))

    # Note: this test is not very reliable
    @pytest.mark.skipif(APPVEYOR, reason="test not relieable on appveyor")
    @retry_on_failure()
    def test_pids(self):
        # Note: this test might fail if the OS is starting/killing
        # other processes in the meantime
        w = wmi.WMI().Win32_Process()
        wmi_pids = set([x.ProcessId for x in w])
        psutil_pids = set(psutil.pids())
        assert wmi_pids == psutil_pids

    @retry_on_failure()
    def test_disks(self):
        ps_parts = psutil.disk_partitions(all=True)
        wmi_parts = wmi.WMI().Win32_LogicalDisk()
        for ps_part in ps_parts:
            for wmi_part in wmi_parts:
                if ps_part.device.replace('\\', '') == wmi_part.DeviceID:
                    if not ps_part.mountpoint:
                        # this is usually a CD-ROM with no disk inserted
                        break
                    if 'cdrom' in ps_part.opts:
                        break
                    if ps_part.mountpoint.startswith('A:'):
                        break  # floppy
                    try:
                        usage = psutil.disk_usage(ps_part.mountpoint)
                    except FileNotFoundError:
                        # usually this is the floppy
                        break
                    assert usage.total == int(wmi_part.Size)
                    wmi_free = int(wmi_part.FreeSpace)
                    assert usage.free == wmi_free
                    # 10 MB tolerance
                    if abs(usage.free - wmi_free) > 10 * 1024 * 1024:
                        raise self.fail(
                            "psutil=%s, wmi=%s" % (usage.free, wmi_free)
                        )
                    break
            else:
                raise self.fail("can't find partition %s" % repr(ps_part))

    @retry_on_failure()
    def test_disk_usage(self):
        for disk in psutil.disk_partitions():
            if 'cdrom' in disk.opts:
                continue
            sys_value = win32api.GetDiskFreeSpaceEx(disk.mountpoint)
            psutil_value = psutil.disk_usage(disk.mountpoint)
            assert abs(sys_value[0] - psutil_value.free) < TOLERANCE_DISK_USAGE
            assert (
                abs(sys_value[1] - psutil_value.total) < TOLERANCE_DISK_USAGE
            )
            assert psutil_value.used == psutil_value.total - psutil_value.free

    def test_disk_partitions(self):
        sys_value = [
            x + '\\'
            for x in win32api.GetLogicalDriveStrings().split("\\\x00")
            if x and not x.startswith('A:')
        ]
        psutil_value = [
            x.mountpoint
            for x in psutil.disk_partitions(all=True)
            if not x.mountpoint.startswith('A:')
        ]
        assert sys_value == psutil_value

    def test_net_if_stats(self):
        ps_names = set(cext.net_if_stats())
        wmi_adapters = wmi.WMI().Win32_NetworkAdapter()
        wmi_names = set()
        for wmi_adapter in wmi_adapters:
            wmi_names.add(wmi_adapter.Name)
            wmi_names.add(wmi_adapter.NetConnectionID)
        assert ps_names & wmi_names, "no common entries in %s, %s" % (
            ps_names,
            wmi_names,
        )

    def test_boot_time(self):
        wmi_os = wmi.WMI().Win32_OperatingSystem()
        wmi_btime_str = wmi_os[0].LastBootUpTime.split('.')[0]
        wmi_btime_dt = datetime.datetime.strptime(
            wmi_btime_str, "%Y%m%d%H%M%S"
        )
        psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time())
        diff = abs((wmi_btime_dt - psutil_dt).total_seconds())
        assert diff <= 5

    def test_boot_time_fluctuation(self):
        # https://github.com/giampaolo/psutil/issues/1007
        with mock.patch('psutil._pswindows.cext.boot_time', return_value=5):
            assert psutil.boot_time() == 5
        with mock.patch('psutil._pswindows.cext.boot_time', return_value=4):
            assert psutil.boot_time() == 5
        with mock.patch('psutil._pswindows.cext.boot_time', return_value=6):
            assert psutil.boot_time() == 5
        with mock.patch('psutil._pswindows.cext.boot_time', return_value=333):
            assert psutil.boot_time() == 333


# ===================================================================
# sensors_battery()
# ===================================================================


class TestSensorsBattery(WindowsTestCase):
    def test_has_battery(self):
        if win32api.GetPwrCapabilities()['SystemBatteriesPresent']:
            assert psutil.sensors_battery() is not None
        else:
            assert psutil.sensors_battery() is None

    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_percent(self):
        w = wmi.WMI()
        battery_wmi = w.query('select * from Win32_Battery')[0]
        battery_psutil = psutil.sensors_battery()
        assert (
            abs(battery_psutil.percent - battery_wmi.EstimatedChargeRemaining)
            < 1
        )

    @pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
    def test_power_plugged(self):
        w = wmi.WMI()
        battery_wmi = w.query('select * from Win32_Battery')[0]
        battery_psutil = psutil.sensors_battery()
        # Status codes:
        # https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx
        assert battery_psutil.power_plugged == (battery_wmi.BatteryStatus == 2)

    def test_emulate_no_battery(self):
        with mock.patch(
            "psutil._pswindows.cext.sensors_battery",
            return_value=(0, 128, 0, 0),
        ) as m:
            assert psutil.sensors_battery() is None
            assert m.called

    def test_emulate_power_connected(self):
        with mock.patch(
            "psutil._pswindows.cext.sensors_battery", return_value=(1, 0, 0, 0)
        ) as m:
            assert (
                psutil.sensors_battery().secsleft
                == psutil.POWER_TIME_UNLIMITED
            )
            assert m.called

    def test_emulate_power_charging(self):
        with mock.patch(
            "psutil._pswindows.cext.sensors_battery", return_value=(0, 8, 0, 0)
        ) as m:
            assert (
                psutil.sensors_battery().secsleft
                == psutil.POWER_TIME_UNLIMITED
            )
            assert m.called

    def test_emulate_secs_left_unknown(self):
        with mock.patch(
            "psutil._pswindows.cext.sensors_battery",
            return_value=(0, 0, 0, -1),
        ) as m:
            assert (
                psutil.sensors_battery().secsleft == psutil.POWER_TIME_UNKNOWN
            )
            assert m.called


# ===================================================================
# Process APIs
# ===================================================================


class TestProcess(WindowsTestCase):
    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    def test_issue_24(self):
        p = psutil.Process(0)
        with pytest.raises(psutil.AccessDenied):
            p.kill()

    def test_special_pid(self):
        p = psutil.Process(4)
        assert p.name() == 'System'
        # use __str__ to access all common Process properties to check
        # that nothing strange happens
        str(p)
        p.username()
        assert p.create_time() >= 0.0
        try:
            rss, _vms = p.memory_info()[:2]
        except psutil.AccessDenied:
            # expected on Windows Vista and Windows 7
            if platform.uname()[1] not in ('vista', 'win-7', 'win7'):
                raise
        else:
            assert rss > 0

    def test_send_signal(self):
        p = psutil.Process(self.pid)
        with pytest.raises(ValueError):
            p.send_signal(signal.SIGINT)

    def test_num_handles_increment(self):
        p = psutil.Process(os.getpid())
        before = p.num_handles()
        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, os.getpid()
        )
        after = p.num_handles()
        assert after == before + 1
        win32api.CloseHandle(handle)
        assert p.num_handles() == before

    def test_ctrl_signals(self):
        p = psutil.Process(self.spawn_testproc().pid)
        p.send_signal(signal.CTRL_C_EVENT)
        p.send_signal(signal.CTRL_BREAK_EVENT)
        p.kill()
        p.wait()
        with pytest.raises(psutil.NoSuchProcess):
            p.send_signal(signal.CTRL_C_EVENT)
        with pytest.raises(psutil.NoSuchProcess):
            p.send_signal(signal.CTRL_BREAK_EVENT)

    def test_username(self):
        name = win32api.GetUserNameEx(win32con.NameSamCompatible)
        if name.endswith('$'):
            # When running as a service account (most likely to be
            # NetworkService), these user name calculations don't produce the
            # same result, causing the test to fail.
            raise pytest.skip('running as service account')
        assert psutil.Process().username() == name

    def test_cmdline(self):
        sys_value = re.sub('[ ]+', ' ', win32api.GetCommandLine()).strip()
        psutil_value = ' '.join(psutil.Process().cmdline())
        if sys_value[0] == '"' != psutil_value[0]:
            # The PyWin32 command line may retain quotes around argv[0] if they
            # were used unnecessarily, while psutil will omit them. So remove
            # the first 2 quotes from sys_value if not in psutil_value.
            # A path to an executable will not contain quotes, so this is safe.
            sys_value = sys_value.replace('"', '', 2)
        assert sys_value == psutil_value

    # XXX - occasional failures

    # def test_cpu_times(self):
    #     handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION,
    #                                   win32con.FALSE, os.getpid())
    #     self.addCleanup(win32api.CloseHandle, handle)
    #     sys_value = win32process.GetProcessTimes(handle)
    #     psutil_value = psutil.Process().cpu_times()
    #     self.assertAlmostEqual(
    #         psutil_value.user, sys_value['UserTime'] / 10000000.0,
    #         delta=0.2)
    #     self.assertAlmostEqual(
    #         psutil_value.user, sys_value['KernelTime'] / 10000000.0,
    #         delta=0.2)

    def test_nice(self):
        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, os.getpid()
        )
        self.addCleanup(win32api.CloseHandle, handle)
        sys_value = win32process.GetPriorityClass(handle)
        psutil_value = psutil.Process().nice()
        assert psutil_value == sys_value

    def test_memory_info(self):
        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, self.pid
        )
        self.addCleanup(win32api.CloseHandle, handle)
        sys_value = win32process.GetProcessMemoryInfo(handle)
        psutil_value = psutil.Process(self.pid).memory_info()
        assert sys_value['PeakWorkingSetSize'] == psutil_value.peak_wset
        assert sys_value['WorkingSetSize'] == psutil_value.wset
        assert (
            sys_value['QuotaPeakPagedPoolUsage']
            == psutil_value.peak_paged_pool
        )
        assert sys_value['QuotaPagedPoolUsage'] == psutil_value.paged_pool
        assert (
            sys_value['QuotaPeakNonPagedPoolUsage']
            == psutil_value.peak_nonpaged_pool
        )
        assert (
            sys_value['QuotaNonPagedPoolUsage'] == psutil_value.nonpaged_pool
        )
        assert sys_value['PagefileUsage'] == psutil_value.pagefile
        assert sys_value['PeakPagefileUsage'] == psutil_value.peak_pagefile

        assert psutil_value.rss == psutil_value.wset
        assert psutil_value.vms == psutil_value.pagefile

    def test_wait(self):
        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, self.pid
        )
        self.addCleanup(win32api.CloseHandle, handle)
        p = psutil.Process(self.pid)
        p.terminate()
        psutil_value = p.wait()
        sys_value = win32process.GetExitCodeProcess(handle)
        assert psutil_value == sys_value

    def test_cpu_affinity(self):
        def from_bitmask(x):
            return [i for i in range(64) if (1 << i) & x]

        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, self.pid
        )
        self.addCleanup(win32api.CloseHandle, handle)
        sys_value = from_bitmask(
            win32process.GetProcessAffinityMask(handle)[0]
        )
        psutil_value = psutil.Process(self.pid).cpu_affinity()
        assert psutil_value == sys_value

    def test_io_counters(self):
        handle = win32api.OpenProcess(
            win32con.PROCESS_QUERY_INFORMATION, win32con.FALSE, os.getpid()
        )
        self.addCleanup(win32api.CloseHandle, handle)
        sys_value = win32process.GetProcessIoCounters(handle)
        psutil_value = psutil.Process().io_counters()
        assert psutil_value.read_count == sys_value['ReadOperationCount']
        assert psutil_value.write_count == sys_value['WriteOperationCount']
        assert psutil_value.read_bytes == sys_value['ReadTransferCount']
        assert psutil_value.write_bytes == sys_value['WriteTransferCount']
        assert psutil_value.other_count == sys_value['OtherOperationCount']
        assert psutil_value.other_bytes == sys_value['OtherTransferCount']

    def test_num_handles(self):
        import ctypes
        import ctypes.wintypes

        PROCESS_QUERY_INFORMATION = 0x400
        handle = ctypes.windll.kernel32.OpenProcess(
            PROCESS_QUERY_INFORMATION, 0, self.pid
        )
        self.addCleanup(ctypes.windll.kernel32.CloseHandle, handle)

        hndcnt = ctypes.wintypes.DWORD()
        ctypes.windll.kernel32.GetProcessHandleCount(
            handle, ctypes.byref(hndcnt)
        )
        sys_value = hndcnt.value
        psutil_value = psutil.Process(self.pid).num_handles()
        assert psutil_value == sys_value

    def test_error_partial_copy(self):
        # https://github.com/giampaolo/psutil/issues/875
        exc = WindowsError()
        exc.winerror = 299
        with mock.patch("psutil._psplatform.cext.proc_cwd", side_effect=exc):
            with mock.patch("time.sleep") as m:
                p = psutil.Process()
                with pytest.raises(psutil.AccessDenied):
                    p.cwd()
        assert m.call_count >= 5

    def test_exe(self):
        # NtQuerySystemInformation succeeds if process is gone. Make sure
        # it raises NSP for a non existent pid.
        pid = psutil.pids()[-1] + 99999
        proc = psutil._psplatform.Process(pid)
        with pytest.raises(psutil.NoSuchProcess):
            proc.exe()


class TestProcessWMI(WindowsTestCase):
    """Compare Process API results with WMI."""

    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    def test_name(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        assert p.name() == w.Caption

    # This fail on github because using virtualenv for test environment
    @pytest.mark.skipif(
        GITHUB_ACTIONS, reason="unreliable path on GITHUB_ACTIONS"
    )
    def test_exe(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        # Note: wmi reports the exe as a lower case string.
        # Being Windows paths case-insensitive we ignore that.
        assert p.exe().lower() == w.ExecutablePath.lower()

    def test_cmdline(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        assert ' '.join(p.cmdline()) == w.CommandLine.replace('"', '')

    def test_username(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        domain, _, username = w.GetOwner()
        username = "%s\\%s" % (domain, username)
        assert p.username() == username

    @retry_on_failure()
    def test_memory_rss(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        rss = p.memory_info().rss
        assert rss == int(w.WorkingSetSize)

    @retry_on_failure()
    def test_memory_vms(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        vms = p.memory_info().vms
        # http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx
        # ...claims that PageFileUsage is represented in Kilo
        # bytes but funnily enough on certain platforms bytes are
        # returned instead.
        wmi_usage = int(w.PageFileUsage)
        if vms not in (wmi_usage, wmi_usage * 1024):
            raise self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms))

    def test_create_time(self):
        w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
        p = psutil.Process(self.pid)
        wmic_create = str(w.CreationDate.split('.')[0])
        psutil_create = time.strftime(
            "%Y%m%d%H%M%S", time.localtime(p.create_time())
        )
        assert wmic_create == psutil_create


# ---


@pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
class TestDualProcessImplementation(PsutilTestCase):
    """Certain APIs on Windows have 2 internal implementations, one
    based on documented Windows APIs, another one based
    NtQuerySystemInformation() which gets called as fallback in
    case the first fails because of limited permission error.
    Here we test that the two methods return the exact same value,
    see:
    https://github.com/giampaolo/psutil/issues/304.
    """

    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc().pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    def test_memory_info(self):
        mem_1 = psutil.Process(self.pid).memory_info()
        with mock.patch(
            "psutil._psplatform.cext.proc_memory_info",
            side_effect=OSError(errno.EPERM, "msg"),
        ) as fun:
            mem_2 = psutil.Process(self.pid).memory_info()
            assert len(mem_1) == len(mem_2)
            for i in range(len(mem_1)):
                assert mem_1[i] >= 0
                assert mem_2[i] >= 0
                assert abs(mem_1[i] - mem_2[i]) < 512
            assert fun.called

    def test_create_time(self):
        ctime = psutil.Process(self.pid).create_time()
        with mock.patch(
            "psutil._psplatform.cext.proc_times",
            side_effect=OSError(errno.EPERM, "msg"),
        ) as fun:
            assert psutil.Process(self.pid).create_time() == ctime
            assert fun.called

    def test_cpu_times(self):
        cpu_times_1 = psutil.Process(self.pid).cpu_times()
        with mock.patch(
            "psutil._psplatform.cext.proc_times",
            side_effect=OSError(errno.EPERM, "msg"),
        ) as fun:
            cpu_times_2 = psutil.Process(self.pid).cpu_times()
            assert fun.called
            assert abs(cpu_times_1.user - cpu_times_2.user) < 0.01
            assert abs(cpu_times_1.system - cpu_times_2.system) < 0.01

    def test_io_counters(self):
        io_counters_1 = psutil.Process(self.pid).io_counters()
        with mock.patch(
            "psutil._psplatform.cext.proc_io_counters",
            side_effect=OSError(errno.EPERM, "msg"),
        ) as fun:
            io_counters_2 = psutil.Process(self.pid).io_counters()
            for i in range(len(io_counters_1)):
                assert abs(io_counters_1[i] - io_counters_2[i]) < 5
            assert fun.called

    def test_num_handles(self):
        num_handles = psutil.Process(self.pid).num_handles()
        with mock.patch(
            "psutil._psplatform.cext.proc_num_handles",
            side_effect=OSError(errno.EPERM, "msg"),
        ) as fun:
            assert psutil.Process(self.pid).num_handles() == num_handles
            assert fun.called

    def test_cmdline(self):
        for pid in psutil.pids():
            try:
                a = cext.proc_cmdline(pid, use_peb=True)
                b = cext.proc_cmdline(pid, use_peb=False)
            except OSError as err:
                err = convert_oserror(err)
                if not isinstance(
                    err, (psutil.AccessDenied, psutil.NoSuchProcess)
                ):
                    raise
            else:
                assert a == b


@pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
class RemoteProcessTestCase(PsutilTestCase):
    """Certain functions require calling ReadProcessMemory.
    This trivially works when called on the current process.
    Check that this works on other processes, especially when they
    have a different bitness.
    """

    @staticmethod
    def find_other_interpreter():
        # find a python interpreter that is of the opposite bitness from us
        code = "import sys; sys.stdout.write(str(sys.maxsize > 2**32))"

        # XXX: a different and probably more stable approach might be to access
        # the registry but accessing 64 bit paths from a 32 bit process
        for filename in glob.glob(r"C:\Python*\python.exe"):
            proc = subprocess.Popen(
                args=[filename, "-c", code],
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
            )
            output, _ = proc.communicate()
            proc.wait()
            if output == str(not IS_64BIT):
                return filename

    test_args = ["-c", "import sys; sys.stdin.read()"]

    def setUp(self):
        super().setUp()

        other_python = self.find_other_interpreter()
        if other_python is None:
            raise pytest.skip(
                "could not find interpreter with opposite bitness"
            )
        if IS_64BIT:
            self.python64 = sys.executable
            self.python32 = other_python
        else:
            self.python64 = other_python
            self.python32 = sys.executable

        env = os.environ.copy()
        env["THINK_OF_A_NUMBER"] = str(os.getpid())
        self.proc32 = self.spawn_testproc(
            [self.python32] + self.test_args, env=env, stdin=subprocess.PIPE
        )
        self.proc64 = self.spawn_testproc(
            [self.python64] + self.test_args, env=env, stdin=subprocess.PIPE
        )

    def tearDown(self):
        super().tearDown()
        self.proc32.communicate()
        self.proc64.communicate()

    def test_cmdline_32(self):
        p = psutil.Process(self.proc32.pid)
        assert len(p.cmdline()) == 3
        assert p.cmdline()[1:] == self.test_args

    def test_cmdline_64(self):
        p = psutil.Process(self.proc64.pid)
        assert len(p.cmdline()) == 3
        assert p.cmdline()[1:] == self.test_args

    def test_cwd_32(self):
        p = psutil.Process(self.proc32.pid)
        assert p.cwd() == os.getcwd()

    def test_cwd_64(self):
        p = psutil.Process(self.proc64.pid)
        assert p.cwd() == os.getcwd()

    def test_environ_32(self):
        p = psutil.Process(self.proc32.pid)
        e = p.environ()
        assert "THINK_OF_A_NUMBER" in e
        assert e["THINK_OF_A_NUMBER"] == str(os.getpid())

    def test_environ_64(self):
        p = psutil.Process(self.proc64.pid)
        try:
            p.environ()
        except psutil.AccessDenied:
            pass


# ===================================================================
# Windows services
# ===================================================================


@pytest.mark.skipif(not WINDOWS, reason="WINDOWS only")
class TestServices(PsutilTestCase):
    def test_win_service_iter(self):
        valid_statuses = set([
            "running",
            "paused",
            "start",
            "pause",
            "continue",
            "stop",
            "stopped",
        ])
        valid_start_types = set(["automatic", "manual", "disabled"])
        valid_statuses = set([
            "running",
            "paused",
            "start_pending",
            "pause_pending",
            "continue_pending",
            "stop_pending",
            "stopped",
        ])
        for serv in psutil.win_service_iter():
            data = serv.as_dict()
            assert isinstance(data['name'], str)
            assert data['name'].strip()
            assert isinstance(data['display_name'], str)
            assert isinstance(data['username'], str)
            assert data['status'] in valid_statuses
            if data['pid'] is not None:
                psutil.Process(data['pid'])
            assert isinstance(data['binpath'], str)
            assert isinstance(data['username'], str)
            assert isinstance(data['start_type'], str)
            assert data['start_type'] in valid_start_types
            assert data['status'] in valid_statuses
            assert isinstance(data['description'], str)
            pid = serv.pid()
            if pid is not None:
                p = psutil.Process(pid)
                assert p.is_running()
            # win_service_get
            s = psutil.win_service_get(serv.name())
            # test __eq__
            assert serv == s

    def test_win_service_get(self):
        ERROR_SERVICE_DOES_NOT_EXIST = (
            psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST
        )
        ERROR_ACCESS_DENIED = psutil._psplatform.cext.ERROR_ACCESS_DENIED

        name = next(psutil.win_service_iter()).name()
        with pytest.raises(psutil.NoSuchProcess) as cm:
            psutil.win_service_get(name + '???')
        assert cm.value.name == name + '???'

        # test NoSuchProcess
        service = psutil.win_service_get(name)
        if PY3:
            args = (0, "msg", 0, ERROR_SERVICE_DOES_NOT_EXIST)
        else:
            args = (ERROR_SERVICE_DOES_NOT_EXIST, "msg")
        exc = WindowsError(*args)
        with mock.patch(
            "psutil._psplatform.cext.winservice_query_status", side_effect=exc
        ):
            with pytest.raises(psutil.NoSuchProcess):
                service.status()
        with mock.patch(
            "psutil._psplatform.cext.winservice_query_config", side_effect=exc
        ):
            with pytest.raises(psutil.NoSuchProcess):
                service.username()

        # test AccessDenied
        if PY3:
            args = (0, "msg", 0, ERROR_ACCESS_DENIED)
        else:
            args = (ERROR_ACCESS_DENIED, "msg")
        exc = WindowsError(*args)
        with mock.patch(
            "psutil._psplatform.cext.winservice_query_status", side_effect=exc
        ):
            with pytest.raises(psutil.AccessDenied):
                service.status()
        with mock.patch(
            "psutil._psplatform.cext.winservice_query_config", side_effect=exc
        ):
            with pytest.raises(psutil.AccessDenied):
                service.username()

        # test __str__ and __repr__
        assert service.name() in str(service)
        assert service.display_name() in str(service)
        assert service.name() in repr(service)
        assert service.display_name() in repr(service)
PKok\�P�
�H�Hpsutil/tests/test_testutils.pynu�[���#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for testing utils (psutil.tests namespace)."""

import collections
import contextlib
import errno
import os
import socket
import stat
import subprocess
import textwrap
import unittest
import warnings

import psutil
import psutil.tests
from psutil import FREEBSD
from psutil import NETBSD
from psutil import POSIX
from psutil._common import open_binary
from psutil._common import open_text
from psutil._common import supports_ipv6
from psutil._compat import PY3
from psutil.tests import CI_TESTING
from psutil.tests import COVERAGE
from psutil.tests import HAS_NET_CONNECTIONS_UNIX
from psutil.tests import HERE
from psutil.tests import PYTHON_EXE
from psutil.tests import PYTHON_EXE_ENV
from psutil.tests import PsutilTestCase
from psutil.tests import TestMemoryLeak
from psutil.tests import bind_socket
from psutil.tests import bind_unix_socket
from psutil.tests import call_until
from psutil.tests import chdir
from psutil.tests import create_sockets
from psutil.tests import fake_pytest
from psutil.tests import filter_proc_net_connections
from psutil.tests import get_free_port
from psutil.tests import is_namedtuple
from psutil.tests import mock
from psutil.tests import process_namespace
from psutil.tests import pytest
from psutil.tests import reap_children
from psutil.tests import retry
from psutil.tests import retry_on_failure
from psutil.tests import safe_mkdir
from psutil.tests import safe_rmpath
from psutil.tests import system_namespace
from psutil.tests import tcp_socketpair
from psutil.tests import terminate
from psutil.tests import unix_socketpair
from psutil.tests import wait_for_file
from psutil.tests import wait_for_pid


# ===================================================================
# --- Unit tests for test utilities.
# ===================================================================


class TestRetryDecorator(PsutilTestCase):
    @mock.patch('time.sleep')
    def test_retry_success(self, sleep):
        # Fail 3 times out of 5; make sure the decorated fun returns.

        @retry(retries=5, interval=1, logfun=None)
        def foo():
            while queue:
                queue.pop()
                1 / 0  # noqa
            return 1

        queue = list(range(3))
        assert foo() == 1
        assert sleep.call_count == 3

    @mock.patch('time.sleep')
    def test_retry_failure(self, sleep):
        # Fail 6 times out of 5; th function is supposed to raise exc.
        @retry(retries=5, interval=1, logfun=None)
        def foo():
            while queue:
                queue.pop()
                1 / 0  # noqa
            return 1

        queue = list(range(6))
        with pytest.raises(ZeroDivisionError):
            foo()
        assert sleep.call_count == 5

    @mock.patch('time.sleep')
    def test_exception_arg(self, sleep):
        @retry(exception=ValueError, interval=1)
        def foo():
            raise TypeError

        with pytest.raises(TypeError):
            foo()
        assert sleep.call_count == 0

    @mock.patch('time.sleep')
    def test_no_interval_arg(self, sleep):
        # if interval is not specified sleep is not supposed to be called

        @retry(retries=5, interval=None, logfun=None)
        def foo():
            1 / 0  # noqa

        with pytest.raises(ZeroDivisionError):
            foo()
        assert sleep.call_count == 0

    @mock.patch('time.sleep')
    def test_retries_arg(self, sleep):
        @retry(retries=5, interval=1, logfun=None)
        def foo():
            1 / 0  # noqa

        with pytest.raises(ZeroDivisionError):
            foo()
        assert sleep.call_count == 5

    @mock.patch('time.sleep')
    def test_retries_and_timeout_args(self, sleep):
        with pytest.raises(ValueError):
            retry(retries=5, timeout=1)


class TestSyncTestUtils(PsutilTestCase):
    def test_wait_for_pid(self):
        wait_for_pid(os.getpid())
        nopid = max(psutil.pids()) + 99999
        with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])):
            with pytest.raises(psutil.NoSuchProcess):
                wait_for_pid(nopid)

    def test_wait_for_file(self):
        testfn = self.get_testfn()
        with open(testfn, 'w') as f:
            f.write('foo')
        wait_for_file(testfn)
        assert not os.path.exists(testfn)

    def test_wait_for_file_empty(self):
        testfn = self.get_testfn()
        with open(testfn, 'w'):
            pass
        wait_for_file(testfn, empty=True)
        assert not os.path.exists(testfn)

    def test_wait_for_file_no_file(self):
        testfn = self.get_testfn()
        with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])):
            with pytest.raises(IOError):
                wait_for_file(testfn)

    def test_wait_for_file_no_delete(self):
        testfn = self.get_testfn()
        with open(testfn, 'w') as f:
            f.write('foo')
        wait_for_file(testfn, delete=False)
        assert os.path.exists(testfn)

    def test_call_until(self):
        call_until(lambda: 1)
        # TODO: test for timeout


class TestFSTestUtils(PsutilTestCase):
    def test_open_text(self):
        with open_text(__file__) as f:
            assert f.mode == 'r'

    def test_open_binary(self):
        with open_binary(__file__) as f:
            assert f.mode == 'rb'

    def test_safe_mkdir(self):
        testfn = self.get_testfn()
        safe_mkdir(testfn)
        assert os.path.isdir(testfn)
        safe_mkdir(testfn)
        assert os.path.isdir(testfn)

    def test_safe_rmpath(self):
        # test file is removed
        testfn = self.get_testfn()
        open(testfn, 'w').close()
        safe_rmpath(testfn)
        assert not os.path.exists(testfn)
        # test no exception if path does not exist
        safe_rmpath(testfn)
        # test dir is removed
        os.mkdir(testfn)
        safe_rmpath(testfn)
        assert not os.path.exists(testfn)
        # test other exceptions are raised
        with mock.patch(
            'psutil.tests.os.stat', side_effect=OSError(errno.EINVAL, "")
        ) as m:
            with pytest.raises(OSError):
                safe_rmpath(testfn)
            assert m.called

    def test_chdir(self):
        testfn = self.get_testfn()
        base = os.getcwd()
        os.mkdir(testfn)
        with chdir(testfn):
            assert os.getcwd() == os.path.join(base, testfn)
        assert os.getcwd() == base


class TestProcessUtils(PsutilTestCase):
    def test_reap_children(self):
        subp = self.spawn_testproc()
        p = psutil.Process(subp.pid)
        assert p.is_running()
        reap_children()
        assert not p.is_running()
        assert not psutil.tests._pids_started
        assert not psutil.tests._subprocesses_started

    def test_spawn_children_pair(self):
        child, grandchild = self.spawn_children_pair()
        assert child.pid != grandchild.pid
        assert child.is_running()
        assert grandchild.is_running()
        children = psutil.Process().children()
        assert children == [child]
        children = psutil.Process().children(recursive=True)
        assert len(children) == 2
        assert child in children
        assert grandchild in children
        assert child.ppid() == os.getpid()
        assert grandchild.ppid() == child.pid

        terminate(child)
        assert not child.is_running()
        assert grandchild.is_running()

        terminate(grandchild)
        assert not grandchild.is_running()

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_spawn_zombie(self):
        _parent, zombie = self.spawn_zombie()
        assert zombie.status() == psutil.STATUS_ZOMBIE

    def test_terminate(self):
        # by subprocess.Popen
        p = self.spawn_testproc()
        terminate(p)
        self.assertPidGone(p.pid)
        terminate(p)
        # by psutil.Process
        p = psutil.Process(self.spawn_testproc().pid)
        terminate(p)
        self.assertPidGone(p.pid)
        terminate(p)
        # by psutil.Popen
        cmd = [
            PYTHON_EXE,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)];",
        ]
        p = psutil.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=PYTHON_EXE_ENV,
        )
        terminate(p)
        self.assertPidGone(p.pid)
        terminate(p)
        # by PID
        pid = self.spawn_testproc().pid
        terminate(pid)
        self.assertPidGone(p.pid)
        terminate(pid)
        # zombie
        if POSIX:
            parent, zombie = self.spawn_zombie()
            terminate(parent)
            terminate(zombie)
            self.assertPidGone(parent.pid)
            self.assertPidGone(zombie.pid)


class TestNetUtils(PsutilTestCase):
    def bind_socket(self):
        port = get_free_port()
        with contextlib.closing(bind_socket(addr=('', port))) as s:
            assert s.getsockname()[1] == port

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_bind_unix_socket(self):
        name = self.get_testfn()
        sock = bind_unix_socket(name)
        with contextlib.closing(sock):
            assert sock.family == socket.AF_UNIX
            assert sock.type == socket.SOCK_STREAM
            assert sock.getsockname() == name
            assert os.path.exists(name)
            assert stat.S_ISSOCK(os.stat(name).st_mode)
        # UDP
        name = self.get_testfn()
        sock = bind_unix_socket(name, type=socket.SOCK_DGRAM)
        with contextlib.closing(sock):
            assert sock.type == socket.SOCK_DGRAM

    def tcp_tcp_socketpair(self):
        addr = ("127.0.0.1", get_free_port())
        server, client = tcp_socketpair(socket.AF_INET, addr=addr)
        with contextlib.closing(server):
            with contextlib.closing(client):
                # Ensure they are connected and the positions are
                # correct.
                assert server.getsockname() == addr
                assert client.getpeername() == addr
                assert client.getsockname() != addr

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @pytest.mark.skipif(
        NETBSD or FREEBSD, reason="/var/run/log UNIX socket opened by default"
    )
    def test_unix_socketpair(self):
        p = psutil.Process()
        num_fds = p.num_fds()
        assert (
            filter_proc_net_connections(p.net_connections(kind='unix')) == []
        )
        name = self.get_testfn()
        server, client = unix_socketpair(name)
        try:
            assert os.path.exists(name)
            assert stat.S_ISSOCK(os.stat(name).st_mode)
            assert p.num_fds() - num_fds == 2
            assert (
                len(
                    filter_proc_net_connections(p.net_connections(kind='unix'))
                )
                == 2
            )
            assert server.getsockname() == name
            assert client.getpeername() == name
        finally:
            client.close()
            server.close()

    def test_create_sockets(self):
        with create_sockets() as socks:
            fams = collections.defaultdict(int)
            types = collections.defaultdict(int)
            for s in socks:
                fams[s.family] += 1
                # work around http://bugs.python.org/issue30204
                types[s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)] += 1
            assert fams[socket.AF_INET] >= 2
            if supports_ipv6():
                assert fams[socket.AF_INET6] >= 2
            if POSIX and HAS_NET_CONNECTIONS_UNIX:
                assert fams[socket.AF_UNIX] >= 2
            assert types[socket.SOCK_STREAM] >= 2
            assert types[socket.SOCK_DGRAM] >= 2


@pytest.mark.xdist_group(name="serial")
class TestMemLeakClass(TestMemoryLeak):
    @retry_on_failure()
    def test_times(self):
        def fun():
            cnt['cnt'] += 1

        cnt = {'cnt': 0}
        self.execute(fun, times=10, warmup_times=15)
        assert cnt['cnt'] == 26

    def test_param_err(self):
        with pytest.raises(ValueError):
            self.execute(lambda: 0, times=0)
        with pytest.raises(ValueError):
            self.execute(lambda: 0, times=-1)
        with pytest.raises(ValueError):
            self.execute(lambda: 0, warmup_times=-1)
        with pytest.raises(ValueError):
            self.execute(lambda: 0, tolerance=-1)
        with pytest.raises(ValueError):
            self.execute(lambda: 0, retries=-1)

    @retry_on_failure()
    @pytest.mark.skipif(CI_TESTING, reason="skipped on CI")
    @pytest.mark.skipif(COVERAGE, reason="skipped during test coverage")
    def test_leak_mem(self):
        ls = []

        def fun(ls=ls):
            ls.append("x" * 248 * 1024)

        try:
            # will consume around 60M in total
            with pytest.raises(AssertionError, match="extra-mem"):
                self.execute(fun, times=100)
        finally:
            del ls

    def test_unclosed_files(self):
        def fun():
            f = open(__file__)
            self.addCleanup(f.close)
            box.append(f)

        box = []
        kind = "fd" if POSIX else "handle"
        with pytest.raises(AssertionError, match="unclosed " + kind):
            self.execute(fun)

    def test_tolerance(self):
        def fun():
            ls.append("x" * 24 * 1024)

        ls = []
        times = 100
        self.execute(
            fun, times=times, warmup_times=0, tolerance=200 * 1024 * 1024
        )
        assert len(ls) == times + 1

    def test_execute_w_exc(self):
        def fun_1():
            1 / 0  # noqa

        self.execute_w_exc(ZeroDivisionError, fun_1)
        with pytest.raises(ZeroDivisionError):
            self.execute_w_exc(OSError, fun_1)

        def fun_2():
            pass

        with pytest.raises(AssertionError):
            self.execute_w_exc(ZeroDivisionError, fun_2)


class TestFakePytest(PsutilTestCase):
    def run_test_class(self, klass):
        suite = unittest.TestSuite()
        suite.addTest(klass)
        runner = unittest.TextTestRunner()
        result = runner.run(suite)
        return result

    def test_raises(self):
        with fake_pytest.raises(ZeroDivisionError) as cm:
            1 / 0  # noqa
        assert isinstance(cm.value, ZeroDivisionError)

        with fake_pytest.raises(ValueError, match="foo") as cm:
            raise ValueError("foo")

        try:
            with fake_pytest.raises(ValueError, match="foo") as cm:
                raise ValueError("bar")
        except AssertionError as err:
            assert str(err) == '"foo" does not match "bar"'
        else:
            raise self.fail("exception not raised")

    def test_mark(self):
        @fake_pytest.mark.xdist_group(name="serial")
        def foo():
            return 1

        assert foo() == 1

        @fake_pytest.mark.xdist_group(name="serial")
        class Foo:
            def bar(self):
                return 1

        assert Foo().bar() == 1

    def test_skipif(self):
        class TestCase(unittest.TestCase):
            @fake_pytest.mark.skipif(True, reason="reason")
            def foo(self):
                assert 1 == 1  # noqa

        result = self.run_test_class(TestCase("foo"))
        assert result.wasSuccessful()
        assert len(result.skipped) == 1
        assert result.skipped[0][1] == "reason"

        class TestCase(unittest.TestCase):
            @fake_pytest.mark.skipif(False, reason="reason")
            def foo(self):
                assert 1 == 1  # noqa

        result = self.run_test_class(TestCase("foo"))
        assert result.wasSuccessful()
        assert len(result.skipped) == 0

    @pytest.mark.skipif(not PY3, reason="not PY3")
    def test_skip(self):
        class TestCase(unittest.TestCase):
            def foo(self):
                fake_pytest.skip("reason")
                assert 1 == 0  # noqa

        result = self.run_test_class(TestCase("foo"))
        assert result.wasSuccessful()
        assert len(result.skipped) == 1
        assert result.skipped[0][1] == "reason"

    def test_main(self):
        tmpdir = self.get_testfn(dir=HERE)
        os.mkdir(tmpdir)
        with open(os.path.join(tmpdir, "__init__.py"), "w"):
            pass
        with open(os.path.join(tmpdir, "test_file.py"), "w") as f:
            f.write(textwrap.dedent("""\
                import unittest

                class TestCase(unittest.TestCase):
                    def test_passed(self):
                        pass
                """).lstrip())
        with mock.patch.object(psutil.tests, "HERE", tmpdir):
            with self.assertWarnsRegex(
                UserWarning, "Fake pytest module was used"
            ):
                suite = fake_pytest.main()
                assert suite.countTestCases() == 1

    def test_warns(self):
        # success
        with fake_pytest.warns(UserWarning):
            warnings.warn("foo", UserWarning, stacklevel=1)

        # failure
        try:
            with fake_pytest.warns(UserWarning):
                warnings.warn("foo", DeprecationWarning, stacklevel=1)
        except AssertionError:
            pass
        else:
            raise self.fail("exception not raised")

        # match success
        with fake_pytest.warns(UserWarning, match="foo"):
            warnings.warn("foo", UserWarning, stacklevel=1)

        # match failure
        try:
            with fake_pytest.warns(UserWarning, match="foo"):
                warnings.warn("bar", UserWarning, stacklevel=1)
        except AssertionError:
            pass
        else:
            raise self.fail("exception not raised")


class TestTestingUtils(PsutilTestCase):
    def test_process_namespace(self):
        p = psutil.Process()
        ns = process_namespace(p)
        ns.test()
        fun = [x for x in ns.iter(ns.getters) if x[1] == 'ppid'][0][0]
        assert fun() == p.ppid()

    def test_system_namespace(self):
        ns = system_namespace()
        fun = [x for x in ns.iter(ns.getters) if x[1] == 'net_if_addrs'][0][0]
        assert fun() == psutil.net_if_addrs()


class TestOtherUtils(PsutilTestCase):
    def test_is_namedtuple(self):
        assert is_namedtuple(collections.namedtuple('foo', 'a b c')(1, 2, 3))
        assert not is_namedtuple(tuple())
PKok\�c�;1;1psutil/tests/test_unicode.pynu�[���#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""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.cwd()
* Process.environ()
* Process.exe()
* Process.memory_maps()
* Process.name()
* Process.net_connections('unix')
* 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
"""

import os
import shutil
import traceback
import warnings
from contextlib import closing

import psutil
from psutil import BSD
from psutil import POSIX
from psutil import WINDOWS
from psutil._compat import PY3
from psutil._compat import super
from psutil.tests import APPVEYOR
from psutil.tests import ASCII_FS
from psutil.tests import CI_TESTING
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_NET_CONNECTIONS_UNIX
from psutil.tests import INVALID_UNICODE_SUFFIX
from psutil.tests import PYPY
from psutil.tests import TESTFN_PREFIX
from psutil.tests import UNICODE_SUFFIX
from psutil.tests import PsutilTestCase
from psutil.tests import bind_unix_socket
from psutil.tests import chdir
from psutil.tests import copyload_shared_lib
from psutil.tests import create_py_exe
from psutil.tests import get_testfn
from psutil.tests import pytest
from psutil.tests import safe_mkdir
from psutil.tests import safe_rmpath
from psutil.tests import skip_on_access_denied
from psutil.tests import spawn_testproc
from psutil.tests import terminate


if APPVEYOR:

    def safe_rmpath(path):  # NOQA
        # TODO - this is quite random and I'm not sure why it happens,
        # nor I can reproduce it locally:
        # https://ci.appveyor.com/project/giampaolo/psutil/build/job/
        #     jiq2cgd6stsbtn60
        # safe_rmpath() happens after reap_children() so this is weird
        # Perhaps wait_procs() on Windows is broken? Maybe because
        # of STILL_ACTIVE?
        # https://github.com/giampaolo/psutil/blob/
        #     68c7a70728a31d8b8b58f4be6c4c0baa2f449eda/psutil/arch/
        #     windows/process_info.c#L146
        from psutil.tests import safe_rmpath as rm

        try:
            return rm(path)
        except WindowsError:
            traceback.print_exc()


def try_unicode(suffix):
    """Return True if both the fs and the subprocess module can
    deal with a unicode file name.
    """
    sproc = None
    testfn = get_testfn(suffix=suffix)
    try:
        safe_rmpath(testfn)
        create_py_exe(testfn)
        sproc = spawn_testproc(cmd=[testfn])
        shutil.copyfile(testfn, testfn + '-2')
        safe_rmpath(testfn + '-2')
    except (UnicodeEncodeError, IOError):
        return False
    else:
        return True
    finally:
        if sproc is not None:
            terminate(sproc)
        safe_rmpath(testfn)


# ===================================================================
# FS APIs
# ===================================================================


class BaseUnicodeTest(PsutilTestCase):
    funky_suffix = None

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.skip_tests = False
        cls.funky_name = None
        if cls.funky_suffix is not None:
            if not try_unicode(cls.funky_suffix):
                cls.skip_tests = True
            else:
                cls.funky_name = get_testfn(suffix=cls.funky_suffix)
                create_py_exe(cls.funky_name)

    def setUp(self):
        super().setUp()
        if self.skip_tests:
            raise pytest.skip("can't handle unicode str")


@pytest.mark.xdist_group(name="serial")
@pytest.mark.skipif(ASCII_FS, reason="ASCII fs")
@pytest.mark.skipif(PYPY and not PY3, reason="too much trouble on PYPY2")
class TestFSAPIs(BaseUnicodeTest):
    """Test FS APIs with a funky, valid, UTF8 path name."""

    funky_suffix = UNICODE_SUFFIX

    def expect_exact_path_match(self):
        # Do not expect psutil to correctly handle unicode paths on
        # Python 2 if os.listdir() is not able either.
        here = '.' if isinstance(self.funky_name, str) else u'.'
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            return self.funky_name in os.listdir(here)

    # ---

    def test_proc_exe(self):
        cmd = [
            self.funky_name,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        subp = self.spawn_testproc(cmd)
        p = psutil.Process(subp.pid)
        exe = p.exe()
        assert isinstance(exe, str)
        if self.expect_exact_path_match():
            assert os.path.normcase(exe) == os.path.normcase(self.funky_name)

    def test_proc_name(self):
        cmd = [
            self.funky_name,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        subp = self.spawn_testproc(cmd)
        name = psutil.Process(subp.pid).name()
        assert isinstance(name, str)
        if self.expect_exact_path_match():
            assert name == os.path.basename(self.funky_name)

    def test_proc_cmdline(self):
        cmd = [
            self.funky_name,
            "-c",
            "import time; [time.sleep(0.1) for x in range(100)]",
        ]
        subp = self.spawn_testproc(cmd)
        p = psutil.Process(subp.pid)
        cmdline = p.cmdline()
        for part in cmdline:
            assert isinstance(part, str)
        if self.expect_exact_path_match():
            assert cmdline == cmd

    def test_proc_cwd(self):
        dname = self.funky_name + "2"
        self.addCleanup(safe_rmpath, dname)
        safe_mkdir(dname)
        with chdir(dname):
            p = psutil.Process()
            cwd = p.cwd()
        assert isinstance(p.cwd(), str)
        if self.expect_exact_path_match():
            assert cwd == dname

    @pytest.mark.skipif(PYPY and WINDOWS, reason="fails on PYPY + WINDOWS")
    def test_proc_open_files(self):
        p = psutil.Process()
        start = set(p.open_files())
        with open(self.funky_name, 'rb'):
            new = set(p.open_files())
        path = (new - start).pop().path
        assert isinstance(path, str)
        if BSD and not path:
            # XXX - see https://github.com/giampaolo/psutil/issues/595
            raise pytest.skip("open_files on BSD is broken")
        if self.expect_exact_path_match():
            assert os.path.normcase(path) == os.path.normcase(self.funky_name)

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    def test_proc_net_connections(self):
        name = self.get_testfn(suffix=self.funky_suffix)
        try:
            sock = bind_unix_socket(name)
        except UnicodeEncodeError:
            if PY3:
                raise
            else:
                raise pytest.skip("not supported")
        with closing(sock):
            conn = psutil.Process().net_connections('unix')[0]
            assert isinstance(conn.laddr, str)
            assert conn.laddr == name

    @pytest.mark.skipif(not POSIX, reason="POSIX only")
    @pytest.mark.skipif(
        not HAS_NET_CONNECTIONS_UNIX, reason="can't list UNIX sockets"
    )
    @skip_on_access_denied()
    def test_net_connections(self):
        def find_sock(cons):
            for conn in cons:
                if os.path.basename(conn.laddr).startswith(TESTFN_PREFIX):
                    return conn
            raise ValueError("connection not found")

        name = self.get_testfn(suffix=self.funky_suffix)
        try:
            sock = bind_unix_socket(name)
        except UnicodeEncodeError:
            if PY3:
                raise
            else:
                raise pytest.skip("not supported")
        with closing(sock):
            cons = psutil.net_connections(kind='unix')
            conn = find_sock(cons)
            assert isinstance(conn.laddr, str)
            assert conn.laddr == name

    def test_disk_usage(self):
        dname = self.funky_name + "2"
        self.addCleanup(safe_rmpath, dname)
        safe_mkdir(dname)
        psutil.disk_usage(dname)

    @pytest.mark.skipif(not HAS_MEMORY_MAPS, reason="not supported")
    @pytest.mark.skipif(
        not PY3, reason="ctypes does not support unicode on PY2"
    )
    @pytest.mark.skipif(PYPY, reason="unstable on PYPY")
    def test_memory_maps(self):
        # XXX: on Python 2, using ctypes.CDLL with a unicode path
        # opens a message box which blocks the test run.
        with copyload_shared_lib(suffix=self.funky_suffix) as funky_path:

            def normpath(p):
                return os.path.realpath(os.path.normcase(p))

            libpaths = [
                normpath(x.path) for x in psutil.Process().memory_maps()
            ]
            # ...just to have a clearer msg in case of failure
            libpaths = [x for x in libpaths if TESTFN_PREFIX in x]
            assert normpath(funky_path) in libpaths
            for path in libpaths:
                assert isinstance(path, str)


@pytest.mark.skipif(CI_TESTING, reason="unreliable on CI")
class TestFSAPIsWithInvalidPath(TestFSAPIs):
    """Test FS APIs with a funky, invalid path name."""

    funky_suffix = INVALID_UNICODE_SUFFIX

    def expect_exact_path_match(self):
        # Invalid unicode names are supposed to work on Python 2.
        return True


# ===================================================================
# Non fs APIs
# ===================================================================


class TestNonFSAPIS(BaseUnicodeTest):
    """Unicode tests for non fs-related APIs."""

    funky_suffix = UNICODE_SUFFIX if PY3 else 'è'

    @pytest.mark.skipif(not HAS_ENVIRON, reason="not supported")
    @pytest.mark.skipif(PYPY and WINDOWS, reason="segfaults on PYPY + WINDOWS")
    def test_proc_environ(self):
        # Note: differently from others, this test does not deal
        # with fs paths. On Python 2 subprocess module is broken as
        # it's not able to handle with non-ASCII env vars, so
        # we use "è", which is part of the extended ASCII table
        # (unicode point <= 255).
        env = os.environ.copy()
        env['FUNNY_ARG'] = self.funky_suffix
        sproc = self.spawn_testproc(env=env)
        p = psutil.Process(sproc.pid)
        env = p.environ()
        for k, v in env.items():
            assert isinstance(k, str)
            assert isinstance(v, str)
        assert env['FUNNY_ARG'] == self.funky_suffix
PKok\�μ[d[dpsutil/tests/test_linux.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Linux specific tests."""

from __future__ import division

import collections
import contextlib
import errno
import glob
import io
import os
import re
import shutil
import socket
import struct
import textwrap
import time
import warnings

import psutil
from psutil import LINUX
from psutil._compat import PY3
from psutil._compat import FileNotFoundError
from psutil._compat import basestring
from psutil.tests import AARCH64
from psutil.tests import GITHUB_ACTIONS
from psutil.tests import GLOBAL_TIMEOUT
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_GETLOADAVG
from psutil.tests import HAS_RLIMIT
from psutil.tests import PYPY
from psutil.tests import PYTEST_PARALLEL
from psutil.tests import QEMU_USER
from psutil.tests import TOLERANCE_DISK_USAGE
from psutil.tests import TOLERANCE_SYS_MEM
from psutil.tests import PsutilTestCase
from psutil.tests import ThreadTask
from psutil.tests import call_until
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import reload_module
from psutil.tests import retry_on_failure
from psutil.tests import safe_rmpath
from psutil.tests import sh
from psutil.tests import skip_on_not_implemented
from psutil.tests import which


if LINUX:
    from psutil._pslinux import CLOCK_TICKS
    from psutil._pslinux import RootFsDeviceFinder
    from psutil._pslinux import calculate_avail_vmem
    from psutil._pslinux import open_binary


HERE = os.path.abspath(os.path.dirname(__file__))
SIOCGIFADDR = 0x8915
SIOCGIFCONF = 0x8912
SIOCGIFHWADDR = 0x8927
SIOCGIFNETMASK = 0x891B
SIOCGIFBRDADDR = 0x8919
if LINUX:
    SECTOR_SIZE = 512
EMPTY_TEMPERATURES = not glob.glob('/sys/class/hwmon/hwmon*')


# =====================================================================
# --- utils
# =====================================================================


def get_ipv4_address(ifname):
    import fcntl

    ifname = ifname[:15]
    if PY3:
        ifname = bytes(ifname, 'ascii')
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    with contextlib.closing(s):
        return socket.inet_ntoa(
            fcntl.ioctl(s.fileno(), SIOCGIFADDR, struct.pack('256s', ifname))[
                20:24
            ]
        )


def get_ipv4_netmask(ifname):
    import fcntl

    ifname = ifname[:15]
    if PY3:
        ifname = bytes(ifname, 'ascii')
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    with contextlib.closing(s):
        return socket.inet_ntoa(
            fcntl.ioctl(
                s.fileno(), SIOCGIFNETMASK, struct.pack('256s', ifname)
            )[20:24]
        )


def get_ipv4_broadcast(ifname):
    import fcntl

    ifname = ifname[:15]
    if PY3:
        ifname = bytes(ifname, 'ascii')
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    with contextlib.closing(s):
        return socket.inet_ntoa(
            fcntl.ioctl(
                s.fileno(), SIOCGIFBRDADDR, struct.pack('256s', ifname)
            )[20:24]
        )


def get_ipv6_addresses(ifname):
    with open("/proc/net/if_inet6") as f:
        all_fields = []
        for line in f:
            fields = line.split()
            if fields[-1] == ifname:
                all_fields.append(fields)

        if len(all_fields) == 0:
            raise ValueError("could not find interface %r" % ifname)

    for i in range(len(all_fields)):
        unformatted = all_fields[i][0]
        groups = []
        for j in range(0, len(unformatted), 4):
            groups.append(unformatted[j : j + 4])
        formatted = ":".join(groups)
        packed = socket.inet_pton(socket.AF_INET6, formatted)
        all_fields[i] = socket.inet_ntop(socket.AF_INET6, packed)
    return all_fields


def get_mac_address(ifname):
    import fcntl

    ifname = ifname[:15]
    if PY3:
        ifname = bytes(ifname, 'ascii')
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    with contextlib.closing(s):
        info = fcntl.ioctl(
            s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname)
        )
        if PY3:

            def ord(x):
                return x

        else:
            import __builtin__

            ord = __builtin__.ord
        return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]


def free_swap():
    """Parse 'free' cmd and return swap memory's s total, used and free
    values.
    """
    out = sh(["free", "-b"], env={"LANG": "C.UTF-8"})
    lines = out.split('\n')
    for line in lines:
        if line.startswith('Swap'):
            _, total, used, free = line.split()
            nt = collections.namedtuple('free', 'total used free')
            return nt(int(total), int(used), int(free))
    raise ValueError(
        "can't find 'Swap' in 'free' output:\n%s" % '\n'.join(lines)
    )


def free_physmem():
    """Parse 'free' cmd and return physical memory's total, used
    and free values.
    """
    # Note: free can have 2 different formats, invalidating 'shared'
    # and 'cached' memory which may have different positions so we
    # do not return them.
    # https://github.com/giampaolo/psutil/issues/538#issuecomment-57059946
    out = sh(["free", "-b"], env={"LANG": "C.UTF-8"})
    lines = out.split('\n')
    for line in lines:
        if line.startswith('Mem'):
            total, used, free, shared = (int(x) for x in line.split()[1:5])
            nt = collections.namedtuple(
                'free', 'total used free shared output'
            )
            return nt(total, used, free, shared, out)
    raise ValueError(
        "can't find 'Mem' in 'free' output:\n%s" % '\n'.join(lines)
    )


def vmstat(stat):
    out = sh(["vmstat", "-s"], env={"LANG": "C.UTF-8"})
    for line in out.split("\n"):
        line = line.strip()
        if stat in line:
            return int(line.split(' ')[0])
    raise ValueError("can't find %r in 'vmstat' output" % stat)


def get_free_version_info():
    out = sh(["free", "-V"]).strip()
    if 'UNKNOWN' in out:
        raise pytest.skip("can't determine free version")
    return tuple(map(int, re.findall(r'\d+', out.split()[-1])))


@contextlib.contextmanager
def mock_open_content(pairs):
    """Mock open() builtin and forces it to return a certain content
    for a given path. `pairs` is a {"path": "content", ...} dict.
    """

    def open_mock(name, *args, **kwargs):
        if name in pairs:
            content = pairs[name]
            if PY3:
                if isinstance(content, basestring):
                    return io.StringIO(content)
                else:
                    return io.BytesIO(content)
            else:
                return io.BytesIO(content)
        else:
            return orig_open(name, *args, **kwargs)

    orig_open = open
    patch_point = 'builtins.open' if PY3 else '__builtin__.open'
    with mock.patch(patch_point, create=True, side_effect=open_mock) as m:
        yield m


@contextlib.contextmanager
def mock_open_exception(for_path, exc):
    """Mock open() builtin and raises `exc` if the path being opened
    matches `for_path`.
    """

    def open_mock(name, *args, **kwargs):
        if name == for_path:
            raise exc
        else:
            return orig_open(name, *args, **kwargs)

    orig_open = open
    patch_point = 'builtins.open' if PY3 else '__builtin__.open'
    with mock.patch(patch_point, create=True, side_effect=open_mock) as m:
        yield m


# =====================================================================
# --- system virtual memory
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemVirtualMemoryAgainstFree(PsutilTestCase):
    def test_total(self):
        cli_value = free_physmem().total
        psutil_value = psutil.virtual_memory().total
        assert cli_value == psutil_value

    @retry_on_failure()
    def test_used(self):
        # Older versions of procps used slab memory to calculate used memory.
        # This got changed in:
        # https://gitlab.com/procps-ng/procps/commit/
        #     05d751c4f076a2f0118b914c5e51cfbb4762ad8e
        # Newer versions of procps are using yet another way to compute used
        # memory.
        # https://gitlab.com/procps-ng/procps/commit/
        #     2184e90d2e7cdb582f9a5b706b47015e56707e4d
        if get_free_version_info() < (3, 3, 12):
            raise pytest.skip("free version too old")
        if get_free_version_info() >= (4, 0, 0):
            raise pytest.skip("free version too recent")
        cli_value = free_physmem().used
        psutil_value = psutil.virtual_memory().used
        assert abs(cli_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_free(self):
        cli_value = free_physmem().free
        psutil_value = psutil.virtual_memory().free
        assert abs(cli_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_shared(self):
        free = free_physmem()
        free_value = free.shared
        if free_value == 0:
            raise pytest.skip("free does not support 'shared' column")
        psutil_value = psutil.virtual_memory().shared
        assert (
            abs(free_value - psutil_value) < TOLERANCE_SYS_MEM
        ), '%s %s \n%s' % (free_value, psutil_value, free.output)

    @retry_on_failure()
    def test_available(self):
        # "free" output format has changed at some point:
        # https://github.com/giampaolo/psutil/issues/538#issuecomment-147192098
        out = sh(["free", "-b"])
        lines = out.split('\n')
        if 'available' not in lines[0]:
            raise pytest.skip("free does not support 'available' column")
        else:
            free_value = int(lines[1].split()[-1])
            psutil_value = psutil.virtual_memory().available
            assert (
                abs(free_value - psutil_value) < TOLERANCE_SYS_MEM
            ), '%s %s \n%s' % (free_value, psutil_value, out)


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemVirtualMemoryAgainstVmstat(PsutilTestCase):
    def test_total(self):
        vmstat_value = vmstat('total memory') * 1024
        psutil_value = psutil.virtual_memory().total
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_used(self):
        # Older versions of procps used slab memory to calculate used memory.
        # This got changed in:
        # https://gitlab.com/procps-ng/procps/commit/
        #     05d751c4f076a2f0118b914c5e51cfbb4762ad8e
        # Newer versions of procps are using yet another way to compute used
        # memory.
        # https://gitlab.com/procps-ng/procps/commit/
        #     2184e90d2e7cdb582f9a5b706b47015e56707e4d
        if get_free_version_info() < (3, 3, 12):
            raise pytest.skip("free version too old")
        if get_free_version_info() >= (4, 0, 0):
            raise pytest.skip("free version too recent")
        vmstat_value = vmstat('used memory') * 1024
        psutil_value = psutil.virtual_memory().used
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_free(self):
        vmstat_value = vmstat('free memory') * 1024
        psutil_value = psutil.virtual_memory().free
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_buffers(self):
        vmstat_value = vmstat('buffer memory') * 1024
        psutil_value = psutil.virtual_memory().buffers
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_active(self):
        vmstat_value = vmstat('active memory') * 1024
        psutil_value = psutil.virtual_memory().active
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_inactive(self):
        vmstat_value = vmstat('inactive memory') * 1024
        psutil_value = psutil.virtual_memory().inactive
        assert abs(vmstat_value - psutil_value) < TOLERANCE_SYS_MEM


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemVirtualMemoryMocks(PsutilTestCase):
    def test_warnings_on_misses(self):
        # Emulate a case where /proc/meminfo provides few info.
        # psutil is supposed to set the missing fields to 0 and
        # raise a warning.
        content = textwrap.dedent("""\
            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemAvailable:         -1 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            SReclaimable:     346648 kB
            """).encode()
        with mock_open_content({'/proc/meminfo': content}) as m:
            with warnings.catch_warnings(record=True) as ws:
                warnings.simplefilter("always")
                ret = psutil.virtual_memory()
                assert m.called
                assert len(ws) == 1
                w = ws[0]
                assert "memory stats couldn't be determined" in str(w.message)
                assert "cached" in str(w.message)
                assert "shared" in str(w.message)
                assert "active" in str(w.message)
                assert "inactive" in str(w.message)
                assert "buffers" in str(w.message)
                assert "available" in str(w.message)
                assert ret.cached == 0
                assert ret.active == 0
                assert ret.inactive == 0
                assert ret.shared == 0
                assert ret.buffers == 0
                assert ret.available == 0
                assert ret.slab == 0

    @retry_on_failure()
    def test_avail_old_percent(self):
        # Make sure that our calculation of avail mem for old kernels
        # is off by max 15%.
        mems = {}
        with open_binary('/proc/meminfo') as f:
            for line in f:
                fields = line.split()
                mems[fields[0]] = int(fields[1]) * 1024

        a = calculate_avail_vmem(mems)
        if b'MemAvailable:' in mems:
            b = mems[b'MemAvailable:']
            diff_percent = abs(a - b) / a * 100
            assert diff_percent < 15

    def test_avail_old_comes_from_kernel(self):
        # Make sure "MemAvailable:" coluimn is used instead of relying
        # on our internal algorithm to calculate avail mem.
        content = textwrap.dedent("""\
            Active:          9444728 kB
            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemAvailable:    6574984 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            SReclaimable:     346648 kB
            """).encode()
        with mock_open_content({'/proc/meminfo': content}) as m:
            with warnings.catch_warnings(record=True) as ws:
                ret = psutil.virtual_memory()
            assert m.called
            assert ret.available == 6574984 * 1024
            w = ws[0]
            assert "inactive memory stats couldn't be determined" in str(
                w.message
            )

    def test_avail_old_missing_fields(self):
        # Remove Active(file), Inactive(file) and SReclaimable
        # from /proc/meminfo and make sure the fallback is used
        # (free + cached),
        content = textwrap.dedent("""\
            Active:          9444728 kB
            Active(anon):    6145416 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            """).encode()
        with mock_open_content({"/proc/meminfo": content}) as m:
            with warnings.catch_warnings(record=True) as ws:
                ret = psutil.virtual_memory()
            assert m.called
            assert ret.available == 2057400 * 1024 + 4818144 * 1024
            w = ws[0]
            assert "inactive memory stats couldn't be determined" in str(
                w.message
            )

    def test_avail_old_missing_zoneinfo(self):
        # Remove /proc/zoneinfo file. Make sure fallback is used
        # (free + cached).
        content = textwrap.dedent("""\
            Active:          9444728 kB
            Active(anon):    6145416 kB
            Active(file):    2950064 kB
            Buffers:          287952 kB
            Cached:          4818144 kB
            Inactive(file):  1578132 kB
            Inactive(anon):   574764 kB
            Inactive(file):  1567648 kB
            MemFree:         2057400 kB
            MemTotal:       16325648 kB
            Shmem:            577588 kB
            SReclaimable:     346648 kB
            """).encode()
        with mock_open_content({"/proc/meminfo": content}):
            with mock_open_exception(
                "/proc/zoneinfo",
                IOError(errno.ENOENT, 'no such file or directory'),
            ):
                with warnings.catch_warnings(record=True) as ws:
                    ret = psutil.virtual_memory()
                    assert ret.available == 2057400 * 1024 + 4818144 * 1024
                    w = ws[0]
                    assert (
                        "inactive memory stats couldn't be determined"
                        in str(w.message)
                    )

    def test_virtual_memory_mocked(self):
        # Emulate /proc/meminfo because neither vmstat nor free return slab.
        content = textwrap.dedent("""\
            MemTotal:              100 kB
            MemFree:               2 kB
            MemAvailable:          3 kB
            Buffers:               4 kB
            Cached:                5 kB
            SwapCached:            6 kB
            Active:                7 kB
            Inactive:              8 kB
            Active(anon):          9 kB
            Inactive(anon):        10 kB
            Active(file):          11 kB
            Inactive(file):        12 kB
            Unevictable:           13 kB
            Mlocked:               14 kB
            SwapTotal:             15 kB
            SwapFree:              16 kB
            Dirty:                 17 kB
            Writeback:             18 kB
            AnonPages:             19 kB
            Mapped:                20 kB
            Shmem:                 21 kB
            Slab:                  22 kB
            SReclaimable:          23 kB
            SUnreclaim:            24 kB
            KernelStack:           25 kB
            PageTables:            26 kB
            NFS_Unstable:          27 kB
            Bounce:                28 kB
            WritebackTmp:          29 kB
            CommitLimit:           30 kB
            Committed_AS:          31 kB
            VmallocTotal:          32 kB
            VmallocUsed:           33 kB
            VmallocChunk:          34 kB
            HardwareCorrupted:     35 kB
            AnonHugePages:         36 kB
            ShmemHugePages:        37 kB
            ShmemPmdMapped:        38 kB
            CmaTotal:              39 kB
            CmaFree:               40 kB
            HugePages_Total:       41 kB
            HugePages_Free:        42 kB
            HugePages_Rsvd:        43 kB
            HugePages_Surp:        44 kB
            Hugepagesize:          45 kB
            DirectMap46k:          46 kB
            DirectMap47M:          47 kB
            DirectMap48G:          48 kB
            """).encode()
        with mock_open_content({"/proc/meminfo": content}) as m:
            mem = psutil.virtual_memory()
            assert m.called
            assert mem.total == 100 * 1024
            assert mem.free == 2 * 1024
            assert mem.buffers == 4 * 1024
            # cached mem also includes reclaimable memory
            assert mem.cached == (5 + 23) * 1024
            assert mem.shared == 21 * 1024
            assert mem.active == 7 * 1024
            assert mem.inactive == 8 * 1024
            assert mem.slab == 22 * 1024
            assert mem.available == 3 * 1024


# =====================================================================
# --- system swap memory
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemSwapMemory(PsutilTestCase):
    @staticmethod
    def meminfo_has_swap_info():
        """Return True if /proc/meminfo provides swap metrics."""
        with open("/proc/meminfo") as f:
            data = f.read()
        return 'SwapTotal:' in data and 'SwapFree:' in data

    def test_total(self):
        free_value = free_swap().total
        psutil_value = psutil.swap_memory().total
        assert abs(free_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_used(self):
        free_value = free_swap().used
        psutil_value = psutil.swap_memory().used
        assert abs(free_value - psutil_value) < TOLERANCE_SYS_MEM

    @retry_on_failure()
    def test_free(self):
        free_value = free_swap().free
        psutil_value = psutil.swap_memory().free
        assert abs(free_value - psutil_value) < TOLERANCE_SYS_MEM

    def test_missing_sin_sout(self):
        with mock.patch('psutil._common.open', create=True) as m:
            with warnings.catch_warnings(record=True) as ws:
                warnings.simplefilter("always")
                ret = psutil.swap_memory()
                assert m.called
                assert len(ws) == 1
                w = ws[0]
                assert (
                    "'sin' and 'sout' swap memory stats couldn't be determined"
                    in str(w.message)
                )
                assert ret.sin == 0
                assert ret.sout == 0

    def test_no_vmstat_mocked(self):
        # see https://github.com/giampaolo/psutil/issues/722
        with mock_open_exception(
            "/proc/vmstat", IOError(errno.ENOENT, 'no such file or directory')
        ) as m:
            with warnings.catch_warnings(record=True) as ws:
                warnings.simplefilter("always")
                ret = psutil.swap_memory()
                assert m.called
                assert len(ws) == 1
                w = ws[0]
                assert (
                    "'sin' and 'sout' swap memory stats couldn't "
                    "be determined and were set to 0"
                    in str(w.message)
                )
                assert ret.sin == 0
                assert ret.sout == 0

    def test_meminfo_against_sysinfo(self):
        # Make sure the content of /proc/meminfo about swap memory
        # matches sysinfo() syscall, see:
        # https://github.com/giampaolo/psutil/issues/1015
        if not self.meminfo_has_swap_info():
            raise pytest.skip("/proc/meminfo has no swap metrics")
        with mock.patch('psutil._pslinux.cext.linux_sysinfo') as m:
            swap = psutil.swap_memory()
        assert not m.called
        import psutil._psutil_linux as cext

        _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo()
        total *= unit_multiplier
        free *= unit_multiplier
        assert swap.total == total
        assert abs(swap.free - free) < TOLERANCE_SYS_MEM

    def test_emulate_meminfo_has_no_metrics(self):
        # Emulate a case where /proc/meminfo provides no swap metrics
        # in which case sysinfo() syscall is supposed to be used
        # as a fallback.
        with mock_open_content({"/proc/meminfo": b""}) as m:
            psutil.swap_memory()
            assert m.called


# =====================================================================
# --- system CPU
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemCPUTimes(PsutilTestCase):
    def test_fields(self):
        fields = psutil.cpu_times()._fields
        kernel_ver = re.findall(r'\d+\.\d+\.\d+', os.uname()[2])[0]
        kernel_ver_info = tuple(map(int, kernel_ver.split('.')))
        if kernel_ver_info >= (2, 6, 11):
            assert 'steal' in fields
        else:
            assert 'steal' not in fields
        if kernel_ver_info >= (2, 6, 24):
            assert 'guest' in fields
        else:
            assert 'guest' not in fields
        if kernel_ver_info >= (3, 2, 0):
            assert 'guest_nice' in fields
        else:
            assert 'guest_nice' not in fields


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemCPUCountLogical(PsutilTestCase):
    @pytest.mark.skipif(
        not os.path.exists("/sys/devices/system/cpu/online"),
        reason="/sys/devices/system/cpu/online does not exist",
    )
    def test_against_sysdev_cpu_online(self):
        with open("/sys/devices/system/cpu/online") as f:
            value = f.read().strip()
        if "-" in str(value):
            value = int(value.split('-')[1]) + 1
            assert psutil.cpu_count() == value

    @pytest.mark.skipif(
        not os.path.exists("/sys/devices/system/cpu"),
        reason="/sys/devices/system/cpu does not exist",
    )
    def test_against_sysdev_cpu_num(self):
        ls = os.listdir("/sys/devices/system/cpu")
        count = len([x for x in ls if re.search(r"cpu\d+$", x) is not None])
        assert psutil.cpu_count() == count

    @pytest.mark.skipif(
        not which("nproc"), reason="nproc utility not available"
    )
    def test_against_nproc(self):
        num = int(sh("nproc --all"))
        assert psutil.cpu_count(logical=True) == num

    @pytest.mark.skipif(
        not which("lscpu"), reason="lscpu utility not available"
    )
    def test_against_lscpu(self):
        out = sh("lscpu -p")
        num = len([x for x in out.split('\n') if not x.startswith('#')])
        assert psutil.cpu_count(logical=True) == num

    def test_emulate_fallbacks(self):
        import psutil._pslinux

        original = psutil._pslinux.cpu_count_logical()
        # Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in
        # order to cause the parsing of /proc/cpuinfo and /proc/stat.
        with mock.patch(
            'psutil._pslinux.os.sysconf', side_effect=ValueError
        ) as m:
            assert psutil._pslinux.cpu_count_logical() == original
            assert m.called

            # Let's have open() return empty data and make sure None is
            # returned ('cause we mimic os.cpu_count()).
            with mock.patch('psutil._common.open', create=True) as m:
                assert psutil._pslinux.cpu_count_logical() is None
                assert m.call_count == 2
                # /proc/stat should be the last one
                assert m.call_args[0][0] == '/proc/stat'

            # Let's push this a bit further and make sure /proc/cpuinfo
            # parsing works as expected.
            with open('/proc/cpuinfo', 'rb') as f:
                cpuinfo_data = f.read()
            fake_file = io.BytesIO(cpuinfo_data)
            with mock.patch(
                'psutil._common.open', return_value=fake_file, create=True
            ) as m:
                assert psutil._pslinux.cpu_count_logical() == original

            # Finally, let's make /proc/cpuinfo return meaningless data;
            # this way we'll fall back on relying on /proc/stat
            with mock_open_content({"/proc/cpuinfo": b""}) as m:
                assert psutil._pslinux.cpu_count_logical() == original
                assert m.called


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemCPUCountCores(PsutilTestCase):
    @pytest.mark.skipif(
        not which("lscpu"), reason="lscpu utility not available"
    )
    def test_against_lscpu(self):
        out = sh("lscpu -p")
        core_ids = set()
        for line in out.split('\n'):
            if not line.startswith('#'):
                fields = line.split(',')
                core_ids.add(fields[1])
        assert psutil.cpu_count(logical=False) == len(core_ids)

    def test_method_2(self):
        meth_1 = psutil._pslinux.cpu_count_cores()
        with mock.patch('glob.glob', return_value=[]) as m:
            meth_2 = psutil._pslinux.cpu_count_cores()
            assert m.called
        if meth_1 is not None:
            assert meth_1 == meth_2

    def test_emulate_none(self):
        with mock.patch('glob.glob', return_value=[]) as m1:
            with mock.patch('psutil._common.open', create=True) as m2:
                assert psutil._pslinux.cpu_count_cores() is None
        assert m1.called
        assert m2.called


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemCPUFrequency(PsutilTestCase):
    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_emulate_use_second_file(self):
        # https://github.com/giampaolo/psutil/issues/981
        def path_exists_mock(path):
            if path.startswith("/sys/devices/system/cpu/cpufreq/policy"):
                return False
            else:
                return orig_exists(path)

        orig_exists = os.path.exists
        with mock.patch(
            "os.path.exists", side_effect=path_exists_mock, create=True
        ):
            assert psutil.cpu_freq()

    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    @pytest.mark.skipif(
        AARCH64, reason="aarch64 does not report mhz in /proc/cpuinfo"
    )
    def test_emulate_use_cpuinfo(self):
        # Emulate a case where /sys/devices/system/cpu/cpufreq* does not
        # exist and /proc/cpuinfo is used instead.
        def path_exists_mock(path):
            if path.startswith('/sys/devices/system/cpu/'):
                return False
            else:
                return os_path_exists(path)

        os_path_exists = os.path.exists
        try:
            with mock.patch("os.path.exists", side_effect=path_exists_mock):
                reload_module(psutil._pslinux)
                ret = psutil.cpu_freq()
                assert ret, ret
                assert ret.max == 0.0
                assert ret.min == 0.0
                for freq in psutil.cpu_freq(percpu=True):
                    assert freq.max == 0.0
                    assert freq.min == 0.0
        finally:
            reload_module(psutil._pslinux)
            reload_module(psutil)

    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_emulate_data(self):
        def open_mock(name, *args, **kwargs):
            if name.endswith('/scaling_cur_freq') and name.startswith(
                "/sys/devices/system/cpu/cpufreq/policy"
            ):
                return io.BytesIO(b"500000")
            elif name.endswith('/scaling_min_freq') and name.startswith(
                "/sys/devices/system/cpu/cpufreq/policy"
            ):
                return io.BytesIO(b"600000")
            elif name.endswith('/scaling_max_freq') and name.startswith(
                "/sys/devices/system/cpu/cpufreq/policy"
            ):
                return io.BytesIO(b"700000")
            elif name == '/proc/cpuinfo':
                return io.BytesIO(b"cpu MHz     : 500")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            with mock.patch('os.path.exists', return_value=True):
                freq = psutil.cpu_freq()
                assert freq.current == 500.0
                # when /proc/cpuinfo is used min and max frequencies are not
                # available and are set to 0.
                if freq.min != 0.0:
                    assert freq.min == 600.0
                if freq.max != 0.0:
                    assert freq.max == 700.0

    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_emulate_multi_cpu(self):
        def open_mock(name, *args, **kwargs):
            n = name
            if n.endswith('/scaling_cur_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy0"
            ):
                return io.BytesIO(b"100000")
            elif n.endswith('/scaling_min_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy0"
            ):
                return io.BytesIO(b"200000")
            elif n.endswith('/scaling_max_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy0"
            ):
                return io.BytesIO(b"300000")
            elif n.endswith('/scaling_cur_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy1"
            ):
                return io.BytesIO(b"400000")
            elif n.endswith('/scaling_min_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy1"
            ):
                return io.BytesIO(b"500000")
            elif n.endswith('/scaling_max_freq') and n.startswith(
                "/sys/devices/system/cpu/cpufreq/policy1"
            ):
                return io.BytesIO(b"600000")
            elif name == '/proc/cpuinfo':
                return io.BytesIO(b"cpu MHz     : 100\ncpu MHz     : 400")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            with mock.patch('os.path.exists', return_value=True):
                with mock.patch(
                    'psutil._pslinux.cpu_count_logical', return_value=2
                ):
                    freq = psutil.cpu_freq(percpu=True)
                    assert freq[0].current == 100.0
                    if freq[0].min != 0.0:
                        assert freq[0].min == 200.0
                    if freq[0].max != 0.0:
                        assert freq[0].max == 300.0
                    assert freq[1].current == 400.0
                    if freq[1].min != 0.0:
                        assert freq[1].min == 500.0
                    if freq[1].max != 0.0:
                        assert freq[1].max == 600.0

    @pytest.mark.skipif(not HAS_CPU_FREQ, reason="not supported")
    def test_emulate_no_scaling_cur_freq_file(self):
        # See: https://github.com/giampaolo/psutil/issues/1071
        def open_mock(name, *args, **kwargs):
            if name.endswith('/scaling_cur_freq'):
                raise IOError(errno.ENOENT, "")
            elif name.endswith('/cpuinfo_cur_freq'):
                return io.BytesIO(b"200000")
            elif name == '/proc/cpuinfo':
                return io.BytesIO(b"cpu MHz     : 200")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            with mock.patch('os.path.exists', return_value=True):
                with mock.patch(
                    'psutil._pslinux.cpu_count_logical', return_value=1
                ):
                    freq = psutil.cpu_freq()
                    assert freq.current == 200


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemCPUStats(PsutilTestCase):

    # XXX: fails too often.
    # def test_ctx_switches(self):
    #     vmstat_value = vmstat("context switches")
    #     psutil_value = psutil.cpu_stats().ctx_switches
    #     self.assertAlmostEqual(vmstat_value, psutil_value, delta=500)

    def test_interrupts(self):
        vmstat_value = vmstat("interrupts")
        psutil_value = psutil.cpu_stats().interrupts
        assert abs(vmstat_value - psutil_value) < 500


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestLoadAvg(PsutilTestCase):
    @pytest.mark.skipif(not HAS_GETLOADAVG, reason="not supported")
    def test_getloadavg(self):
        psutil_value = psutil.getloadavg()
        with open("/proc/loadavg") as f:
            proc_value = f.read().split()

        assert abs(float(proc_value[0]) - psutil_value[0]) < 1
        assert abs(float(proc_value[1]) - psutil_value[1]) < 1
        assert abs(float(proc_value[2]) - psutil_value[2]) < 1


# =====================================================================
# --- system network
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemNetIfAddrs(PsutilTestCase):
    def test_ips(self):
        for name, addrs in psutil.net_if_addrs().items():
            for addr in addrs:
                if addr.family == psutil.AF_LINK:
                    assert addr.address == get_mac_address(name)
                elif addr.family == socket.AF_INET:
                    assert addr.address == get_ipv4_address(name)
                    assert addr.netmask == get_ipv4_netmask(name)
                    if addr.broadcast is not None:
                        assert addr.broadcast == get_ipv4_broadcast(name)
                    else:
                        assert get_ipv4_broadcast(name) == '0.0.0.0'
                elif addr.family == socket.AF_INET6:
                    # IPv6 addresses can have a percent symbol at the end.
                    # E.g. these 2 are equivalent:
                    # "fe80::1ff:fe23:4567:890a"
                    # "fe80::1ff:fe23:4567:890a%eth0"
                    # That is the "zone id" portion, which usually is the name
                    # of the network interface.
                    address = addr.address.split('%')[0]
                    assert address in get_ipv6_addresses(name)

    # XXX - not reliable when having virtual NICs installed by Docker.
    # @pytest.mark.skipif(not which('ip'), reason="'ip' utility not available")
    # def test_net_if_names(self):
    #     out = sh("ip addr").strip()
    #     nics = [x for x in psutil.net_if_addrs().keys() if ':' not in x]
    #     found = 0
    #     for line in out.split('\n'):
    #         line = line.strip()
    #         if re.search(r"^\d+:", line):
    #             found += 1
    #             name = line.split(':')[1].strip()
    #             self.assertIn(name, nics)
    #     self.assertEqual(len(nics), found, msg="%s\n---\n%s" % (
    #         pprint.pformat(nics), out))


@pytest.mark.skipif(not LINUX, reason="LINUX only")
@pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
class TestSystemNetIfStats(PsutilTestCase):
    @pytest.mark.skipif(
        not which("ifconfig"), reason="ifconfig utility not available"
    )
    def test_against_ifconfig(self):
        for name, stats in psutil.net_if_stats().items():
            try:
                out = sh("ifconfig %s" % name)
            except RuntimeError:
                pass
            else:
                assert stats.isup == ('RUNNING' in out), out
                assert stats.mtu == int(
                    re.findall(r'(?i)MTU[: ](\d+)', out)[0]
                )

    def test_mtu(self):
        for name, stats in psutil.net_if_stats().items():
            with open("/sys/class/net/%s/mtu" % name) as f:
                assert stats.mtu == int(f.read().strip())

    @pytest.mark.skipif(
        not which("ifconfig"), reason="ifconfig utility not available"
    )
    def test_flags(self):
        # first line looks like this:
        # "eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500"
        matches_found = 0
        for name, stats in psutil.net_if_stats().items():
            try:
                out = sh("ifconfig %s" % name)
            except RuntimeError:
                pass
            else:
                match = re.search(r"flags=(\d+)?<(.*?)>", out)
                if match and len(match.groups()) >= 2:
                    matches_found += 1
                    ifconfig_flags = set(match.group(2).lower().split(","))
                    psutil_flags = set(stats.flags.split(","))
                    assert ifconfig_flags == psutil_flags
                else:
                    # ifconfig has a different output on CentOS 6
                    # let's try that
                    match = re.search(r"(.*)  MTU:(\d+)  Metric:(\d+)", out)
                    if match and len(match.groups()) >= 3:
                        matches_found += 1
                        ifconfig_flags = set(match.group(1).lower().split())
                        psutil_flags = set(stats.flags.split(","))
                        assert ifconfig_flags == psutil_flags

        if not matches_found:
            raise self.fail("no matches were found")


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemNetIOCounters(PsutilTestCase):
    @pytest.mark.skipif(
        not which("ifconfig"), reason="ifconfig utility not available"
    )
    @retry_on_failure()
    def test_against_ifconfig(self):
        def ifconfig(nic):
            ret = {}
            out = sh("ifconfig %s" % nic)
            ret['packets_recv'] = int(
                re.findall(r'RX packets[: ](\d+)', out)[0]
            )
            ret['packets_sent'] = int(
                re.findall(r'TX packets[: ](\d+)', out)[0]
            )
            ret['errin'] = int(re.findall(r'errors[: ](\d+)', out)[0])
            ret['errout'] = int(re.findall(r'errors[: ](\d+)', out)[1])
            ret['dropin'] = int(re.findall(r'dropped[: ](\d+)', out)[0])
            ret['dropout'] = int(re.findall(r'dropped[: ](\d+)', out)[1])
            ret['bytes_recv'] = int(
                re.findall(r'RX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]
            )
            ret['bytes_sent'] = int(
                re.findall(r'TX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]
            )
            return ret

        nio = psutil.net_io_counters(pernic=True, nowrap=False)
        for name, stats in nio.items():
            try:
                ifconfig_ret = ifconfig(name)
            except RuntimeError:
                continue
            assert (
                abs(stats.bytes_recv - ifconfig_ret['bytes_recv']) < 1024 * 10
            )
            assert (
                abs(stats.bytes_sent - ifconfig_ret['bytes_sent']) < 1024 * 10
            )
            assert (
                abs(stats.packets_recv - ifconfig_ret['packets_recv']) < 1024
            )
            assert (
                abs(stats.packets_sent - ifconfig_ret['packets_sent']) < 1024
            )
            assert abs(stats.errin - ifconfig_ret['errin']) < 10
            assert abs(stats.errout - ifconfig_ret['errout']) < 10
            assert abs(stats.dropin - ifconfig_ret['dropin']) < 10
            assert abs(stats.dropout - ifconfig_ret['dropout']) < 10


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemNetConnections(PsutilTestCase):
    @mock.patch('psutil._pslinux.socket.inet_ntop', side_effect=ValueError)
    @mock.patch('psutil._pslinux.supports_ipv6', return_value=False)
    def test_emulate_ipv6_unsupported(self, supports_ipv6, inet_ntop):
        # see: https://github.com/giampaolo/psutil/issues/623
        try:
            s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
            self.addCleanup(s.close)
            s.bind(("::1", 0))
        except socket.error:
            pass
        psutil.net_connections(kind='inet6')

    def test_emulate_unix(self):
        content = textwrap.dedent("""\
            0: 00000003 000 000 0001 03 462170 @/tmp/dbus-Qw2hMPIU3n
            0: 00000003 000 000 0001 03 35010 @/tmp/dbus-tB2X8h69BQ
            0: 00000003 000 000 0001 03 34424 @/tmp/dbus-cHy80Y8O
            000000000000000000000000000000000000000000000000000000
            """)
        with mock_open_content({"/proc/net/unix": content}) as m:
            psutil.net_connections(kind='unix')
            assert m.called


# =====================================================================
# --- system disks
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemDiskPartitions(PsutilTestCase):
    @pytest.mark.skipif(
        not hasattr(os, 'statvfs'), reason="os.statvfs() not available"
    )
    @skip_on_not_implemented()
    def test_against_df(self):
        # test psutil.disk_usage() and psutil.disk_partitions()
        # against "df -a"
        def df(path):
            out = sh('df -P -B 1 "%s"' % path).strip()
            lines = out.split('\n')
            lines.pop(0)
            line = lines.pop(0)
            dev, total, used, free = line.split()[:4]
            if dev == 'none':
                dev = ''
            total, used, free = int(total), int(used), int(free)
            return dev, total, used, free

        for part in psutil.disk_partitions(all=False):
            usage = psutil.disk_usage(part.mountpoint)
            _, total, used, free = df(part.mountpoint)
            assert usage.total == total
            assert abs(usage.free - free) < TOLERANCE_DISK_USAGE
            assert abs(usage.used - used) < TOLERANCE_DISK_USAGE

    def test_zfs_fs(self):
        # Test that ZFS partitions are returned.
        with open("/proc/filesystems") as f:
            data = f.read()
        if 'zfs' in data:
            for part in psutil.disk_partitions():
                if part.fstype == 'zfs':
                    break
            else:
                raise self.fail("couldn't find any ZFS partition")
        else:
            # No ZFS partitions on this system. Let's fake one.
            fake_file = io.StringIO(u"nodev\tzfs\n")
            with mock.patch(
                'psutil._common.open', return_value=fake_file, create=True
            ) as m1:
                with mock.patch(
                    'psutil._pslinux.cext.disk_partitions',
                    return_value=[('/dev/sdb3', '/', 'zfs', 'rw')],
                ) as m2:
                    ret = psutil.disk_partitions()
                    assert m1.called
                    assert m2.called
                    assert ret
                    assert ret[0].fstype == 'zfs'

    def test_emulate_realpath_fail(self):
        # See: https://github.com/giampaolo/psutil/issues/1307
        try:
            with mock.patch(
                'os.path.realpath', return_value='/non/existent'
            ) as m:
                with pytest.raises(FileNotFoundError):
                    psutil.disk_partitions()
                assert m.called
        finally:
            psutil.PROCFS_PATH = "/proc"


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSystemDiskIoCounters(PsutilTestCase):
    def test_emulate_kernel_2_4(self):
        # Tests /proc/diskstats parsing format for 2.4 kernels, see:
        # https://github.com/giampaolo/psutil/issues/767
        content = "   3     0   1 hda 2 3 4 5 6 7 8 9 10 11 12"
        with mock_open_content({'/proc/diskstats': content}):
            with mock.patch(
                'psutil._pslinux.is_storage_device', return_value=True
            ):
                ret = psutil.disk_io_counters(nowrap=False)
                assert ret.read_count == 1
                assert ret.read_merged_count == 2
                assert ret.read_bytes == 3 * SECTOR_SIZE
                assert ret.read_time == 4
                assert ret.write_count == 5
                assert ret.write_merged_count == 6
                assert ret.write_bytes == 7 * SECTOR_SIZE
                assert ret.write_time == 8
                assert ret.busy_time == 10

    def test_emulate_kernel_2_6_full(self):
        # Tests /proc/diskstats parsing format for 2.6 kernels,
        # lines reporting all metrics:
        # https://github.com/giampaolo/psutil/issues/767
        content = "   3    0   hda 1 2 3 4 5 6 7 8 9 10 11"
        with mock_open_content({"/proc/diskstats": content}):
            with mock.patch(
                'psutil._pslinux.is_storage_device', return_value=True
            ):
                ret = psutil.disk_io_counters(nowrap=False)
                assert ret.read_count == 1
                assert ret.read_merged_count == 2
                assert ret.read_bytes == 3 * SECTOR_SIZE
                assert ret.read_time == 4
                assert ret.write_count == 5
                assert ret.write_merged_count == 6
                assert ret.write_bytes == 7 * SECTOR_SIZE
                assert ret.write_time == 8
                assert ret.busy_time == 10

    def test_emulate_kernel_2_6_limited(self):
        # Tests /proc/diskstats parsing format for 2.6 kernels,
        # where one line of /proc/partitions return a limited
        # amount of metrics when it bumps into a partition
        # (instead of a disk). See:
        # https://github.com/giampaolo/psutil/issues/767
        with mock_open_content({"/proc/diskstats": "   3    1   hda 1 2 3 4"}):
            with mock.patch(
                'psutil._pslinux.is_storage_device', return_value=True
            ):
                ret = psutil.disk_io_counters(nowrap=False)
                assert ret.read_count == 1
                assert ret.read_bytes == 2 * SECTOR_SIZE
                assert ret.write_count == 3
                assert ret.write_bytes == 4 * SECTOR_SIZE

                assert ret.read_merged_count == 0
                assert ret.read_time == 0
                assert ret.write_merged_count == 0
                assert ret.write_time == 0
                assert ret.busy_time == 0

    def test_emulate_include_partitions(self):
        # Make sure that when perdisk=True disk partitions are returned,
        # see:
        # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842
        content = textwrap.dedent("""\
            3    0   nvme0n1 1 2 3 4 5 6 7 8 9 10 11
            3    0   nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11
            """)
        with mock_open_content({"/proc/diskstats": content}):
            with mock.patch(
                'psutil._pslinux.is_storage_device', return_value=False
            ):
                ret = psutil.disk_io_counters(perdisk=True, nowrap=False)
                assert len(ret) == 2
                assert ret['nvme0n1'].read_count == 1
                assert ret['nvme0n1p1'].read_count == 1
                assert ret['nvme0n1'].write_count == 5
                assert ret['nvme0n1p1'].write_count == 5

    def test_emulate_exclude_partitions(self):
        # Make sure that when perdisk=False partitions (e.g. 'sda1',
        # 'nvme0n1p1') are skipped and not included in the total count.
        # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842
        content = textwrap.dedent("""\
            3    0   nvme0n1 1 2 3 4 5 6 7 8 9 10 11
            3    0   nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11
            """)
        with mock_open_content({"/proc/diskstats": content}):
            with mock.patch(
                'psutil._pslinux.is_storage_device', return_value=False
            ):
                ret = psutil.disk_io_counters(perdisk=False, nowrap=False)
                assert ret is None

        def is_storage_device(name):
            return name == 'nvme0n1'

        content = textwrap.dedent("""\
            3    0   nvme0n1 1 2 3 4 5 6 7 8 9 10 11
            3    0   nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11
            """)
        with mock_open_content({"/proc/diskstats": content}):
            with mock.patch(
                'psutil._pslinux.is_storage_device',
                create=True,
                side_effect=is_storage_device,
            ):
                ret = psutil.disk_io_counters(perdisk=False, nowrap=False)
                assert ret.read_count == 1
                assert ret.write_count == 5

    def test_emulate_use_sysfs(self):
        def exists(path):
            return path == '/proc/diskstats'

        wprocfs = psutil.disk_io_counters(perdisk=True)
        with mock.patch(
            'psutil._pslinux.os.path.exists', create=True, side_effect=exists
        ):
            wsysfs = psutil.disk_io_counters(perdisk=True)
        assert len(wprocfs) == len(wsysfs)

    def test_emulate_not_impl(self):
        def exists(path):
            return False

        with mock.patch(
            'psutil._pslinux.os.path.exists', create=True, side_effect=exists
        ):
            with pytest.raises(NotImplementedError):
                psutil.disk_io_counters()


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestRootFsDeviceFinder(PsutilTestCase):
    def setUp(self):
        dev = os.stat("/").st_dev
        self.major = os.major(dev)
        self.minor = os.minor(dev)

    def test_call_methods(self):
        finder = RootFsDeviceFinder()
        if os.path.exists("/proc/partitions"):
            finder.ask_proc_partitions()
        else:
            with pytest.raises(FileNotFoundError):
                finder.ask_proc_partitions()
        if os.path.exists(
            "/sys/dev/block/%s:%s/uevent" % (self.major, self.minor)
        ):
            finder.ask_sys_dev_block()
        else:
            with pytest.raises(FileNotFoundError):
                finder.ask_sys_dev_block()
        finder.ask_sys_class_block()

    @pytest.mark.skipif(GITHUB_ACTIONS, reason="unsupported on GITHUB_ACTIONS")
    def test_comparisons(self):
        finder = RootFsDeviceFinder()
        assert finder.find() is not None

        a = b = c = None
        if os.path.exists("/proc/partitions"):
            a = finder.ask_proc_partitions()
        if os.path.exists(
            "/sys/dev/block/%s:%s/uevent" % (self.major, self.minor)
        ):
            b = finder.ask_sys_class_block()
        c = finder.ask_sys_dev_block()

        base = a or b or c
        if base and a:
            assert base == a
        if base and b:
            assert base == b
        if base and c:
            assert base == c

    @pytest.mark.skipif(
        not which("findmnt"), reason="findmnt utility not available"
    )
    @pytest.mark.skipif(GITHUB_ACTIONS, reason="unsupported on GITHUB_ACTIONS")
    def test_against_findmnt(self):
        psutil_value = RootFsDeviceFinder().find()
        findmnt_value = sh("findmnt -o SOURCE -rn /")
        assert psutil_value == findmnt_value

    def test_disk_partitions_mocked(self):
        with mock.patch(
            'psutil._pslinux.cext.disk_partitions',
            return_value=[('/dev/root', '/', 'ext4', 'rw')],
        ) as m:
            part = psutil.disk_partitions()[0]
            assert m.called
            if not GITHUB_ACTIONS:
                assert part.device != "/dev/root"
                assert part.device == RootFsDeviceFinder().find()
            else:
                assert part.device == "/dev/root"


# =====================================================================
# --- misc
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestMisc(PsutilTestCase):
    def test_boot_time(self):
        vmstat_value = vmstat('boot time')
        psutil_value = psutil.boot_time()
        assert int(vmstat_value) == int(psutil_value)

    def test_no_procfs_on_import(self):
        my_procfs = self.get_testfn()
        os.mkdir(my_procfs)

        with open(os.path.join(my_procfs, 'stat'), 'w') as f:
            f.write('cpu   0 0 0 0 0 0 0 0 0 0\n')
            f.write('cpu0  0 0 0 0 0 0 0 0 0 0\n')
            f.write('cpu1  0 0 0 0 0 0 0 0 0 0\n')

        try:
            orig_open = open

            def open_mock(name, *args, **kwargs):
                if name.startswith('/proc'):
                    raise IOError(errno.ENOENT, 'rejecting access for test')
                return orig_open(name, *args, **kwargs)

            patch_point = 'builtins.open' if PY3 else '__builtin__.open'
            with mock.patch(patch_point, side_effect=open_mock):
                reload_module(psutil)

                with pytest.raises(IOError):
                    psutil.cpu_times()
                with pytest.raises(IOError):
                    psutil.cpu_times(percpu=True)
                with pytest.raises(IOError):
                    psutil.cpu_percent()
                with pytest.raises(IOError):
                    psutil.cpu_percent(percpu=True)
                with pytest.raises(IOError):
                    psutil.cpu_times_percent()
                with pytest.raises(IOError):
                    psutil.cpu_times_percent(percpu=True)

                psutil.PROCFS_PATH = my_procfs

                assert psutil.cpu_percent() == 0
                assert sum(psutil.cpu_times_percent()) == 0

                # since we don't know the number of CPUs at import time,
                # we awkwardly say there are none until the second call
                per_cpu_percent = psutil.cpu_percent(percpu=True)
                assert sum(per_cpu_percent) == 0

                # ditto awkward length
                per_cpu_times_percent = psutil.cpu_times_percent(percpu=True)
                assert sum(map(sum, per_cpu_times_percent)) == 0

                # much user, very busy
                with open(os.path.join(my_procfs, 'stat'), 'w') as f:
                    f.write('cpu   1 0 0 0 0 0 0 0 0 0\n')
                    f.write('cpu0  1 0 0 0 0 0 0 0 0 0\n')
                    f.write('cpu1  1 0 0 0 0 0 0 0 0 0\n')

                assert psutil.cpu_percent() != 0
                assert sum(psutil.cpu_percent(percpu=True)) != 0
                assert sum(psutil.cpu_times_percent()) != 0
                assert (
                    sum(map(sum, psutil.cpu_times_percent(percpu=True))) != 0
                )
        finally:
            shutil.rmtree(my_procfs)
            reload_module(psutil)

        assert psutil.PROCFS_PATH == '/proc'

    def test_cpu_steal_decrease(self):
        # Test cumulative cpu stats decrease. We should ignore this.
        # See issue #1210.
        content = textwrap.dedent("""\
            cpu   0 0 0 0 0 0 0 1 0 0
            cpu0  0 0 0 0 0 0 0 1 0 0
            cpu1  0 0 0 0 0 0 0 1 0 0
            """).encode()
        with mock_open_content({"/proc/stat": content}) as m:
            # first call to "percent" functions should read the new stat file
            # and compare to the "real" file read at import time - so the
            # values are meaningless
            psutil.cpu_percent()
            assert m.called
            psutil.cpu_percent(percpu=True)
            psutil.cpu_times_percent()
            psutil.cpu_times_percent(percpu=True)

        content = textwrap.dedent("""\
            cpu   1 0 0 0 0 0 0 0 0 0
            cpu0  1 0 0 0 0 0 0 0 0 0
            cpu1  1 0 0 0 0 0 0 0 0 0
            """).encode()
        with mock_open_content({"/proc/stat": content}):
            # Increase "user" while steal goes "backwards" to zero.
            cpu_percent = psutil.cpu_percent()
            assert m.called
            cpu_percent_percpu = psutil.cpu_percent(percpu=True)
            cpu_times_percent = psutil.cpu_times_percent()
            cpu_times_percent_percpu = psutil.cpu_times_percent(percpu=True)
            assert cpu_percent != 0
            assert sum(cpu_percent_percpu) != 0
            assert sum(cpu_times_percent) != 0
            assert sum(cpu_times_percent) != 100.0
            assert sum(map(sum, cpu_times_percent_percpu)) != 0
            assert sum(map(sum, cpu_times_percent_percpu)) != 100.0
            assert cpu_times_percent.steal == 0
            assert cpu_times_percent.user != 0

    def test_boot_time_mocked(self):
        with mock.patch('psutil._common.open', create=True) as m:
            with pytest.raises(RuntimeError):
                psutil._pslinux.boot_time()
            assert m.called

    def test_users(self):
        # Make sure the C extension converts ':0' and ':0.0' to
        # 'localhost'.
        for user in psutil.users():
            assert user.host not in (":0", ":0.0")

    def test_procfs_path(self):
        tdir = self.get_testfn()
        os.mkdir(tdir)
        try:
            psutil.PROCFS_PATH = tdir
            with pytest.raises(IOError):
                psutil.virtual_memory()
            with pytest.raises(IOError):
                psutil.cpu_times()
            with pytest.raises(IOError):
                psutil.cpu_times(percpu=True)
            with pytest.raises(IOError):
                psutil.boot_time()
            # self.assertRaises(IOError, psutil.pids)
            with pytest.raises(IOError):
                psutil.net_connections()
            with pytest.raises(IOError):
                psutil.net_io_counters()
            with pytest.raises(IOError):
                psutil.net_if_stats()
            # self.assertRaises(IOError, psutil.disk_io_counters)
            with pytest.raises(IOError):
                psutil.disk_partitions()
            with pytest.raises(psutil.NoSuchProcess):
                psutil.Process()
        finally:
            psutil.PROCFS_PATH = "/proc"

    @retry_on_failure()
    @pytest.mark.skipif(PYTEST_PARALLEL, reason="skip if pytest-parallel")
    def test_issue_687(self):
        # In case of thread ID:
        # - pid_exists() is supposed to return False
        # - Process(tid) is supposed to work
        # - pids() should not return the TID
        # See: https://github.com/giampaolo/psutil/issues/687
        with ThreadTask():
            p = psutil.Process()
            threads = p.threads()
            assert len(threads) == (3 if QEMU_USER else 2)
            tid = sorted(threads, key=lambda x: x.id)[1].id
            assert p.pid != tid
            pt = psutil.Process(tid)
            pt.as_dict()
            assert tid not in psutil.pids()

    def test_pid_exists_no_proc_status(self):
        # Internally pid_exists relies on /proc/{pid}/status.
        # Emulate a case where this file is empty in which case
        # psutil is supposed to fall back on using pids().
        with mock_open_content({"/proc/%s/status": ""}) as m:
            assert psutil.pid_exists(os.getpid())
            assert m.called


# =====================================================================
# --- sensors
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
@pytest.mark.skipif(not HAS_BATTERY, reason="no battery")
class TestSensorsBattery(PsutilTestCase):
    @pytest.mark.skipif(not which("acpi"), reason="acpi utility not available")
    def test_percent(self):
        out = sh("acpi -b")
        acpi_value = int(out.split(",")[1].strip().replace('%', ''))
        psutil_value = psutil.sensors_battery().percent
        assert abs(acpi_value - psutil_value) < 1

    def test_emulate_power_plugged(self):
        # Pretend the AC power cable is connected.
        def open_mock(name, *args, **kwargs):
            if name.endswith(('AC0/online', 'AC/online')):
                return io.BytesIO(b"1")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock) as m:
            assert psutil.sensors_battery().power_plugged is True
            assert (
                psutil.sensors_battery().secsleft
                == psutil.POWER_TIME_UNLIMITED
            )
            assert m.called

    def test_emulate_power_plugged_2(self):
        # Same as above but pretend /AC0/online does not exist in which
        # case code relies on /status file.
        def open_mock(name, *args, **kwargs):
            if name.endswith(('AC0/online', 'AC/online')):
                raise IOError(errno.ENOENT, "")
            elif name.endswith("/status"):
                return io.StringIO(u"charging")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock) as m:
            assert psutil.sensors_battery().power_plugged is True
            assert m.called

    def test_emulate_power_not_plugged(self):
        # Pretend the AC power cable is not connected.
        def open_mock(name, *args, **kwargs):
            if name.endswith(('AC0/online', 'AC/online')):
                return io.BytesIO(b"0")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock) as m:
            assert psutil.sensors_battery().power_plugged is False
            assert m.called

    def test_emulate_power_not_plugged_2(self):
        # Same as above but pretend /AC0/online does not exist in which
        # case code relies on /status file.
        def open_mock(name, *args, **kwargs):
            if name.endswith(('AC0/online', 'AC/online')):
                raise IOError(errno.ENOENT, "")
            elif name.endswith("/status"):
                return io.StringIO(u"discharging")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock) as m:
            assert psutil.sensors_battery().power_plugged is False
            assert m.called

    def test_emulate_power_undetermined(self):
        # Pretend we can't know whether the AC power cable not
        # connected (assert fallback to False).
        def open_mock(name, *args, **kwargs):
            if name.startswith((
                '/sys/class/power_supply/AC0/online',
                '/sys/class/power_supply/AC/online',
            )):
                raise IOError(errno.ENOENT, "")
            elif name.startswith("/sys/class/power_supply/BAT0/status"):
                return io.BytesIO(b"???")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock) as m:
            assert psutil.sensors_battery().power_plugged is None
            assert m.called

    def test_emulate_energy_full_0(self):
        # Emulate a case where energy_full files returns 0.
        with mock_open_content(
            {"/sys/class/power_supply/BAT0/energy_full": b"0"}
        ) as m:
            assert psutil.sensors_battery().percent == 0
            assert m.called

    def test_emulate_energy_full_not_avail(self):
        # Emulate a case where energy_full file does not exist.
        # Expected fallback on /capacity.
        with mock_open_exception(
            "/sys/class/power_supply/BAT0/energy_full",
            IOError(errno.ENOENT, ""),
        ):
            with mock_open_exception(
                "/sys/class/power_supply/BAT0/charge_full",
                IOError(errno.ENOENT, ""),
            ):
                with mock_open_content(
                    {"/sys/class/power_supply/BAT0/capacity": b"88"}
                ):
                    assert psutil.sensors_battery().percent == 88

    def test_emulate_no_power(self):
        # Emulate a case where /AC0/online file nor /BAT0/status exist.
        with mock_open_exception(
            "/sys/class/power_supply/AC/online", IOError(errno.ENOENT, "")
        ):
            with mock_open_exception(
                "/sys/class/power_supply/AC0/online", IOError(errno.ENOENT, "")
            ):
                with mock_open_exception(
                    "/sys/class/power_supply/BAT0/status",
                    IOError(errno.ENOENT, ""),
                ):
                    assert psutil.sensors_battery().power_plugged is None


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSensorsBatteryEmulated(PsutilTestCase):
    def test_it(self):
        def open_mock(name, *args, **kwargs):
            if name.endswith("/energy_now"):
                return io.StringIO(u"60000000")
            elif name.endswith("/power_now"):
                return io.StringIO(u"0")
            elif name.endswith("/energy_full"):
                return io.StringIO(u"60000001")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch('os.listdir', return_value=["BAT0"]) as mlistdir:
            with mock.patch(patch_point, side_effect=open_mock) as mopen:
                assert psutil.sensors_battery() is not None
        assert mlistdir.called
        assert mopen.called


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSensorsTemperatures(PsutilTestCase):
    def test_emulate_class_hwmon(self):
        def open_mock(name, *args, **kwargs):
            if name.endswith('/name'):
                return io.StringIO(u"name")
            elif name.endswith('/temp1_label'):
                return io.StringIO(u"label")
            elif name.endswith('/temp1_input'):
                return io.BytesIO(b"30000")
            elif name.endswith('/temp1_max'):
                return io.BytesIO(b"40000")
            elif name.endswith('/temp1_crit'):
                return io.BytesIO(b"50000")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            # Test case with /sys/class/hwmon
            with mock.patch(
                'glob.glob', return_value=['/sys/class/hwmon/hwmon0/temp1']
            ):
                temp = psutil.sensors_temperatures()['name'][0]
                assert temp.label == 'label'
                assert temp.current == 30.0
                assert temp.high == 40.0
                assert temp.critical == 50.0

    def test_emulate_class_thermal(self):
        def open_mock(name, *args, **kwargs):
            if name.endswith('0_temp'):
                return io.BytesIO(b"50000")
            elif name.endswith('temp'):
                return io.BytesIO(b"30000")
            elif name.endswith('0_type'):
                return io.StringIO(u"critical")
            elif name.endswith('type'):
                return io.StringIO(u"name")
            else:
                return orig_open(name, *args, **kwargs)

        def glob_mock(path):
            if path == '/sys/class/hwmon/hwmon*/temp*_*':  # noqa
                return []
            elif path == '/sys/class/hwmon/hwmon*/device/temp*_*':
                return []
            elif path == '/sys/class/thermal/thermal_zone*':
                return ['/sys/class/thermal/thermal_zone0']
            elif path == '/sys/class/thermal/thermal_zone0/trip_point*':
                return [
                    '/sys/class/thermal/thermal_zone1/trip_point_0_type',
                    '/sys/class/thermal/thermal_zone1/trip_point_0_temp',
                ]
            return []

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            with mock.patch('glob.glob', create=True, side_effect=glob_mock):
                temp = psutil.sensors_temperatures()['name'][0]
                assert temp.label == ''  # noqa
                assert temp.current == 30.0
                assert temp.high == 50.0
                assert temp.critical == 50.0


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestSensorsFans(PsutilTestCase):
    def test_emulate_data(self):
        def open_mock(name, *args, **kwargs):
            if name.endswith('/name'):
                return io.StringIO(u"name")
            elif name.endswith('/fan1_label'):
                return io.StringIO(u"label")
            elif name.endswith('/fan1_input'):
                return io.StringIO(u"2000")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock):
            with mock.patch(
                'glob.glob', return_value=['/sys/class/hwmon/hwmon2/fan1']
            ):
                fan = psutil.sensors_fans()['name'][0]
                assert fan.label == 'label'
                assert fan.current == 2000


# =====================================================================
# --- test process
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestProcess(PsutilTestCase):
    @retry_on_failure()
    def test_parse_smaps_vs_memory_maps(self):
        sproc = self.spawn_testproc()
        uss, pss, swap = psutil._pslinux.Process(sproc.pid)._parse_smaps()
        maps = psutil.Process(sproc.pid).memory_maps(grouped=False)
        assert (
            abs(uss - sum([x.private_dirty + x.private_clean for x in maps]))
            < 4096
        )
        assert abs(pss - sum([x.pss for x in maps])) < 4096
        assert abs(swap - sum([x.swap for x in maps])) < 4096

    def test_parse_smaps_mocked(self):
        # See: https://github.com/giampaolo/psutil/issues/1222
        content = textwrap.dedent("""\
            fffff0 r-xp 00000000 00:00 0                  [vsyscall]
            Size:                  1 kB
            Rss:                   2 kB
            Pss:                   3 kB
            Shared_Clean:          4 kB
            Shared_Dirty:          5 kB
            Private_Clean:         6 kB
            Private_Dirty:         7 kB
            Referenced:            8 kB
            Anonymous:             9 kB
            LazyFree:              10 kB
            AnonHugePages:         11 kB
            ShmemPmdMapped:        12 kB
            Shared_Hugetlb:        13 kB
            Private_Hugetlb:       14 kB
            Swap:                  15 kB
            SwapPss:               16 kB
            KernelPageSize:        17 kB
            MMUPageSize:           18 kB
            Locked:                19 kB
            VmFlags: rd ex
            """).encode()
        with mock_open_content({"/proc/%s/smaps" % os.getpid(): content}) as m:
            p = psutil._pslinux.Process(os.getpid())
            uss, pss, swap = p._parse_smaps()
            assert m.called
            assert uss == (6 + 7 + 14) * 1024
            assert pss == 3 * 1024
            assert swap == 15 * 1024

    # On PYPY file descriptors are not closed fast enough.
    @pytest.mark.skipif(PYPY, reason="unreliable on PYPY")
    def test_open_files_mode(self):
        def get_test_file(fname):
            p = psutil.Process()
            giveup_at = time.time() + GLOBAL_TIMEOUT
            while True:
                for file in p.open_files():
                    if file.path == os.path.abspath(fname):
                        return file
                    elif time.time() > giveup_at:
                        break
            raise RuntimeError("timeout looking for test file")

        testfn = self.get_testfn()
        with open(testfn, "w"):
            assert get_test_file(testfn).mode == "w"
        with open(testfn):
            assert get_test_file(testfn).mode == "r"
        with open(testfn, "a"):
            assert get_test_file(testfn).mode == "a"
        with open(testfn, "r+"):
            assert get_test_file(testfn).mode == "r+"
        with open(testfn, "w+"):
            assert get_test_file(testfn).mode == "r+"
        with open(testfn, "a+"):
            assert get_test_file(testfn).mode == "a+"
        # note: "x" bit is not supported
        if PY3:
            safe_rmpath(testfn)
            with open(testfn, "x"):
                assert get_test_file(testfn).mode == "w"
            safe_rmpath(testfn)
            with open(testfn, "x+"):
                assert get_test_file(testfn).mode == "r+"

    def test_open_files_file_gone(self):
        # simulates a file which gets deleted during open_files()
        # execution
        p = psutil.Process()
        files = p.open_files()
        with open(self.get_testfn(), 'w'):
            # give the kernel some time to see the new file
            call_until(lambda: len(p.open_files()) != len(files))
            with mock.patch(
                'psutil._pslinux.os.readlink',
                side_effect=OSError(errno.ENOENT, ""),
            ) as m:
                assert p.open_files() == []
                assert m.called
            # also simulate the case where os.readlink() returns EINVAL
            # in which case psutil is supposed to 'continue'
            with mock.patch(
                'psutil._pslinux.os.readlink',
                side_effect=OSError(errno.EINVAL, ""),
            ) as m:
                assert p.open_files() == []
                assert m.called

    def test_open_files_fd_gone(self):
        # Simulate a case where /proc/{pid}/fdinfo/{fd} disappears
        # while iterating through fds.
        # https://travis-ci.org/giampaolo/psutil/jobs/225694530
        p = psutil.Process()
        files = p.open_files()
        with open(self.get_testfn(), 'w'):
            # give the kernel some time to see the new file
            call_until(lambda: len(p.open_files()) != len(files))
            patch_point = 'builtins.open' if PY3 else '__builtin__.open'
            with mock.patch(
                patch_point, side_effect=IOError(errno.ENOENT, "")
            ) as m:
                assert p.open_files() == []
                assert m.called

    def test_open_files_enametoolong(self):
        # Simulate a case where /proc/{pid}/fd/{fd} symlink
        # points to a file with full path longer than PATH_MAX, see:
        # https://github.com/giampaolo/psutil/issues/1940
        p = psutil.Process()
        files = p.open_files()
        with open(self.get_testfn(), 'w'):
            # give the kernel some time to see the new file
            call_until(lambda: len(p.open_files()) != len(files))
            patch_point = 'psutil._pslinux.os.readlink'
            with mock.patch(
                patch_point, side_effect=OSError(errno.ENAMETOOLONG, "")
            ) as m:
                with mock.patch("psutil._pslinux.debug"):
                    assert p.open_files() == []
                    assert m.called

    # --- mocked tests

    def test_terminal_mocked(self):
        with mock.patch(
            'psutil._pslinux._psposix.get_terminal_map', return_value={}
        ) as m:
            assert psutil._pslinux.Process(os.getpid()).terminal() is None
            assert m.called

    # TODO: re-enable this test.
    # def test_num_ctx_switches_mocked(self):
    #     with mock.patch('psutil._common.open', create=True) as m:
    #         self.assertRaises(
    #             NotImplementedError,
    #             psutil._pslinux.Process(os.getpid()).num_ctx_switches)
    #         assert m.called

    def test_cmdline_mocked(self):
        # see: https://github.com/giampaolo/psutil/issues/639
        p = psutil.Process()
        fake_file = io.StringIO(u'foo\x00bar\x00')
        with mock.patch(
            'psutil._common.open', return_value=fake_file, create=True
        ) as m:
            assert p.cmdline() == ['foo', 'bar']
            assert m.called
        fake_file = io.StringIO(u'foo\x00bar\x00\x00')
        with mock.patch(
            'psutil._common.open', return_value=fake_file, create=True
        ) as m:
            assert p.cmdline() == ['foo', 'bar', '']
            assert m.called

    def test_cmdline_spaces_mocked(self):
        # see: https://github.com/giampaolo/psutil/issues/1179
        p = psutil.Process()
        fake_file = io.StringIO(u'foo bar ')
        with mock.patch(
            'psutil._common.open', return_value=fake_file, create=True
        ) as m:
            assert p.cmdline() == ['foo', 'bar']
            assert m.called
        fake_file = io.StringIO(u'foo bar  ')
        with mock.patch(
            'psutil._common.open', return_value=fake_file, create=True
        ) as m:
            assert p.cmdline() == ['foo', 'bar', '']
            assert m.called

    def test_cmdline_mixed_separators(self):
        # https://github.com/giampaolo/psutil/issues/
        #    1179#issuecomment-552984549
        p = psutil.Process()
        fake_file = io.StringIO(u'foo\x20bar\x00')
        with mock.patch(
            'psutil._common.open', return_value=fake_file, create=True
        ) as m:
            assert p.cmdline() == ['foo', 'bar']
            assert m.called

    def test_readlink_path_deleted_mocked(self):
        with mock.patch(
            'psutil._pslinux.os.readlink', return_value='/home/foo (deleted)'
        ):
            assert psutil.Process().exe() == "/home/foo"
            assert psutil.Process().cwd() == "/home/foo"

    def test_threads_mocked(self):
        # Test the case where os.listdir() returns a file (thread)
        # which no longer exists by the time we open() it (race
        # condition). threads() is supposed to ignore that instead
        # of raising NSP.
        def open_mock_1(name, *args, **kwargs):
            if name.startswith('/proc/%s/task' % os.getpid()):
                raise IOError(errno.ENOENT, "")
            else:
                return orig_open(name, *args, **kwargs)

        orig_open = open
        patch_point = 'builtins.open' if PY3 else '__builtin__.open'
        with mock.patch(patch_point, side_effect=open_mock_1) as m:
            ret = psutil.Process().threads()
            assert m.called
            assert ret == []

        # ...but if it bumps into something != ENOENT we want an
        # exception.
        def open_mock_2(name, *args, **kwargs):
            if name.startswith('/proc/%s/task' % os.getpid()):
                raise IOError(errno.EPERM, "")
            else:
                return orig_open(name, *args, **kwargs)

        with mock.patch(patch_point, side_effect=open_mock_2):
            with pytest.raises(psutil.AccessDenied):
                psutil.Process().threads()

    def test_exe_mocked(self):
        with mock.patch(
            'psutil._pslinux.readlink', side_effect=OSError(errno.ENOENT, "")
        ) as m:
            # de-activate guessing from cmdline()
            with mock.patch(
                'psutil._pslinux.Process.cmdline', return_value=[]
            ):
                ret = psutil.Process().exe()
                assert m.called
                assert ret == ""  # noqa

    def test_issue_1014(self):
        # Emulates a case where smaps file does not exist. In this case
        # wrap_exception decorator should not raise NoSuchProcess.
        with mock_open_exception(
            '/proc/%s/smaps' % os.getpid(), IOError(errno.ENOENT, "")
        ) as m:
            p = psutil.Process()
            with pytest.raises(FileNotFoundError):
                p.memory_maps()
            assert m.called

    @pytest.mark.skipif(not HAS_RLIMIT, reason="not supported")
    def test_rlimit_zombie(self):
        # Emulate a case where rlimit() raises ENOSYS, which may
        # happen in case of zombie process:
        # https://travis-ci.org/giampaolo/psutil/jobs/51368273
        with mock.patch(
            "psutil._pslinux.prlimit", side_effect=OSError(errno.ENOSYS, "")
        ) as m1:
            with mock.patch(
                "psutil._pslinux.Process._is_zombie", return_value=True
            ) as m2:
                p = psutil.Process()
                p.name()
                with pytest.raises(psutil.ZombieProcess) as cm:
                    p.rlimit(psutil.RLIMIT_NOFILE)
        assert m1.called
        assert m2.called
        assert cm.value.pid == p.pid
        assert cm.value.name == p.name()

    def test_stat_file_parsing(self):
        args = [
            "0",  # pid
            "(cat)",  # name
            "Z",  # status
            "1",  # ppid
            "0",  # pgrp
            "0",  # session
            "0",  # tty
            "0",  # tpgid
            "0",  # flags
            "0",  # minflt
            "0",  # cminflt
            "0",  # majflt
            "0",  # cmajflt
            "2",  # utime
            "3",  # stime
            "4",  # cutime
            "5",  # cstime
            "0",  # priority
            "0",  # nice
            "0",  # num_threads
            "0",  # itrealvalue
            "6",  # starttime
            "0",  # vsize
            "0",  # rss
            "0",  # rsslim
            "0",  # startcode
            "0",  # endcode
            "0",  # startstack
            "0",  # kstkesp
            "0",  # kstkeip
            "0",  # signal
            "0",  # blocked
            "0",  # sigignore
            "0",  # sigcatch
            "0",  # wchan
            "0",  # nswap
            "0",  # cnswap
            "0",  # exit_signal
            "6",  # processor
            "0",  # rt priority
            "0",  # policy
            "7",  # delayacct_blkio_ticks
        ]
        content = " ".join(args).encode()
        with mock_open_content({"/proc/%s/stat" % os.getpid(): content}):
            p = psutil.Process()
            assert p.name() == 'cat'
            assert p.status() == psutil.STATUS_ZOMBIE
            assert p.ppid() == 1
            assert p.create_time() == 6 / CLOCK_TICKS + psutil.boot_time()
            cpu = p.cpu_times()
            assert cpu.user == 2 / CLOCK_TICKS
            assert cpu.system == 3 / CLOCK_TICKS
            assert cpu.children_user == 4 / CLOCK_TICKS
            assert cpu.children_system == 5 / CLOCK_TICKS
            assert cpu.iowait == 7 / CLOCK_TICKS
            assert p.cpu_num() == 6

    def test_status_file_parsing(self):
        content = textwrap.dedent("""\
            Uid:\t1000\t1001\t1002\t1003
            Gid:\t1004\t1005\t1006\t1007
            Threads:\t66
            Cpus_allowed:\tf
            Cpus_allowed_list:\t0-7
            voluntary_ctxt_switches:\t12
            nonvoluntary_ctxt_switches:\t13""").encode()
        with mock_open_content({"/proc/%s/status" % os.getpid(): content}):
            p = psutil.Process()
            assert p.num_ctx_switches().voluntary == 12
            assert p.num_ctx_switches().involuntary == 13
            assert p.num_threads() == 66
            uids = p.uids()
            assert uids.real == 1000
            assert uids.effective == 1001
            assert uids.saved == 1002
            gids = p.gids()
            assert gids.real == 1004
            assert gids.effective == 1005
            assert gids.saved == 1006
            assert p._proc._get_eligible_cpus() == list(range(8))

    def test_net_connections_enametoolong(self):
        # Simulate a case where /proc/{pid}/fd/{fd} symlink points to
        # a file with full path longer than PATH_MAX, see:
        # https://github.com/giampaolo/psutil/issues/1940
        with mock.patch(
            'psutil._pslinux.os.readlink',
            side_effect=OSError(errno.ENAMETOOLONG, ""),
        ) as m:
            p = psutil.Process()
            with mock.patch("psutil._pslinux.debug"):
                assert p.net_connections() == []
                assert m.called


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestProcessAgainstStatus(PsutilTestCase):
    """/proc/pid/stat and /proc/pid/status have many values in common.
    Whenever possible, psutil uses /proc/pid/stat (it's faster).
    For all those cases we check that the value found in
    /proc/pid/stat (by psutil) matches the one found in
    /proc/pid/status.
    """

    @classmethod
    def setUpClass(cls):
        cls.proc = psutil.Process()

    def read_status_file(self, linestart):
        with psutil._psplatform.open_text(
            '/proc/%s/status' % self.proc.pid
        ) as f:
            for line in f:
                line = line.strip()
                if line.startswith(linestart):
                    value = line.partition('\t')[2]
                    try:
                        return int(value)
                    except ValueError:
                        return value
            raise ValueError("can't find %r" % linestart)

    def test_name(self):
        value = self.read_status_file("Name:")
        assert self.proc.name() == value

    @pytest.mark.skipif(QEMU_USER, reason="QEMU user not supported")
    def test_status(self):
        value = self.read_status_file("State:")
        value = value[value.find('(') + 1 : value.rfind(')')]
        value = value.replace(' ', '-')
        assert self.proc.status() == value

    def test_ppid(self):
        value = self.read_status_file("PPid:")
        assert self.proc.ppid() == value

    def test_num_threads(self):
        value = self.read_status_file("Threads:")
        assert self.proc.num_threads() == value

    def test_uids(self):
        value = self.read_status_file("Uid:")
        value = tuple(map(int, value.split()[1:4]))
        assert self.proc.uids() == value

    def test_gids(self):
        value = self.read_status_file("Gid:")
        value = tuple(map(int, value.split()[1:4]))
        assert self.proc.gids() == value

    @retry_on_failure()
    def test_num_ctx_switches(self):
        value = self.read_status_file("voluntary_ctxt_switches:")
        assert self.proc.num_ctx_switches().voluntary == value
        value = self.read_status_file("nonvoluntary_ctxt_switches:")
        assert self.proc.num_ctx_switches().involuntary == value

    def test_cpu_affinity(self):
        value = self.read_status_file("Cpus_allowed_list:")
        if '-' in str(value):
            min_, max_ = map(int, value.split('-'))
            assert self.proc.cpu_affinity() == list(range(min_, max_ + 1))

    def test_cpu_affinity_eligible_cpus(self):
        value = self.read_status_file("Cpus_allowed_list:")
        with mock.patch("psutil._pslinux.per_cpu_times") as m:
            self.proc._proc._get_eligible_cpus()
        if '-' in str(value):
            assert not m.called
        else:
            assert m.called


# =====================================================================
# --- test utils
# =====================================================================


@pytest.mark.skipif(not LINUX, reason="LINUX only")
class TestUtils(PsutilTestCase):
    def test_readlink(self):
        with mock.patch("os.readlink", return_value="foo (deleted)") as m:
            assert psutil._psplatform.readlink("bar") == "foo"
            assert m.called
PKok\�u���psutil/tests/test_sunos.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Sun OS specific tests."""

import os

import psutil
from psutil import SUNOS
from psutil.tests import PsutilTestCase
from psutil.tests import pytest
from psutil.tests import sh


@pytest.mark.skipif(not SUNOS, reason="SUNOS only")
class SunOSSpecificTestCase(PsutilTestCase):
    def test_swap_memory(self):
        out = sh('env PATH=/usr/sbin:/sbin:%s swap -l' % os.environ['PATH'])
        lines = out.strip().split('\n')[1:]
        if not lines:
            raise ValueError('no swap device(s) configured')
        total = free = 0
        for line in lines:
            fields = line.split()
            total = int(fields[3]) * 512
            free = int(fields[4]) * 512
        used = total - free

        psutil_swap = psutil.swap_memory()
        assert psutil_swap.total == total
        assert psutil_swap.used == used
        assert psutil_swap.free == free

    def test_cpu_count(self):
        out = sh("/usr/sbin/psrinfo")
        assert psutil.cpu_count() == len(out.split('\n'))
PKok\0��DDpsutil/tests/test_posix.pynu�[���#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""POSIX specific tests."""

import datetime
import errno
import os
import re
import subprocess
import time

import psutil
from psutil import AIX
from psutil import BSD
from psutil import LINUX
from psutil import MACOS
from psutil import OPENBSD
from psutil import POSIX
from psutil import SUNOS
from psutil.tests import AARCH64
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import PYTHON_EXE
from psutil.tests import QEMU_USER
from psutil.tests import PsutilTestCase
from psutil.tests import mock
from psutil.tests import pytest
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import skip_on_access_denied
from psutil.tests import spawn_testproc
from psutil.tests import terminate
from psutil.tests import which


if POSIX:
    import mmap
    import resource

    from psutil._psutil_posix import getpagesize


def ps(fmt, pid=None):
    """Wrapper for calling the ps command with a little bit of cross-platform
    support for a narrow range of features.
    """

    cmd = ['ps']

    if LINUX:
        cmd.append('--no-headers')

    if pid is not None:
        cmd.extend(['-p', str(pid)])
    else:
        if SUNOS or AIX:
            cmd.append('-A')
        else:
            cmd.append('ax')

    if SUNOS:
        fmt = fmt.replace("start", "stime")

    cmd.extend(['-o', fmt])

    output = sh(cmd)

    output = output.splitlines() if LINUX else output.splitlines()[1:]

    all_output = []
    for line in output:
        line = line.strip()

        try:
            line = int(line)
        except ValueError:
            pass

        all_output.append(line)

    if pid is None:
        return all_output
    else:
        return all_output[0]


# ps "-o" field names differ wildly between platforms.
# "comm" means "only executable name" but is not available on BSD platforms.
# "args" means "command with all its arguments", and is also not available
# on BSD platforms.
# "command" is like "args" on most platforms, but like "comm" on AIX,
# and not available on SUNOS.
# so for the executable name we can use "comm" on Solaris and split "command"
# on other platforms.
# to get the cmdline (with args) we have to use "args" on AIX and
# Solaris, and can use "command" on all others.


def ps_name(pid):
    field = "command"
    if SUNOS:
        field = "comm"
    command = ps(field, pid).split()
    if QEMU_USER:
        assert "/bin/qemu-" in command[0]
        return command[1]
    return command[0]


def ps_args(pid):
    field = "command"
    if AIX or SUNOS:
        field = "args"
    out = ps(field, pid)
    # observed on BSD + Github CI: '/usr/local/bin/python3 -E -O (python3.9)'
    out = re.sub(r"\(python.*?\)$", "", out)
    return out.strip()


def ps_rss(pid):
    field = "rss"
    if AIX:
        field = "rssize"
    return ps(field, pid)


def ps_vsz(pid):
    field = "vsz"
    if AIX:
        field = "vsize"
    return ps(field, pid)


def df(device):
    try:
        out = sh("df -k %s" % device).strip()
    except RuntimeError as err:
        if "device busy" in str(err).lower():
            raise pytest.skip("df returned EBUSY")
        raise
    line = out.split('\n')[1]
    fields = line.split()
    sys_total = int(fields[1]) * 1024
    sys_used = int(fields[2]) * 1024
    sys_free = int(fields[3]) * 1024
    sys_percent = float(fields[4].replace('%', ''))
    return (sys_total, sys_used, sys_free, sys_percent)


@pytest.mark.skipif(not POSIX, reason="POSIX only")
class TestProcess(PsutilTestCase):
    """Compare psutil results against 'ps' command line utility (mainly)."""

    @classmethod
    def setUpClass(cls):
        cls.pid = spawn_testproc(
            [PYTHON_EXE, "-E", "-O"], stdin=subprocess.PIPE
        ).pid

    @classmethod
    def tearDownClass(cls):
        terminate(cls.pid)

    def test_ppid(self):
        ppid_ps = ps('ppid', self.pid)
        ppid_psutil = psutil.Process(self.pid).ppid()
        assert ppid_ps == ppid_psutil

    def test_uid(self):
        uid_ps = ps('uid', self.pid)
        uid_psutil = psutil.Process(self.pid).uids().real
        assert uid_ps == uid_psutil

    def test_gid(self):
        gid_ps = ps('rgid', self.pid)
        gid_psutil = psutil.Process(self.pid).gids().real
        assert gid_ps == gid_psutil

    def test_username(self):
        username_ps = ps('user', self.pid)
        username_psutil = psutil.Process(self.pid).username()
        assert username_ps == username_psutil

    def test_username_no_resolution(self):
        # Emulate a case where the system can't resolve the uid to
        # a username in which case psutil is supposed to return
        # the stringified uid.
        p = psutil.Process()
        with mock.patch("psutil.pwd.getpwuid", side_effect=KeyError) as fun:
            assert p.username() == str(p.uids().real)
            assert fun.called

    @skip_on_access_denied()
    @retry_on_failure()
    def test_rss_memory(self):
        # give python interpreter some time to properly initialize
        # so that the results are the same
        time.sleep(0.1)
        rss_ps = ps_rss(self.pid)
        rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024
        assert rss_ps == rss_psutil

    @skip_on_access_denied()
    @retry_on_failure()
    def test_vsz_memory(self):
        # give python interpreter some time to properly initialize
        # so that the results are the same
        time.sleep(0.1)
        vsz_ps = ps_vsz(self.pid)
        vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024
        assert vsz_ps == vsz_psutil

    def test_name(self):
        name_ps = ps_name(self.pid)
        # remove path if there is any, from the command
        name_ps = os.path.basename(name_ps).lower()
        name_psutil = psutil.Process(self.pid).name().lower()
        # ...because of how we calculate PYTHON_EXE; on MACOS this may
        # be "pythonX.Y".
        name_ps = re.sub(r"\d.\d", "", name_ps)
        name_psutil = re.sub(r"\d.\d", "", name_psutil)
        # ...may also be "python.X"
        name_ps = re.sub(r"\d", "", name_ps)
        name_psutil = re.sub(r"\d", "", name_psutil)
        assert name_ps == name_psutil

    def test_name_long(self):
        # On UNIX the kernel truncates the name to the first 15
        # characters. In such a case psutil tries to determine the
        # full name from the cmdline.
        name = "long-program-name"
        cmdline = ["long-program-name-extended", "foo", "bar"]
        with mock.patch("psutil._psplatform.Process.name", return_value=name):
            with mock.patch(
                "psutil._psplatform.Process.cmdline", return_value=cmdline
            ):
                p = psutil.Process()
                assert p.name() == "long-program-name-extended"

    def test_name_long_cmdline_ad_exc(self):
        # Same as above but emulates a case where cmdline() raises
        # AccessDenied in which case psutil is supposed to return
        # the truncated name instead of crashing.
        name = "long-program-name"
        with mock.patch("psutil._psplatform.Process.name", return_value=name):
            with mock.patch(
                "psutil._psplatform.Process.cmdline",
                side_effect=psutil.AccessDenied(0, ""),
            ):
                p = psutil.Process()
                assert p.name() == "long-program-name"

    def test_name_long_cmdline_nsp_exc(self):
        # Same as above but emulates a case where cmdline() raises NSP
        # which is supposed to propagate.
        name = "long-program-name"
        with mock.patch("psutil._psplatform.Process.name", return_value=name):
            with mock.patch(
                "psutil._psplatform.Process.cmdline",
                side_effect=psutil.NoSuchProcess(0, ""),
            ):
                p = psutil.Process()
                with pytest.raises(psutil.NoSuchProcess):
                    p.name()

    @pytest.mark.skipif(MACOS or BSD, reason="ps -o start not available")
    def test_create_time(self):
        time_ps = ps('start', self.pid)
        time_psutil = psutil.Process(self.pid).create_time()
        time_psutil_tstamp = datetime.datetime.fromtimestamp(
            time_psutil
        ).strftime("%H:%M:%S")
        # sometimes ps shows the time rounded up instead of down, so we check
        # for both possible values
        round_time_psutil = round(time_psutil)
        round_time_psutil_tstamp = datetime.datetime.fromtimestamp(
            round_time_psutil
        ).strftime("%H:%M:%S")
        assert time_ps in [time_psutil_tstamp, round_time_psutil_tstamp]

    def test_exe(self):
        ps_pathname = ps_name(self.pid)
        psutil_pathname = psutil.Process(self.pid).exe()
        try:
            assert ps_pathname == psutil_pathname
        except AssertionError:
            # certain platforms such as BSD are more accurate returning:
            # "/usr/local/bin/python2.7"
            # ...instead of:
            # "/usr/local/bin/python"
            # We do not want to consider this difference in accuracy
            # an error.
            adjusted_ps_pathname = ps_pathname[: len(ps_pathname)]
            assert ps_pathname == adjusted_ps_pathname

    # On macOS the official python installer exposes a python wrapper that
    # executes a python executable hidden inside an application bundle inside
    # the Python framework.
    # There's a race condition between the ps call & the psutil call below
    # depending on the completion of the execve call so let's retry on failure
    @retry_on_failure()
    def test_cmdline(self):
        ps_cmdline = ps_args(self.pid)
        psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline())
        if AARCH64 and len(ps_cmdline) < len(psutil_cmdline):
            assert psutil_cmdline.startswith(ps_cmdline)
        else:
            assert ps_cmdline == psutil_cmdline

    # On SUNOS "ps" reads niceness /proc/pid/psinfo which returns an
    # incorrect value (20); the real deal is getpriority(2) which
    # returns 0; psutil relies on it, see:
    # https://github.com/giampaolo/psutil/issues/1082
    # AIX has the same issue
    @pytest.mark.skipif(SUNOS, reason="not reliable on SUNOS")
    @pytest.mark.skipif(AIX, reason="not reliable on AIX")
    def test_nice(self):
        ps_nice = ps('nice', self.pid)
        psutil_nice = psutil.Process().nice()
        assert ps_nice == psutil_nice


@pytest.mark.skipif(not POSIX, reason="POSIX only")
class TestSystemAPIs(PsutilTestCase):
    """Test some system APIs."""

    @retry_on_failure()
    def test_pids(self):
        # Note: this test might fail if the OS is starting/killing
        # other processes in the meantime
        pids_ps = sorted(ps("pid"))
        pids_psutil = psutil.pids()

        # on MACOS and OPENBSD ps doesn't show pid 0
        if MACOS or (OPENBSD and 0 not in pids_ps):
            pids_ps.insert(0, 0)

        # There will often be one more process in pids_ps for ps itself
        if len(pids_ps) - len(pids_psutil) > 1:
            difference = [x for x in pids_psutil if x not in pids_ps] + [
                x for x in pids_ps if x not in pids_psutil
            ]
            raise self.fail("difference: " + str(difference))

    # for some reason ifconfig -a does not report all interfaces
    # returned by psutil
    @pytest.mark.skipif(SUNOS, reason="unreliable on SUNOS")
    @pytest.mark.skipif(not which('ifconfig'), reason="no ifconfig cmd")
    @pytest.mark.skipif(not HAS_NET_IO_COUNTERS, reason="not supported")
    def test_nic_names(self):
        output = sh("ifconfig -a")
        for nic in psutil.net_io_counters(pernic=True):
            for line in output.split():
                if line.startswith(nic):
                    break
            else:
                raise self.fail(
                    "couldn't find %s nic in 'ifconfig -a' output\n%s"
                    % (nic, output)
                )

    # @pytest.mark.skipif(CI_TESTING and not psutil.users(),
    #                     reason="unreliable on CI")
    @retry_on_failure()
    def test_users(self):
        out = sh("who -u")
        if not out.strip():
            raise pytest.skip("no users on this system")
        lines = out.split('\n')
        users = [x.split()[0] for x in lines]
        terminals = [x.split()[1] for x in lines]
        assert len(users) == len(psutil.users())
        with self.subTest(psutil=psutil.users(), who=out):
            for idx, u in enumerate(psutil.users()):
                assert u.name == users[idx]
                assert u.terminal == terminals[idx]
                if u.pid is not None:  # None on OpenBSD
                    psutil.Process(u.pid)

    @retry_on_failure()
    def test_users_started(self):
        out = sh("who -u")
        if not out.strip():
            raise pytest.skip("no users on this system")
        tstamp = None
        # '2023-04-11 09:31' (Linux)
        started = re.findall(r"\d\d\d\d-\d\d-\d\d \d\d:\d\d", out)
        if started:
            tstamp = "%Y-%m-%d %H:%M"
        else:
            # 'Apr 10 22:27' (macOS)
            started = re.findall(r"[A-Z][a-z][a-z] \d\d \d\d:\d\d", out)
            if started:
                tstamp = "%b %d %H:%M"
            else:
                # 'Apr 10'
                started = re.findall(r"[A-Z][a-z][a-z] \d\d", out)
                if started:
                    tstamp = "%b %d"
                else:
                    # 'apr 10' (sunOS)
                    started = re.findall(r"[a-z][a-z][a-z] \d\d", out)
                    if started:
                        tstamp = "%b %d"
                        started = [x.capitalize() for x in started]

        if not tstamp:
            raise pytest.skip(
                "cannot interpret tstamp in who output\n%s" % (out)
            )

        with self.subTest(psutil=psutil.users(), who=out):
            for idx, u in enumerate(psutil.users()):
                psutil_value = datetime.datetime.fromtimestamp(
                    u.started
                ).strftime(tstamp)
                assert psutil_value == started[idx]

    def test_pid_exists_let_raise(self):
        # According to "man 2 kill" possible error values for kill
        # are (EINVAL, EPERM, ESRCH). Test that any other errno
        # results in an exception.
        with mock.patch(
            "psutil._psposix.os.kill", side_effect=OSError(errno.EBADF, "")
        ) as m:
            with pytest.raises(OSError):
                psutil._psposix.pid_exists(os.getpid())
            assert m.called

    def test_os_waitpid_let_raise(self):
        # os.waitpid() is supposed to catch EINTR and ECHILD only.
        # Test that any other errno results in an exception.
        with mock.patch(
            "psutil._psposix.os.waitpid", side_effect=OSError(errno.EBADF, "")
        ) as m:
            with pytest.raises(OSError):
                psutil._psposix.wait_pid(os.getpid())
            assert m.called

    def test_os_waitpid_eintr(self):
        # os.waitpid() is supposed to "retry" on EINTR.
        with mock.patch(
            "psutil._psposix.os.waitpid", side_effect=OSError(errno.EINTR, "")
        ) as m:
            with pytest.raises(psutil._psposix.TimeoutExpired):
                psutil._psposix.wait_pid(os.getpid(), timeout=0.01)
            assert m.called

    def test_os_waitpid_bad_ret_status(self):
        # Simulate os.waitpid() returning a bad status.
        with mock.patch(
            "psutil._psposix.os.waitpid", return_value=(1, -1)
        ) as m:
            with pytest.raises(ValueError):
                psutil._psposix.wait_pid(os.getpid())
            assert m.called

    # AIX can return '-' in df output instead of numbers, e.g. for /proc
    @pytest.mark.skipif(AIX, reason="unreliable on AIX")
    @retry_on_failure()
    def test_disk_usage(self):
        tolerance = 4 * 1024 * 1024  # 4MB
        for part in psutil.disk_partitions(all=False):
            usage = psutil.disk_usage(part.mountpoint)
            try:
                sys_total, sys_used, sys_free, sys_percent = df(part.device)
            except RuntimeError as err:
                # see:
                # https://travis-ci.org/giampaolo/psutil/jobs/138338464
                # https://travis-ci.org/giampaolo/psutil/jobs/138343361
                err = str(err).lower()
                if (
                    "no such file or directory" in err
                    or "raw devices not supported" in err
                    or "permission denied" in err
                ):
                    continue
                raise
            else:
                assert abs(usage.total - sys_total) < tolerance
                assert abs(usage.used - sys_used) < tolerance
                assert abs(usage.free - sys_free) < tolerance
                assert abs(usage.percent - sys_percent) <= 1


@pytest.mark.skipif(not POSIX, reason="POSIX only")
class TestMisc(PsutilTestCase):
    def test_getpagesize(self):
        pagesize = getpagesize()
        assert pagesize > 0
        assert pagesize == resource.getpagesize()
        assert pagesize == mmap.PAGESIZE
PKok\�����psutil/tests/test_aix.pynu�[���#!/usr/bin/env python3

# Copyright (c) 2009, Giampaolo Rodola'
# Copyright (c) 2017, Arnon Yaari
# All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""AIX specific tests."""

import re

import psutil
from psutil import AIX
from psutil.tests import PsutilTestCase
from psutil.tests import pytest
from psutil.tests import sh


@pytest.mark.skipif(not AIX, reason="AIX only")
class AIXSpecificTestCase(PsutilTestCase):
    def test_virtual_memory(self):
        out = sh('/usr/bin/svmon -O unit=KB')
        re_pattern = r"memory\s*"
        for field in ("size inuse free pin virtual available mmode").split():
            re_pattern += r"(?P<%s>\S+)\s+" % (field,)
        matchobj = re.search(re_pattern, out)

        assert matchobj is not None

        KB = 1024
        total = int(matchobj.group("size")) * KB
        available = int(matchobj.group("available")) * KB
        used = int(matchobj.group("inuse")) * KB
        free = int(matchobj.group("free")) * KB

        psutil_result = psutil.virtual_memory()

        # TOLERANCE_SYS_MEM from psutil.tests is not enough. For some reason
        # we're seeing differences of ~1.2 MB. 2 MB is still a good tolerance
        # when compared to GBs.
        TOLERANCE_SYS_MEM = 2 * KB * KB  # 2 MB
        assert psutil_result.total == total
        assert abs(psutil_result.used - used) < TOLERANCE_SYS_MEM
        assert abs(psutil_result.available - available) < TOLERANCE_SYS_MEM
        assert abs(psutil_result.free - free) < TOLERANCE_SYS_MEM

    def test_swap_memory(self):
        out = sh('/usr/sbin/lsps -a')
        # From the man page, "The size is given in megabytes" so we assume
        # we'll always have 'MB' in the result
        # TODO maybe try to use "swap -l" to check "used" too, but its units
        # are not guaranteed to be "MB" so parsing may not be consistent
        matchobj = re.search(
            r"(?P<space>\S+)\s+"
            r"(?P<vol>\S+)\s+"
            r"(?P<vg>\S+)\s+"
            r"(?P<size>\d+)MB",
            out,
        )

        assert matchobj is not None

        total_mb = int(matchobj.group("size"))
        MB = 1024**2
        psutil_result = psutil.swap_memory()
        # we divide our result by MB instead of multiplying the lsps value by
        # MB because lsps may round down, so we round down too
        assert int(psutil_result.total / MB) == total_mb

    def test_cpu_stats(self):
        out = sh('/usr/bin/mpstat -a')

        re_pattern = r"ALL\s*"
        for field in (
            "min maj mpcs mpcr dev soft dec ph cs ics bound rq "
            "push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd "
            "sysc"
        ).split():
            re_pattern += r"(?P<%s>\S+)\s+" % (field,)
        matchobj = re.search(re_pattern, out)

        assert matchobj is not None

        # numbers are usually in the millions so 1000 is ok for tolerance
        CPU_STATS_TOLERANCE = 1000
        psutil_result = psutil.cpu_stats()
        assert (
            abs(psutil_result.ctx_switches - int(matchobj.group("cs")))
            < CPU_STATS_TOLERANCE
        )
        assert (
            abs(psutil_result.syscalls - int(matchobj.group("sysc")))
            < CPU_STATS_TOLERANCE
        )
        assert (
            abs(psutil_result.interrupts - int(matchobj.group("dev")))
            < CPU_STATS_TOLERANCE
        )
        assert (
            abs(psutil_result.soft_interrupts - int(matchobj.group("soft")))
            < CPU_STATS_TOLERANCE
        )

    def test_cpu_count_logical(self):
        out = sh('/usr/bin/mpstat -a')
        mpstat_lcpu = int(re.search(r"lcpu=(\d+)", out).group(1))
        psutil_lcpu = psutil.cpu_count(logical=True)
        assert mpstat_lcpu == psutil_lcpu

    def test_net_if_addrs_names(self):
        out = sh('/etc/ifconfig -l')
        ifconfig_names = set(out.split())
        psutil_names = set(psutil.net_if_addrs().keys())
        assert ifconfig_names == psutil_names
PKok\�$�B\B\psutil/__init__.pynu�[���# -*- coding: utf-8 -*-

# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""psutil is a cross-platform library for retrieving information on
running processes and system utilization (CPU, memory, disks, network,
sensors) in Python. Supported platforms:

 - Linux
 - Windows
 - macOS
 - FreeBSD
 - OpenBSD
 - NetBSD
 - Sun Solaris
 - AIX

Works with Python versions 2.7 and 3.6+.
"""

from __future__ import division

import collections
import contextlib
import datetime
import functools
import os
import signal
import subprocess
import sys
import threading
import time


try:
    import pwd
except ImportError:
    pwd = None

from . import _common
from ._common import AIX
from ._common import BSD
from ._common import CONN_CLOSE
from ._common import CONN_CLOSE_WAIT
from ._common import CONN_CLOSING
from ._common import CONN_ESTABLISHED
from ._common import CONN_FIN_WAIT1
from ._common import CONN_FIN_WAIT2
from ._common import CONN_LAST_ACK
from ._common import CONN_LISTEN
from ._common import CONN_NONE
from ._common import CONN_SYN_RECV
from ._common import CONN_SYN_SENT
from ._common import CONN_TIME_WAIT
from ._common import FREEBSD  # NOQA
from ._common import LINUX
from ._common import MACOS
from ._common import NETBSD  # NOQA
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import OPENBSD  # NOQA
from ._common import OSX  # deprecated alias
from ._common import POSIX  # NOQA
from ._common import POWER_TIME_UNKNOWN
from ._common import POWER_TIME_UNLIMITED
from ._common import STATUS_DEAD
from ._common import STATUS_DISK_SLEEP
from ._common import STATUS_IDLE
from ._common import STATUS_LOCKED
from ._common import STATUS_PARKED
from ._common import STATUS_RUNNING
from ._common import STATUS_SLEEPING
from ._common import STATUS_STOPPED
from ._common import STATUS_TRACING_STOP
from ._common import STATUS_WAITING
from ._common import STATUS_WAKING
from ._common import STATUS_ZOMBIE
from ._common import SUNOS
from ._common import WINDOWS
from ._common import AccessDenied
from ._common import Error
from ._common import NoSuchProcess
from ._common import TimeoutExpired
from ._common import ZombieProcess
from ._common import debug
from ._common import memoize_when_activated
from ._common import wrap_numbers as _wrap_numbers
from ._compat import PY3 as _PY3
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import SubprocessTimeoutExpired as _SubprocessTimeoutExpired
from ._compat import long


if LINUX:
    # This is public API and it will be retrieved from _pslinux.py
    # via sys.modules.
    PROCFS_PATH = "/proc"

    from . import _pslinux as _psplatform
    from ._pslinux import IOPRIO_CLASS_BE  # NOQA
    from ._pslinux import IOPRIO_CLASS_IDLE  # NOQA
    from ._pslinux import IOPRIO_CLASS_NONE  # NOQA
    from ._pslinux import IOPRIO_CLASS_RT  # NOQA

elif WINDOWS:
    from . import _pswindows as _psplatform
    from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS  # NOQA
    from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS  # NOQA
    from ._psutil_windows import HIGH_PRIORITY_CLASS  # NOQA
    from ._psutil_windows import IDLE_PRIORITY_CLASS  # NOQA
    from ._psutil_windows import NORMAL_PRIORITY_CLASS  # NOQA
    from ._psutil_windows import REALTIME_PRIORITY_CLASS  # NOQA
    from ._pswindows import CONN_DELETE_TCB  # NOQA
    from ._pswindows import IOPRIO_HIGH  # NOQA
    from ._pswindows import IOPRIO_LOW  # NOQA
    from ._pswindows import IOPRIO_NORMAL  # NOQA
    from ._pswindows import IOPRIO_VERYLOW  # NOQA

elif MACOS:
    from . import _psosx as _psplatform

elif BSD:
    from . import _psbsd as _psplatform

elif SUNOS:
    from . import _pssunos as _psplatform
    from ._pssunos import CONN_BOUND  # NOQA
    from ._pssunos import CONN_IDLE  # NOQA

    # This is public writable API which is read from _pslinux.py and
    # _pssunos.py via sys.modules.
    PROCFS_PATH = "/proc"

elif AIX:
    from . import _psaix as _psplatform

    # This is public API and it will be retrieved from _pslinux.py
    # via sys.modules.
    PROCFS_PATH = "/proc"

else:  # pragma: no cover
    raise NotImplementedError('platform %s is not supported' % sys.platform)


# fmt: off
__all__ = [
    # exceptions
    "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied",
    "TimeoutExpired",

    # constants
    "version_info", "__version__",

    "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
    "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
    "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED",
    "STATUS_PARKED",

    "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1",
    "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
    "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE",
    # "CONN_IDLE", "CONN_BOUND",

    "AF_LINK",

    "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN",

    "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED",

    "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX",
    "SUNOS", "WINDOWS", "AIX",

    # "RLIM_INFINITY", "RLIMIT_AS", "RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA",
    # "RLIMIT_FSIZE", "RLIMIT_LOCKS", "RLIMIT_MEMLOCK", "RLIMIT_NOFILE",
    # "RLIMIT_NPROC", "RLIMIT_RSS", "RLIMIT_STACK", "RLIMIT_MSGQUEUE",
    # "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIMIT_SIGPENDING",

    # classes
    "Process", "Popen",

    # functions
    "pid_exists", "pids", "process_iter", "wait_procs",             # proc
    "virtual_memory", "swap_memory",                                # memory
    "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count",   # cpu
    "cpu_stats",  # "cpu_freq", "getloadavg"
    "net_io_counters", "net_connections", "net_if_addrs",           # network
    "net_if_stats",
    "disk_io_counters", "disk_partitions", "disk_usage",            # disk
    # "sensors_temperatures", "sensors_battery", "sensors_fans"     # sensors
    "users", "boot_time",                                           # others
]
# fmt: on


__all__.extend(_psplatform.__extra__all__)

# Linux, FreeBSD
if hasattr(_psplatform.Process, "rlimit"):
    # Populate global namespace with RLIM* constants.
    from . import _psutil_posix

    _globals = globals()
    _name = None
    for _name in dir(_psutil_posix):
        if _name.startswith('RLIM') and _name.isupper():
            _globals[_name] = getattr(_psutil_posix, _name)
            __all__.append(_name)
    del _globals, _name

AF_LINK = _psplatform.AF_LINK

__author__ = "Giampaolo Rodola'"
__version__ = "6.1.0"
version_info = tuple([int(num) for num in __version__.split('.')])

_timer = getattr(time, 'monotonic', time.time)
_TOTAL_PHYMEM = None
_LOWEST_PID = None
_SENTINEL = object()

# Sanity check in case the user messed up with psutil installation
# or did something weird with sys.path. In this case we might end
# up importing a python module using a C extension module which
# was compiled for a different version of psutil.
# We want to prevent that by failing sooner rather than later.
# See: https://github.com/giampaolo/psutil/issues/564
if int(__version__.replace('.', '')) != getattr(
    _psplatform.cext, 'version', None
):
    msg = "version conflict: %r C extension " % _psplatform.cext.__file__
    msg += "module was built for another version of psutil"
    if hasattr(_psplatform.cext, 'version'):
        msg += " (%s instead of %s)" % (
            '.'.join([x for x in str(_psplatform.cext.version)]),
            __version__,
        )
    else:
        msg += " (different than %s)" % __version__
    msg += "; you may try to 'pip uninstall psutil', manually remove %s" % (
        getattr(
            _psplatform.cext,
            "__file__",
            "the existing psutil install directory",
        )
    )
    msg += " or clean the virtual env somehow, then reinstall"
    raise ImportError(msg)


# =====================================================================
# --- Utils
# =====================================================================


if hasattr(_psplatform, 'ppid_map'):
    # Faster version (Windows and Linux).
    _ppid_map = _psplatform.ppid_map
else:  # pragma: no cover

    def _ppid_map():
        """Return a {pid: ppid, ...} dict for all running processes in
        one shot. Used to speed up Process.children().
        """
        ret = {}
        for pid in pids():
            try:
                ret[pid] = _psplatform.Process(pid).ppid()
            except (NoSuchProcess, ZombieProcess):
                pass
        return ret


def _pprint_secs(secs):
    """Format seconds in a human readable form."""
    now = time.time()
    secs_ago = int(now - secs)
    fmt = "%H:%M:%S" if secs_ago < 60 * 60 * 24 else "%Y-%m-%d %H:%M:%S"
    return datetime.datetime.fromtimestamp(secs).strftime(fmt)


# =====================================================================
# --- Process class
# =====================================================================


class Process(object):  # noqa: UP004
    """Represents an OS process with the given PID.
    If PID is omitted current process PID (os.getpid()) is used.
    Raise NoSuchProcess if PID does not exist.

    Note that most of the methods of this class do not make sure that
    the PID of the process being queried has been reused. That means
    that you may end up retrieving information for another process.

    The only exceptions for which process identity is pre-emptively
    checked and guaranteed are:

     - parent()
     - children()
     - nice() (set)
     - ionice() (set)
     - rlimit() (set)
     - cpu_affinity (set)
     - suspend()
     - resume()
     - send_signal()
     - terminate()
     - kill()

    To prevent this problem for all other methods you can use
    is_running() before querying the process.
    """

    def __init__(self, pid=None):
        self._init(pid)

    def _init(self, pid, _ignore_nsp=False):
        if pid is None:
            pid = os.getpid()
        else:
            if not _PY3 and not isinstance(pid, (int, long)):
                msg = "pid must be an integer (got %r)" % pid
                raise TypeError(msg)
            if pid < 0:
                msg = "pid must be a positive integer (got %s)" % pid
                raise ValueError(msg)
            try:
                _psplatform.cext.check_pid_range(pid)
            except OverflowError:
                msg = "process PID out of range (got %s)" % pid
                raise NoSuchProcess(pid, msg=msg)

        self._pid = pid
        self._name = None
        self._exe = None
        self._create_time = None
        self._gone = False
        self._pid_reused = False
        self._hash = None
        self._lock = threading.RLock()
        # used for caching on Windows only (on POSIX ppid may change)
        self._ppid = None
        # platform-specific modules define an _psplatform.Process
        # implementation class
        self._proc = _psplatform.Process(pid)
        self._last_sys_cpu_times = None
        self._last_proc_cpu_times = None
        self._exitcode = _SENTINEL
        self._ident = (self.pid, None)
        try:
            self._ident = self._get_ident()
        except AccessDenied:
            # This should happen on Windows only, since we use the fast
            # create time method. AFAIK, on all other platforms we are
            # able to get create time for all PIDs.
            pass
        except ZombieProcess:
            # Zombies can still be queried by this class (although
            # not always) and pids() return them so just go on.
            pass
        except NoSuchProcess:
            if not _ignore_nsp:
                msg = "process PID not found"
                raise NoSuchProcess(pid, msg=msg)
            else:
                self._gone = True

    def _get_ident(self):
        """Return a (pid, uid) tuple which is supposed to identify a
        Process instance univocally over time. The PID alone is not
        enough, as it can be assigned to a new process after this one
        terminates, so we add process creation time to the mix. We need
        this in order to prevent killing the wrong process later on.
        This is also known as PID reuse or PID recycling problem.

        The reliability of this strategy mostly depends on
        create_time() precision, which is 0.01 secs on Linux. The
        assumption is that, after a process terminates, the kernel
        won't reuse the same PID after such a short period of time
        (0.01 secs). Technically this is inherently racy, but
        practically it should be good enough.
        """
        if WINDOWS:
            # Use create_time() fast method in order to speedup
            # `process_iter()`. This means we'll get AccessDenied for
            # most ADMIN processes, but that's fine since it means
            # we'll also get AccessDenied on kill().
            # https://github.com/giampaolo/psutil/issues/2366#issuecomment-2381646555
            self._create_time = self._proc.create_time(fast_only=True)
            return (self.pid, self._create_time)
        else:
            return (self.pid, self.create_time())

    def __str__(self):
        info = collections.OrderedDict()
        info["pid"] = self.pid
        if self._name:
            info['name'] = self._name
        with self.oneshot():
            if self._pid_reused:
                info["status"] = "terminated + PID reused"
            else:
                try:
                    info["name"] = self.name()
                    info["status"] = self.status()
                except ZombieProcess:
                    info["status"] = "zombie"
                except NoSuchProcess:
                    info["status"] = "terminated"
                except AccessDenied:
                    pass

            if self._exitcode not in (_SENTINEL, None):
                info["exitcode"] = self._exitcode
            if self._create_time is not None:
                info['started'] = _pprint_secs(self._create_time)

            return "%s.%s(%s)" % (
                self.__class__.__module__,
                self.__class__.__name__,
                ", ".join(["%s=%r" % (k, v) for k, v in info.items()]),
            )

    __repr__ = __str__

    def __eq__(self, other):
        # Test for equality with another Process object based
        # on PID and creation time.
        if not isinstance(other, Process):
            return NotImplemented
        if OPENBSD or NETBSD:  # pragma: no cover
            # Zombie processes on Open/NetBSD have a creation time of
            # 0.0. This covers the case when a process started normally
            # (so it has a ctime), then it turned into a zombie. It's
            # important to do this because is_running() depends on
            # __eq__.
            pid1, ident1 = self._ident
            pid2, ident2 = other._ident
            if pid1 == pid2:
                if ident1 and not ident2:
                    try:
                        return self.status() == STATUS_ZOMBIE
                    except Error:
                        pass
        return self._ident == other._ident

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        if self._hash is None:
            self._hash = hash(self._ident)
        return self._hash

    def _raise_if_pid_reused(self):
        """Raises NoSuchProcess in case process PID has been reused."""
        if self._pid_reused or (not self.is_running() and self._pid_reused):
            # We may directly raise NSP in here already if PID is just
            # not running, but I prefer NSP to be raised naturally by
            # the actual Process API call. This way unit tests will tell
            # us if the API is broken (aka don't raise NSP when it
            # should). We also remain consistent with all other "get"
            # APIs which don't use _raise_if_pid_reused().
            msg = "process no longer exists and its PID has been reused"
            raise NoSuchProcess(self.pid, self._name, msg=msg)

    @property
    def pid(self):
        """The process PID."""
        return self._pid

    # --- utility methods

    @contextlib.contextmanager
    def oneshot(self):
        """Utility context manager which considerably speeds up the
        retrieval of multiple process information at the same time.

        Internally different process info (e.g. name, ppid, uids,
        gids, ...) may be fetched by using the same routine, but
        only one information is returned and the others are discarded.
        When using this context manager the internal routine is
        executed once (in the example below on name()) and the
        other info are cached.

        The cache is cleared when exiting the context manager block.
        The advice is to use this every time you retrieve more than
        one information about the process. If you're lucky, you'll
        get a hell of a speedup.

        >>> import psutil
        >>> p = psutil.Process()
        >>> with p.oneshot():
        ...     p.name()  # collect multiple info
        ...     p.cpu_times()  # return cached value
        ...     p.cpu_percent()  # return cached value
        ...     p.create_time()  # return cached value
        ...
        >>>
        """
        with self._lock:
            if hasattr(self, "_cache"):
                # NOOP: this covers the use case where the user enters the
                # context twice:
                #
                # >>> with p.oneshot():
                # ...    with p.oneshot():
                # ...
                #
                # Also, since as_dict() internally uses oneshot()
                # I expect that the code below will be a pretty common
                # "mistake" that the user will make, so let's guard
                # against that:
                #
                # >>> with p.oneshot():
                # ...    p.as_dict()
                # ...
                yield
            else:
                try:
                    # cached in case cpu_percent() is used
                    self.cpu_times.cache_activate(self)
                    # cached in case memory_percent() is used
                    self.memory_info.cache_activate(self)
                    # cached in case parent() is used
                    self.ppid.cache_activate(self)
                    # cached in case username() is used
                    if POSIX:
                        self.uids.cache_activate(self)
                    # specific implementation cache
                    self._proc.oneshot_enter()
                    yield
                finally:
                    self.cpu_times.cache_deactivate(self)
                    self.memory_info.cache_deactivate(self)
                    self.ppid.cache_deactivate(self)
                    if POSIX:
                        self.uids.cache_deactivate(self)
                    self._proc.oneshot_exit()

    def as_dict(self, attrs=None, ad_value=None):
        """Utility method returning process information as a
        hashable dictionary.
        If *attrs* is specified it must be a list of strings
        reflecting available Process class' attribute names
        (e.g. ['cpu_times', 'name']) else all public (read
        only) attributes are assumed.
        *ad_value* is the value which gets assigned in case
        AccessDenied or ZombieProcess exception is raised when
        retrieving that particular process information.
        """
        valid_names = _as_dict_attrnames
        if attrs is not None:
            if not isinstance(attrs, (list, tuple, set, frozenset)):
                msg = "invalid attrs type %s" % type(attrs)
                raise TypeError(msg)
            attrs = set(attrs)
            invalid_names = attrs - valid_names
            if invalid_names:
                msg = "invalid attr name%s %s" % (
                    "s" if len(invalid_names) > 1 else "",
                    ", ".join(map(repr, invalid_names)),
                )
                raise ValueError(msg)

        retdict = {}
        ls = attrs or valid_names
        with self.oneshot():
            for name in ls:
                try:
                    if name == 'pid':
                        ret = self.pid
                    else:
                        meth = getattr(self, name)
                        ret = meth()
                except (AccessDenied, ZombieProcess):
                    ret = ad_value
                except NotImplementedError:
                    # in case of not implemented functionality (may happen
                    # on old or exotic systems) we want to crash only if
                    # the user explicitly asked for that particular attr
                    if attrs:
                        raise
                    continue
                retdict[name] = ret
        return retdict

    def parent(self):
        """Return the parent process as a Process object pre-emptively
        checking whether PID has been reused.
        If no parent is known return None.
        """
        lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0]
        if self.pid == lowest_pid:
            return None
        ppid = self.ppid()
        if ppid is not None:
            ctime = self.create_time()
            try:
                parent = Process(ppid)
                if parent.create_time() <= ctime:
                    return parent
                # ...else ppid has been reused by another process
            except NoSuchProcess:
                pass

    def parents(self):
        """Return the parents of this process as a list of Process
        instances. If no parents are known return an empty list.
        """
        parents = []
        proc = self.parent()
        while proc is not None:
            parents.append(proc)
            proc = proc.parent()
        return parents

    def is_running(self):
        """Return whether this process is running.

        It also checks if PID has been reused by another process, in
        which case it will remove the process from `process_iter()`
        internal cache and return False.
        """
        if self._gone or self._pid_reused:
            return False
        try:
            # Checking if PID is alive is not enough as the PID might
            # have been reused by another process. Process identity /
            # uniqueness over time is guaranteed by (PID + creation
            # time) and that is verified in __eq__.
            self._pid_reused = self != Process(self.pid)
            if self._pid_reused:
                _pids_reused.add(self.pid)
                raise NoSuchProcess(self.pid)
            return True
        except ZombieProcess:
            # We should never get here as it's already handled in
            # Process.__init__; here just for extra safety.
            return True
        except NoSuchProcess:
            self._gone = True
            return False

    # --- actual API

    @memoize_when_activated
    def ppid(self):
        """The process parent PID.
        On Windows the return value is cached after first call.
        """
        # On POSIX we don't want to cache the ppid as it may unexpectedly
        # change to 1 (init) in case this process turns into a zombie:
        # https://github.com/giampaolo/psutil/issues/321
        # http://stackoverflow.com/questions/356722/

        # XXX should we check creation time here rather than in
        # Process.parent()?
        self._raise_if_pid_reused()
        if POSIX:
            return self._proc.ppid()
        else:  # pragma: no cover
            self._ppid = self._ppid or self._proc.ppid()
            return self._ppid

    def name(self):
        """The process name. The return value is cached after first call."""
        # Process name is only cached on Windows as on POSIX it may
        # change, see:
        # https://github.com/giampaolo/psutil/issues/692
        if WINDOWS and self._name is not None:
            return self._name
        name = self._proc.name()
        if POSIX and len(name) >= 15:
            # On UNIX the name gets truncated to the first 15 characters.
            # If it matches the first part of the cmdline we return that
            # one instead because it's usually more explicative.
            # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon".
            try:
                cmdline = self.cmdline()
            except (AccessDenied, ZombieProcess):
                # Just pass and return the truncated name: it's better
                # than nothing. Note: there are actual cases where a
                # zombie process can return a name() but not a
                # cmdline(), see:
                # https://github.com/giampaolo/psutil/issues/2239
                pass
            else:
                if cmdline:
                    extended_name = os.path.basename(cmdline[0])
                    if extended_name.startswith(name):
                        name = extended_name
        self._name = name
        self._proc._name = name
        return name

    def exe(self):
        """The process executable as an absolute path.
        May also be an empty string.
        The return value is cached after first call.
        """

        def guess_it(fallback):
            # try to guess exe from cmdline[0] in absence of a native
            # exe representation
            cmdline = self.cmdline()
            if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'):
                exe = cmdline[0]  # the possible exe
                # Attempt to guess only in case of an absolute path.
                # It is not safe otherwise as the process might have
                # changed cwd.
                if (
                    os.path.isabs(exe)
                    and os.path.isfile(exe)
                    and os.access(exe, os.X_OK)
                ):
                    return exe
            if isinstance(fallback, AccessDenied):
                raise fallback
            return fallback

        if self._exe is None:
            try:
                exe = self._proc.exe()
            except AccessDenied as err:
                return guess_it(fallback=err)
            else:
                if not exe:
                    # underlying implementation can legitimately return an
                    # empty string; if that's the case we don't want to
                    # raise AD while guessing from the cmdline
                    try:
                        exe = guess_it(fallback=exe)
                    except AccessDenied:
                        pass
                self._exe = exe
        return self._exe

    def cmdline(self):
        """The command line this process has been called with."""
        return self._proc.cmdline()

    def status(self):
        """The process current status as a STATUS_* constant."""
        try:
            return self._proc.status()
        except ZombieProcess:
            return STATUS_ZOMBIE

    def username(self):
        """The name of the user that owns the process.
        On UNIX this is calculated by using *real* process uid.
        """
        if POSIX:
            if pwd is None:
                # might happen if python was installed from sources
                msg = "requires pwd module shipped with standard python"
                raise ImportError(msg)
            real_uid = self.uids().real
            try:
                return pwd.getpwuid(real_uid).pw_name
            except KeyError:
                # the uid can't be resolved by the system
                return str(real_uid)
        else:
            return self._proc.username()

    def create_time(self):
        """The process creation time as a floating point number
        expressed in seconds since the epoch.
        The return value is cached after first call.
        """
        if self._create_time is None:
            self._create_time = self._proc.create_time()
        return self._create_time

    def cwd(self):
        """Process current working directory as an absolute path."""
        return self._proc.cwd()

    def nice(self, value=None):
        """Get or set process niceness (priority)."""
        if value is None:
            return self._proc.nice_get()
        else:
            self._raise_if_pid_reused()
            self._proc.nice_set(value)

    if POSIX:

        @memoize_when_activated
        def uids(self):
            """Return process UIDs as a (real, effective, saved)
            namedtuple.
            """
            return self._proc.uids()

        def gids(self):
            """Return process GIDs as a (real, effective, saved)
            namedtuple.
            """
            return self._proc.gids()

        def terminal(self):
            """The terminal associated with this process, if any,
            else None.
            """
            return self._proc.terminal()

        def num_fds(self):
            """Return the number of file descriptors opened by this
            process (POSIX only).
            """
            return self._proc.num_fds()

    # Linux, BSD, AIX and Windows only
    if hasattr(_psplatform.Process, "io_counters"):

        def io_counters(self):
            """Return process I/O statistics as a
            (read_count, write_count, read_bytes, write_bytes)
            namedtuple.
            Those are the number of read/write calls performed and the
            amount of bytes read and written by the process.
            """
            return self._proc.io_counters()

    # Linux and Windows
    if hasattr(_psplatform.Process, "ionice_get"):

        def ionice(self, ioclass=None, value=None):
            """Get or set process I/O niceness (priority).

            On Linux *ioclass* is one of the IOPRIO_CLASS_* constants.
            *value* is a number which goes from 0 to 7. The higher the
            value, the lower the I/O priority of the process.

            On Windows only *ioclass* is used and it can be set to 2
            (normal), 1 (low) or 0 (very low).

            Available on Linux and Windows > Vista only.
            """
            if ioclass is None:
                if value is not None:
                    msg = "'ioclass' argument must be specified"
                    raise ValueError(msg)
                return self._proc.ionice_get()
            else:
                self._raise_if_pid_reused()
                return self._proc.ionice_set(ioclass, value)

    # Linux / FreeBSD only
    if hasattr(_psplatform.Process, "rlimit"):

        def rlimit(self, resource, limits=None):
            """Get or set process resource limits as a (soft, hard)
            tuple.

            *resource* is one of the RLIMIT_* constants.
            *limits* is supposed to be a (soft, hard) tuple.

            See "man prlimit" for further info.
            Available on Linux and FreeBSD only.
            """
            if limits is not None:
                self._raise_if_pid_reused()
            return self._proc.rlimit(resource, limits)

    # Windows, Linux and FreeBSD only
    if hasattr(_psplatform.Process, "cpu_affinity_get"):

        def cpu_affinity(self, cpus=None):
            """Get or set process CPU affinity.
            If specified, *cpus* must be a list of CPUs for which you
            want to set the affinity (e.g. [0, 1]).
            If an empty list is passed, all egible CPUs are assumed
            (and set).
            (Windows, Linux and BSD only).
            """
            if cpus is None:
                return sorted(set(self._proc.cpu_affinity_get()))
            else:
                self._raise_if_pid_reused()
                if not cpus:
                    if hasattr(self._proc, "_get_eligible_cpus"):
                        cpus = self._proc._get_eligible_cpus()
                    else:
                        cpus = tuple(range(len(cpu_times(percpu=True))))
                self._proc.cpu_affinity_set(list(set(cpus)))

    # Linux, FreeBSD, SunOS
    if hasattr(_psplatform.Process, "cpu_num"):

        def cpu_num(self):
            """Return what CPU this process is currently running on.
            The returned number should be <= psutil.cpu_count()
            and <= len(psutil.cpu_percent(percpu=True)).
            It may be used in conjunction with
            psutil.cpu_percent(percpu=True) to observe the system
            workload distributed across CPUs.
            """
            return self._proc.cpu_num()

    # All platforms has it, but maybe not in the future.
    if hasattr(_psplatform.Process, "environ"):

        def environ(self):
            """The environment variables of the process as a dict.  Note: this
            might not reflect changes made after the process started.
            """
            return self._proc.environ()

    if WINDOWS:

        def num_handles(self):
            """Return the number of handles opened by this process
            (Windows only).
            """
            return self._proc.num_handles()

    def num_ctx_switches(self):
        """Return the number of voluntary and involuntary context
        switches performed by this process.
        """
        return self._proc.num_ctx_switches()

    def num_threads(self):
        """Return the number of threads used by this process."""
        return self._proc.num_threads()

    if hasattr(_psplatform.Process, "threads"):

        def threads(self):
            """Return threads opened by process as a list of
            (id, user_time, system_time) namedtuples representing
            thread id and thread CPU times (user/system).
            On OpenBSD this method requires root access.
            """
            return self._proc.threads()

    def children(self, recursive=False):
        """Return the children of this process as a list of Process
        instances, pre-emptively checking whether PID has been reused.
        If *recursive* is True return all the parent descendants.

        Example (A == this process):

         A ─┐
            │
            ├─ B (child) ─┐
            │             └─ X (grandchild) ─┐
            │                                └─ Y (great grandchild)
            ├─ C (child)
            └─ D (child)

        >>> import psutil
        >>> p = psutil.Process()
        >>> p.children()
        B, C, D
        >>> p.children(recursive=True)
        B, X, Y, C, D

        Note that in the example above if process X disappears
        process Y won't be listed as the reference to process A
        is lost.
        """
        self._raise_if_pid_reused()
        ppid_map = _ppid_map()
        ret = []
        if not recursive:
            for pid, ppid in ppid_map.items():
                if ppid == self.pid:
                    try:
                        child = Process(pid)
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        if self.create_time() <= child.create_time():
                            ret.append(child)
                    except (NoSuchProcess, ZombieProcess):
                        pass
        else:
            # Construct a {pid: [child pids]} dict
            reverse_ppid_map = collections.defaultdict(list)
            for pid, ppid in ppid_map.items():
                reverse_ppid_map[ppid].append(pid)
            # Recursively traverse that dict, starting from self.pid,
            # such that we only call Process() on actual children
            seen = set()
            stack = [self.pid]
            while stack:
                pid = stack.pop()
                if pid in seen:
                    # Since pids can be reused while the ppid_map is
                    # constructed, there may be rare instances where
                    # there's a cycle in the recorded process "tree".
                    continue
                seen.add(pid)
                for child_pid in reverse_ppid_map[pid]:
                    try:
                        child = Process(child_pid)
                        # if child happens to be older than its parent
                        # (self) it means child's PID has been reused
                        intime = self.create_time() <= child.create_time()
                        if intime:
                            ret.append(child)
                            stack.append(child_pid)
                    except (NoSuchProcess, ZombieProcess):
                        pass
        return ret

    def cpu_percent(self, interval=None):
        """Return a float representing the current process CPU
        utilization as a percentage.

        When *interval* is 0.0 or None (default) compares process times
        to system CPU times elapsed since last call, returning
        immediately (non-blocking). That means that the first time
        this is called it will return a meaningful 0.0 value.

        When *interval* is > 0.0 compares process times to system CPU
        times elapsed before and after the interval (blocking).

        In this case is recommended for accuracy that this function
        be called with at least 0.1 seconds between calls.

        A value > 100.0 can be returned in case of processes running
        multiple threads on different CPU cores.

        The returned value is explicitly NOT split evenly between
        all available logical CPUs. This means that a busy loop process
        running on a system with 2 logical CPUs will be reported as
        having 100% CPU utilization instead of 50%.

        Examples:

          >>> import psutil
          >>> p = psutil.Process(os.getpid())
          >>> # blocking
          >>> p.cpu_percent(interval=1)
          2.0
          >>> # non-blocking (percentage since last call)
          >>> p.cpu_percent(interval=None)
          2.9
          >>>
        """
        blocking = interval is not None and interval > 0.0
        if interval is not None and interval < 0:
            msg = "interval is not positive (got %r)" % interval
            raise ValueError(msg)
        num_cpus = cpu_count() or 1

        def timer():
            return _timer() * num_cpus

        if blocking:
            st1 = timer()
            pt1 = self._proc.cpu_times()
            time.sleep(interval)
            st2 = timer()
            pt2 = self._proc.cpu_times()
        else:
            st1 = self._last_sys_cpu_times
            pt1 = self._last_proc_cpu_times
            st2 = timer()
            pt2 = self._proc.cpu_times()
            if st1 is None or pt1 is None:
                self._last_sys_cpu_times = st2
                self._last_proc_cpu_times = pt2
                return 0.0

        delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system)
        delta_time = st2 - st1
        # reset values for next call in case of interval == None
        self._last_sys_cpu_times = st2
        self._last_proc_cpu_times = pt2

        try:
            # This is the utilization split evenly between all CPUs.
            # E.g. a busy loop process on a 2-CPU-cores system at this
            # point is reported as 50% instead of 100%.
            overall_cpus_percent = (delta_proc / delta_time) * 100
        except ZeroDivisionError:
            # interval was too low
            return 0.0
        else:
            # Note 1:
            # in order to emulate "top" we multiply the value for the num
            # of CPU cores. This way the busy process will be reported as
            # having 100% (or more) usage.
            #
            # Note 2:
            # taskmgr.exe on Windows differs in that it will show 50%
            # instead.
            #
            # Note 3:
            # a percentage > 100 is legitimate as it can result from a
            # process with multiple threads running on different CPU
            # cores (top does the same), see:
            # http://stackoverflow.com/questions/1032357
            # https://github.com/giampaolo/psutil/issues/474
            single_cpu_percent = overall_cpus_percent * num_cpus
            return round(single_cpu_percent, 1)

    @memoize_when_activated
    def cpu_times(self):
        """Return a (user, system, children_user, children_system)
        namedtuple representing the accumulated process time, in
        seconds.
        This is similar to os.times() but per-process.
        On macOS and Windows children_user and children_system are
        always set to 0.
        """
        return self._proc.cpu_times()

    @memoize_when_activated
    def memory_info(self):
        """Return a namedtuple with variable fields depending on the
        platform, representing memory information about the process.

        The "portable" fields available on all platforms are `rss` and `vms`.

        All numbers are expressed in bytes.
        """
        return self._proc.memory_info()

    @_common.deprecated_method(replacement="memory_info")
    def memory_info_ex(self):
        return self.memory_info()

    def memory_full_info(self):
        """This method returns the same information as memory_info(),
        plus, on some platform (Linux, macOS, Windows), also provides
        additional metrics (USS, PSS and swap).
        The additional metrics provide a better representation of actual
        process memory usage.

        Namely USS is the memory which is unique to a process and which
        would be freed if the process was terminated right now.

        It does so by passing through the whole process address.
        As such it usually requires higher user privileges than
        memory_info() and is considerably slower.
        """
        return self._proc.memory_full_info()

    def memory_percent(self, memtype="rss"):
        """Compare process memory to total physical system memory and
        calculate process memory utilization as a percentage.
        *memtype* argument is a string that dictates what type of
        process memory you want to compare against (defaults to "rss").
        The list of available strings can be obtained like this:

        >>> psutil.Process().memory_info()._fields
        ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss')
        """
        valid_types = list(_psplatform.pfullmem._fields)
        if memtype not in valid_types:
            msg = "invalid memtype %r; valid types are %r" % (
                memtype,
                tuple(valid_types),
            )
            raise ValueError(msg)
        fun = (
            self.memory_info
            if memtype in _psplatform.pmem._fields
            else self.memory_full_info
        )
        metrics = fun()
        value = getattr(metrics, memtype)

        # use cached value if available
        total_phymem = _TOTAL_PHYMEM or virtual_memory().total
        if not total_phymem > 0:
            # we should never get here
            msg = (
                "can't calculate process memory percent because total physical"
                " system memory is not positive (%r)" % (total_phymem)
            )
            raise ValueError(msg)
        return (value / float(total_phymem)) * 100

    if hasattr(_psplatform.Process, "memory_maps"):

        def memory_maps(self, grouped=True):
            """Return process' mapped memory regions as a list of namedtuples
            whose fields are variable depending on the platform.

            If *grouped* is True the mapped regions with the same 'path'
            are grouped together and the different memory fields are summed.

            If *grouped* is False every mapped region is shown as a single
            entity and the namedtuple will also include the mapped region's
            address space ('addr') and permission set ('perms').
            """
            it = self._proc.memory_maps()
            if grouped:
                d = {}
                for tupl in it:
                    path = tupl[2]
                    nums = tupl[3:]
                    try:
                        d[path] = map(lambda x, y: x + y, d[path], nums)
                    except KeyError:
                        d[path] = nums
                nt = _psplatform.pmmap_grouped
                return [nt(path, *d[path]) for path in d]  # NOQA
            else:
                nt = _psplatform.pmmap_ext
                return [nt(*x) for x in it]

    def open_files(self):
        """Return files opened by process as a list of
        (path, fd) namedtuples including the absolute file name
        and file descriptor number.
        """
        return self._proc.open_files()

    def net_connections(self, kind='inet'):
        """Return socket connections opened by process as a list of
        (fd, family, type, laddr, raddr, status) namedtuples.
        The *kind* parameter filters for connections that match the
        following criteria:

        +------------+----------------------------------------------------+
        | Kind Value | Connections using                                  |
        +------------+----------------------------------------------------+
        | inet       | IPv4 and IPv6                                      |
        | inet4      | IPv4                                               |
        | inet6      | IPv6                                               |
        | tcp        | TCP                                                |
        | tcp4       | TCP over IPv4                                      |
        | tcp6       | TCP over IPv6                                      |
        | udp        | UDP                                                |
        | udp4       | UDP over IPv4                                      |
        | udp6       | UDP over IPv6                                      |
        | unix       | UNIX socket (both UDP and TCP protocols)           |
        | all        | the sum of all the possible families and protocols |
        +------------+----------------------------------------------------+
        """
        return self._proc.net_connections(kind)

    @_common.deprecated_method(replacement="net_connections")
    def connections(self, kind="inet"):
        return self.net_connections(kind=kind)

    # --- signals

    if POSIX:

        def _send_signal(self, sig):
            assert not self.pid < 0, self.pid
            self._raise_if_pid_reused()
            if self.pid == 0:
                # see "man 2 kill"
                msg = (
                    "preventing sending signal to process with PID 0 as it "
                    "would affect every process in the process group of the "
                    "calling process (os.getpid()) instead of PID 0"
                )
                raise ValueError(msg)
            try:
                os.kill(self.pid, sig)
            except ProcessLookupError:
                if OPENBSD and pid_exists(self.pid):
                    # We do this because os.kill() lies in case of
                    # zombie processes.
                    raise ZombieProcess(self.pid, self._name, self._ppid)
                else:
                    self._gone = True
                    raise NoSuchProcess(self.pid, self._name)
            except PermissionError:
                raise AccessDenied(self.pid, self._name)

    def send_signal(self, sig):
        """Send a signal *sig* to process pre-emptively checking
        whether PID has been reused (see signal module constants) .
        On Windows only SIGTERM is valid and is treated as an alias
        for kill().
        """
        if POSIX:
            self._send_signal(sig)
        else:  # pragma: no cover
            self._raise_if_pid_reused()
            if sig != signal.SIGTERM and not self.is_running():
                msg = "process no longer exists"
                raise NoSuchProcess(self.pid, self._name, msg=msg)
            self._proc.send_signal(sig)

    def suspend(self):
        """Suspend process execution with SIGSTOP pre-emptively checking
        whether PID has been reused.
        On Windows this has the effect of suspending all process threads.
        """
        if POSIX:
            self._send_signal(signal.SIGSTOP)
        else:  # pragma: no cover
            self._raise_if_pid_reused()
            self._proc.suspend()

    def resume(self):
        """Resume process execution with SIGCONT pre-emptively checking
        whether PID has been reused.
        On Windows this has the effect of resuming all process threads.
        """
        if POSIX:
            self._send_signal(signal.SIGCONT)
        else:  # pragma: no cover
            self._raise_if_pid_reused()
            self._proc.resume()

    def terminate(self):
        """Terminate the process with SIGTERM pre-emptively checking
        whether PID has been reused.
        On Windows this is an alias for kill().
        """
        if POSIX:
            self._send_signal(signal.SIGTERM)
        else:  # pragma: no cover
            self._raise_if_pid_reused()
            self._proc.kill()

    def kill(self):
        """Kill the current process with SIGKILL pre-emptively checking
        whether PID has been reused.
        """
        if POSIX:
            self._send_signal(signal.SIGKILL)
        else:  # pragma: no cover
            self._raise_if_pid_reused()
            self._proc.kill()

    def wait(self, timeout=None):
        """Wait for process to terminate and, if process is a children
        of os.getpid(), also return its exit code, else None.
        On Windows there's no such limitation (exit code is always
        returned).

        If the process is already terminated immediately return None
        instead of raising NoSuchProcess.

        If *timeout* (in seconds) is specified and process is still
        alive raise TimeoutExpired.

        To wait for multiple Process(es) use psutil.wait_procs().
        """
        if timeout is not None and not timeout >= 0:
            msg = "timeout must be a positive integer"
            raise ValueError(msg)
        if self._exitcode is not _SENTINEL:
            return self._exitcode
        self._exitcode = self._proc.wait(timeout)
        return self._exitcode


# The valid attr names which can be processed by Process.as_dict().
# fmt: off
_as_dict_attrnames = set(
    [x for x in dir(Process) if not x.startswith('_') and x not in
     {'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
      'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit',
      'memory_info_ex', 'connections', 'oneshot'}])
# fmt: on


# =====================================================================
# --- Popen class
# =====================================================================


class Popen(Process):
    """Same as subprocess.Popen, but in addition it provides all
    psutil.Process methods in a single class.
    For the following methods which are common to both classes, psutil
    implementation takes precedence:

    * send_signal()
    * terminate()
    * kill()

    This is done in order to avoid killing another process in case its
    PID has been reused, fixing BPO-6973.

      >>> import psutil
      >>> from subprocess import PIPE
      >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE)
      >>> p.name()
      'python'
      >>> p.uids()
      user(real=1000, effective=1000, saved=1000)
      >>> p.username()
      'giampaolo'
      >>> p.communicate()
      ('hi', None)
      >>> p.terminate()
      >>> p.wait(timeout=2)
      0
      >>>
    """

    def __init__(self, *args, **kwargs):
        # Explicitly avoid to raise NoSuchProcess in case the process
        # spawned by subprocess.Popen terminates too quickly, see:
        # https://github.com/giampaolo/psutil/issues/193
        self.__subproc = subprocess.Popen(*args, **kwargs)
        self._init(self.__subproc.pid, _ignore_nsp=True)

    def __dir__(self):
        return sorted(set(dir(Popen) + dir(subprocess.Popen)))

    def __enter__(self):
        if hasattr(self.__subproc, '__enter__'):
            self.__subproc.__enter__()
        return self

    def __exit__(self, *args, **kwargs):
        if hasattr(self.__subproc, '__exit__'):
            return self.__subproc.__exit__(*args, **kwargs)
        else:
            if self.stdout:
                self.stdout.close()
            if self.stderr:
                self.stderr.close()
            try:
                # Flushing a BufferedWriter may raise an error.
                if self.stdin:
                    self.stdin.close()
            finally:
                # Wait for the process to terminate, to avoid zombies.
                self.wait()

    def __getattribute__(self, name):
        try:
            return object.__getattribute__(self, name)
        except AttributeError:
            try:
                return object.__getattribute__(self.__subproc, name)
            except AttributeError:
                msg = "%s instance has no attribute '%s'" % (
                    self.__class__.__name__,
                    name,
                )
                raise AttributeError(msg)

    def wait(self, timeout=None):
        if self.__subproc.returncode is not None:
            return self.__subproc.returncode
        ret = super(Popen, self).wait(timeout)  # noqa
        self.__subproc.returncode = ret
        return ret


# =====================================================================
# --- system processes related functions
# =====================================================================


def pids():
    """Return a list of current running PIDs."""
    global _LOWEST_PID
    ret = sorted(_psplatform.pids())
    _LOWEST_PID = ret[0]
    return ret


def pid_exists(pid):
    """Return True if given PID exists in the current process list.
    This is faster than doing "pid in psutil.pids()" and
    should be preferred.
    """
    if pid < 0:
        return False
    elif pid == 0 and POSIX:
        # On POSIX we use os.kill() to determine PID existence.
        # According to "man 2 kill" PID 0 has a special meaning
        # though: it refers to <<every process in the process
        # group of the calling process>> and that is not we want
        # to do here.
        return pid in pids()
    else:
        return _psplatform.pid_exists(pid)


_pmap = {}
_pids_reused = set()


def process_iter(attrs=None, ad_value=None):
    """Return a generator yielding a Process instance for all
    running processes.

    Every new Process instance is only created once and then cached
    into an internal table which is updated every time this is used.
    Cache can optionally be cleared via `process_iter.clear_cache()`.

    The sorting order in which processes are yielded is based on
    their PIDs.

    *attrs* and *ad_value* have the same meaning as in
    Process.as_dict(). If *attrs* is specified as_dict() is called
    and the resulting dict is stored as a 'info' attribute attached
    to returned Process instance.
    If *attrs* is an empty list it will retrieve all process info
    (slow).
    """
    global _pmap

    def add(pid):
        proc = Process(pid)
        pmap[proc.pid] = proc
        return proc

    def remove(pid):
        pmap.pop(pid, None)

    pmap = _pmap.copy()
    a = set(pids())
    b = set(pmap.keys())
    new_pids = a - b
    gone_pids = b - a
    for pid in gone_pids:
        remove(pid)
    while _pids_reused:
        pid = _pids_reused.pop()
        debug("refreshing Process instance for reused PID %s" % pid)
        remove(pid)
    try:
        ls = sorted(list(pmap.items()) + list(dict.fromkeys(new_pids).items()))
        for pid, proc in ls:
            try:
                if proc is None:  # new process
                    proc = add(pid)
                if attrs is not None:
                    proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value)
                yield proc
            except NoSuchProcess:
                remove(pid)
    finally:
        _pmap = pmap


process_iter.cache_clear = lambda: _pmap.clear()  # noqa
process_iter.cache_clear.__doc__ = "Clear process_iter() internal cache."


def wait_procs(procs, timeout=None, callback=None):
    """Convenience function which waits for a list of processes to
    terminate.

    Return a (gone, alive) tuple indicating which processes
    are gone and which ones are still alive.

    The gone ones will have a new *returncode* attribute indicating
    process exit status (may be None).

    *callback* is a function which gets called every time a process
    terminates (a Process instance is passed as callback argument).

    Function will return as soon as all processes terminate or when
    *timeout* occurs.
    Differently from Process.wait() it will not raise TimeoutExpired if
    *timeout* occurs.

    Typical use case is:

     - send SIGTERM to a list of processes
     - give them some time to terminate
     - send SIGKILL to those ones which are still alive

    Example:

    >>> def on_terminate(proc):
    ...     print("process {} terminated".format(proc))
    ...
    >>> for p in procs:
    ...    p.terminate()
    ...
    >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate)
    >>> for p in alive:
    ...     p.kill()
    """

    def check_gone(proc, timeout):
        try:
            returncode = proc.wait(timeout=timeout)
        except TimeoutExpired:
            pass
        except _SubprocessTimeoutExpired:
            pass
        else:
            if returncode is not None or not proc.is_running():
                # Set new Process instance attribute.
                proc.returncode = returncode
                gone.add(proc)
                if callback is not None:
                    callback(proc)

    if timeout is not None and not timeout >= 0:
        msg = "timeout must be a positive integer, got %s" % timeout
        raise ValueError(msg)
    gone = set()
    alive = set(procs)
    if callback is not None and not callable(callback):
        msg = "callback %r is not a callable" % callback
        raise TypeError(msg)
    if timeout is not None:
        deadline = _timer() + timeout

    while alive:
        if timeout is not None and timeout <= 0:
            break
        for proc in alive:
            # Make sure that every complete iteration (all processes)
            # will last max 1 sec.
            # We do this because we don't want to wait too long on a
            # single process: in case it terminates too late other
            # processes may disappear in the meantime and their PID
            # reused.
            max_timeout = 1.0 / len(alive)
            if timeout is not None:
                timeout = min((deadline - _timer()), max_timeout)
                if timeout <= 0:
                    break
                check_gone(proc, timeout)
            else:
                check_gone(proc, max_timeout)
        alive = alive - gone  # noqa PLR6104

    if alive:
        # Last attempt over processes survived so far.
        # timeout == 0 won't make this function wait any further.
        for proc in alive:
            check_gone(proc, 0)
        alive = alive - gone  # noqa: PLR6104

    return (list(gone), list(alive))


# =====================================================================
# --- CPU related functions
# =====================================================================


def cpu_count(logical=True):
    """Return the number of logical CPUs in the system (same as
    os.cpu_count() in Python 3.4).

    If *logical* is False return the number of physical cores only
    (e.g. hyper thread CPUs are excluded).

    Return None if undetermined.

    The return value is cached after first call.
    If desired cache can be cleared like this:

    >>> psutil.cpu_count.cache_clear()
    """
    if logical:
        ret = _psplatform.cpu_count_logical()
    else:
        ret = _psplatform.cpu_count_cores()
    if ret is not None and ret < 1:
        ret = None
    return ret


def cpu_times(percpu=False):
    """Return system-wide CPU times as a namedtuple.
    Every CPU time represents the seconds the CPU has spent in the
    given mode. The namedtuple's fields availability varies depending on the
    platform:

     - user
     - system
     - idle
     - nice (UNIX)
     - iowait (Linux)
     - irq (Linux, FreeBSD)
     - softirq (Linux)
     - steal (Linux >= 2.6.11)
     - guest (Linux >= 2.6.24)
     - guest_nice (Linux >= 3.2.0)

    When *percpu* is True return a list of namedtuples for each CPU.
    First element of the list refers to first CPU, second element
    to second CPU and so on.
    The order of the list is consistent across calls.
    """
    if not percpu:
        return _psplatform.cpu_times()
    else:
        return _psplatform.per_cpu_times()


try:
    _last_cpu_times = {threading.current_thread().ident: cpu_times()}
except Exception:  # noqa: BLE001
    # Don't want to crash at import time.
    _last_cpu_times = {}

try:
    _last_per_cpu_times = {
        threading.current_thread().ident: cpu_times(percpu=True)
    }
except Exception:  # noqa: BLE001
    # Don't want to crash at import time.
    _last_per_cpu_times = {}


def _cpu_tot_time(times):
    """Given a cpu_time() ntuple calculates the total CPU time
    (including idle time).
    """
    tot = sum(times)
    if LINUX:
        # On Linux guest times are already accounted in "user" or
        # "nice" times, so we subtract them from total.
        # Htop does the same. References:
        # https://github.com/giampaolo/psutil/pull/940
        # http://unix.stackexchange.com/questions/178045
        # https://github.com/torvalds/linux/blob/
        #     447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/
        #     cputime.c#L158
        tot -= getattr(times, "guest", 0)  # Linux 2.6.24+
        tot -= getattr(times, "guest_nice", 0)  # Linux 3.2.0+
    return tot


def _cpu_busy_time(times):
    """Given a cpu_time() ntuple calculates the busy CPU time.
    We do so by subtracting all idle CPU times.
    """
    busy = _cpu_tot_time(times)
    busy -= times.idle
    # Linux: "iowait" is time during which the CPU does not do anything
    # (waits for IO to complete). On Linux IO wait is *not* accounted
    # in "idle" time so we subtract it. Htop does the same.
    # References:
    # https://github.com/torvalds/linux/blob/
    #     447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244
    busy -= getattr(times, "iowait", 0)
    return busy


def _cpu_times_deltas(t1, t2):
    assert t1._fields == t2._fields, (t1, t2)
    field_deltas = []
    for field in _psplatform.scputimes._fields:
        field_delta = getattr(t2, field) - getattr(t1, field)
        # CPU times are always supposed to increase over time
        # or at least remain the same and that's because time
        # cannot go backwards.
        # Surprisingly sometimes this might not be the case (at
        # least on Windows and Linux), see:
        # https://github.com/giampaolo/psutil/issues/392
        # https://github.com/giampaolo/psutil/issues/645
        # https://github.com/giampaolo/psutil/issues/1210
        # Trim negative deltas to zero to ignore decreasing fields.
        # top does the same. Reference:
        # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063
        field_delta = max(0, field_delta)
        field_deltas.append(field_delta)
    return _psplatform.scputimes(*field_deltas)


def cpu_percent(interval=None, percpu=False):
    """Return a float representing the current system-wide CPU
    utilization as a percentage.

    When *interval* is > 0.0 compares system CPU times elapsed before
    and after the interval (blocking).

    When *interval* is 0.0 or None compares system CPU times elapsed
    since last call or module import, returning immediately (non
    blocking). That means the first time this is called it will
    return a meaningless 0.0 value which you should ignore.
    In this case is recommended for accuracy that this function be
    called with at least 0.1 seconds between calls.

    When *percpu* is True returns a list of floats representing the
    utilization as a percentage for each CPU.
    First element of the list refers to first CPU, second element
    to second CPU and so on.
    The order of the list is consistent across calls.

    Examples:

      >>> # blocking, system-wide
      >>> psutil.cpu_percent(interval=1)
      2.0
      >>>
      >>> # blocking, per-cpu
      >>> psutil.cpu_percent(interval=1, percpu=True)
      [2.0, 1.0]
      >>>
      >>> # non-blocking (percentage since last call)
      >>> psutil.cpu_percent(interval=None)
      2.9
      >>>
    """
    tid = threading.current_thread().ident
    blocking = interval is not None and interval > 0.0
    if interval is not None and interval < 0:
        msg = "interval is not positive (got %r)" % interval
        raise ValueError(msg)

    def calculate(t1, t2):
        times_delta = _cpu_times_deltas(t1, t2)
        all_delta = _cpu_tot_time(times_delta)
        busy_delta = _cpu_busy_time(times_delta)

        try:
            busy_perc = (busy_delta / all_delta) * 100
        except ZeroDivisionError:
            return 0.0
        else:
            return round(busy_perc, 1)

    # system-wide usage
    if not percpu:
        if blocking:
            t1 = cpu_times()
            time.sleep(interval)
        else:
            t1 = _last_cpu_times.get(tid) or cpu_times()
        _last_cpu_times[tid] = cpu_times()
        return calculate(t1, _last_cpu_times[tid])
    # per-cpu usage
    else:
        ret = []
        if blocking:
            tot1 = cpu_times(percpu=True)
            time.sleep(interval)
        else:
            tot1 = _last_per_cpu_times.get(tid) or cpu_times(percpu=True)
        _last_per_cpu_times[tid] = cpu_times(percpu=True)
        for t1, t2 in zip(tot1, _last_per_cpu_times[tid]):
            ret.append(calculate(t1, t2))
        return ret


# Use a separate dict for cpu_times_percent(), so it's independent from
# cpu_percent() and they can both be used within the same program.
_last_cpu_times_2 = _last_cpu_times.copy()
_last_per_cpu_times_2 = _last_per_cpu_times.copy()


def cpu_times_percent(interval=None, percpu=False):
    """Same as cpu_percent() but provides utilization percentages
    for each specific CPU time as is returned by cpu_times().
    For instance, on Linux we'll get:

      >>> cpu_times_percent()
      cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0,
                 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
      >>>

    *interval* and *percpu* arguments have the same meaning as in
    cpu_percent().
    """
    tid = threading.current_thread().ident
    blocking = interval is not None and interval > 0.0
    if interval is not None and interval < 0:
        msg = "interval is not positive (got %r)" % interval
        raise ValueError(msg)

    def calculate(t1, t2):
        nums = []
        times_delta = _cpu_times_deltas(t1, t2)
        all_delta = _cpu_tot_time(times_delta)
        # "scale" is the value to multiply each delta with to get percentages.
        # We use "max" to avoid division by zero (if all_delta is 0, then all
        # fields are 0 so percentages will be 0 too. all_delta cannot be a
        # fraction because cpu times are integers)
        scale = 100.0 / max(1, all_delta)
        for field_delta in times_delta:
            field_perc = field_delta * scale
            field_perc = round(field_perc, 1)
            # make sure we don't return negative values or values over 100%
            field_perc = min(max(0.0, field_perc), 100.0)
            nums.append(field_perc)
        return _psplatform.scputimes(*nums)

    # system-wide usage
    if not percpu:
        if blocking:
            t1 = cpu_times()
            time.sleep(interval)
        else:
            t1 = _last_cpu_times_2.get(tid) or cpu_times()
        _last_cpu_times_2[tid] = cpu_times()
        return calculate(t1, _last_cpu_times_2[tid])
    # per-cpu usage
    else:
        ret = []
        if blocking:
            tot1 = cpu_times(percpu=True)
            time.sleep(interval)
        else:
            tot1 = _last_per_cpu_times_2.get(tid) or cpu_times(percpu=True)
        _last_per_cpu_times_2[tid] = cpu_times(percpu=True)
        for t1, t2 in zip(tot1, _last_per_cpu_times_2[tid]):
            ret.append(calculate(t1, t2))
        return ret


def cpu_stats():
    """Return CPU statistics."""
    return _psplatform.cpu_stats()


if hasattr(_psplatform, "cpu_freq"):

    def cpu_freq(percpu=False):
        """Return CPU frequency as a namedtuple including current,
        min and max frequency expressed in Mhz.

        If *percpu* is True and the system supports per-cpu frequency
        retrieval (Linux only) a list of frequencies is returned for
        each CPU. If not a list with one element is returned.
        """
        ret = _psplatform.cpu_freq()
        if percpu:
            return ret
        else:
            num_cpus = float(len(ret))
            if num_cpus == 0:
                return None
            elif num_cpus == 1:
                return ret[0]
            else:
                currs, mins, maxs = 0.0, 0.0, 0.0
                set_none = False
                for cpu in ret:
                    currs += cpu.current
                    # On Linux if /proc/cpuinfo is used min/max are set
                    # to None.
                    if LINUX and cpu.min is None:
                        set_none = True
                        continue
                    mins += cpu.min
                    maxs += cpu.max

                current = currs / num_cpus

                if set_none:
                    min_ = max_ = None
                else:
                    min_ = mins / num_cpus
                    max_ = maxs / num_cpus

                return _common.scpufreq(current, min_, max_)

    __all__.append("cpu_freq")


if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"):
    # Perform this hasattr check once on import time to either use the
    # platform based code or proxy straight from the os module.
    if hasattr(os, "getloadavg"):
        getloadavg = os.getloadavg
    else:
        getloadavg = _psplatform.getloadavg

    __all__.append("getloadavg")


# =====================================================================
# --- system memory related functions
# =====================================================================


def virtual_memory():
    """Return statistics about system memory usage as a namedtuple
    including the following fields, expressed in bytes:

     - total:
       total physical memory available.

     - available:
       the memory that can be given instantly to processes without the
       system going into swap.
       This is calculated by summing different memory values depending
       on the platform and it is supposed to be used to monitor actual
       memory usage in a cross platform fashion.

     - percent:
       the percentage usage calculated as (total - available) / total * 100

     - used:
        memory used, calculated differently depending on the platform and
        designed for informational purposes only:
        macOS: active + wired
        BSD: active + wired + cached
        Linux: total - free

     - free:
       memory not being used at all (zeroed) that is readily available;
       note that this doesn't reflect the actual memory available
       (use 'available' instead)

    Platform-specific fields:

     - active (UNIX):
       memory currently in use or very recently used, and so it is in RAM.

     - inactive (UNIX):
       memory that is marked as not used.

     - buffers (BSD, Linux):
       cache for things like file system metadata.

     - cached (BSD, macOS):
       cache for various things.

     - wired (macOS, BSD):
       memory that is marked to always stay in RAM. It is never moved to disk.

     - shared (BSD):
       memory that may be simultaneously accessed by multiple processes.

    The sum of 'used' and 'available' does not necessarily equal total.
    On Windows 'available' and 'free' are the same.
    """
    global _TOTAL_PHYMEM
    ret = _psplatform.virtual_memory()
    # cached for later use in Process.memory_percent()
    _TOTAL_PHYMEM = ret.total
    return ret


def swap_memory():
    """Return system swap memory statistics as a namedtuple including
    the following fields:

     - total:   total swap memory in bytes
     - used:    used swap memory in bytes
     - free:    free swap memory in bytes
     - percent: the percentage usage
     - sin:     no. of bytes the system has swapped in from disk (cumulative)
     - sout:    no. of bytes the system has swapped out from disk (cumulative)

    'sin' and 'sout' on Windows are meaningless and always set to 0.
    """
    return _psplatform.swap_memory()


# =====================================================================
# --- disks/partitions related functions
# =====================================================================


def disk_usage(path):
    """Return disk usage statistics about the given *path* as a
    namedtuple including total, used and free space expressed in bytes
    plus the percentage usage.
    """
    return _psplatform.disk_usage(path)


def disk_partitions(all=False):
    """Return mounted partitions as a list of
    (device, mountpoint, fstype, opts) namedtuple.
    'opts' field is a raw string separated by commas indicating mount
    options which may vary depending on the platform.

    If *all* parameter is False return physical devices only and ignore
    all others.
    """
    return _psplatform.disk_partitions(all)


def disk_io_counters(perdisk=False, nowrap=True):
    """Return system disk I/O statistics as a namedtuple including
    the following fields:

     - read_count:  number of reads
     - write_count: number of writes
     - read_bytes:  number of bytes read
     - write_bytes: number of bytes written
     - read_time:   time spent reading from disk (in ms)
     - write_time:  time spent writing to disk (in ms)

    Platform specific:

     - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms)
     - read_merged_count (Linux): number of merged reads
     - write_merged_count (Linux): number of merged writes

    If *perdisk* is True return the same information for every
    physical disk installed on the system as a dictionary
    with partition names as the keys and the namedtuple
    described above as the values.

    If *nowrap* is True it detects and adjust the numbers which overflow
    and wrap (restart from 0) and add "old value" to "new value" so that
    the returned numbers will always be increasing or remain the same,
    but never decrease.
    "disk_io_counters.cache_clear()" can be used to invalidate the
    cache.

    On recent Windows versions 'diskperf -y' command may need to be
    executed first otherwise this function won't find any disk.
    """
    kwargs = dict(perdisk=perdisk) if LINUX else {}
    rawdict = _psplatform.disk_io_counters(**kwargs)
    if not rawdict:
        return {} if perdisk else None
    if nowrap:
        rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters')
    nt = getattr(_psplatform, "sdiskio", _common.sdiskio)
    if perdisk:
        for disk, fields in rawdict.items():
            rawdict[disk] = nt(*fields)
        return rawdict
    else:
        return nt(*(sum(x) for x in zip(*rawdict.values())))


disk_io_counters.cache_clear = functools.partial(
    _wrap_numbers.cache_clear, 'psutil.disk_io_counters'
)
disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache"


# =====================================================================
# --- network related functions
# =====================================================================


def net_io_counters(pernic=False, nowrap=True):
    """Return network I/O statistics as a namedtuple including
    the following fields:

     - bytes_sent:   number of bytes sent
     - bytes_recv:   number of bytes received
     - packets_sent: number of packets sent
     - packets_recv: number of packets received
     - errin:        total number of errors while receiving
     - errout:       total number of errors while sending
     - dropin:       total number of incoming packets which were dropped
     - dropout:      total number of outgoing packets which were dropped
                     (always 0 on macOS and BSD)

    If *pernic* is True return the same information for every
    network interface installed on the system as a dictionary
    with network interface names as the keys and the namedtuple
    described above as the values.

    If *nowrap* is True it detects and adjust the numbers which overflow
    and wrap (restart from 0) and add "old value" to "new value" so that
    the returned numbers will always be increasing or remain the same,
    but never decrease.
    "net_io_counters.cache_clear()" can be used to invalidate the
    cache.
    """
    rawdict = _psplatform.net_io_counters()
    if not rawdict:
        return {} if pernic else None
    if nowrap:
        rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters')
    if pernic:
        for nic, fields in rawdict.items():
            rawdict[nic] = _common.snetio(*fields)
        return rawdict
    else:
        return _common.snetio(*[sum(x) for x in zip(*rawdict.values())])


net_io_counters.cache_clear = functools.partial(
    _wrap_numbers.cache_clear, 'psutil.net_io_counters'
)
net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache"


def net_connections(kind='inet'):
    """Return system-wide socket connections as a list of
    (fd, family, type, laddr, raddr, status, pid) namedtuples.
    In case of limited privileges 'fd' and 'pid' may be set to -1
    and None respectively.
    The *kind* parameter filters for connections that fit the
    following criteria:

    +------------+----------------------------------------------------+
    | Kind Value | Connections using                                  |
    +------------+----------------------------------------------------+
    | inet       | IPv4 and IPv6                                      |
    | inet4      | IPv4                                               |
    | inet6      | IPv6                                               |
    | tcp        | TCP                                                |
    | tcp4       | TCP over IPv4                                      |
    | tcp6       | TCP over IPv6                                      |
    | udp        | UDP                                                |
    | udp4       | UDP over IPv4                                      |
    | udp6       | UDP over IPv6                                      |
    | unix       | UNIX socket (both UDP and TCP protocols)           |
    | all        | the sum of all the possible families and protocols |
    +------------+----------------------------------------------------+

    On macOS this function requires root privileges.
    """
    return _psplatform.net_connections(kind)


def net_if_addrs():
    """Return the addresses associated to each NIC (network interface
    card) installed on the system as a dictionary whose keys are the
    NIC names and value is a list of namedtuples for each address
    assigned to the NIC. Each namedtuple includes 5 fields:

     - family: can be either socket.AF_INET, socket.AF_INET6 or
               psutil.AF_LINK, which refers to a MAC address.
     - address: is the primary address and it is always set.
     - netmask: and 'broadcast' and 'ptp' may be None.
     - ptp: stands for "point to point" and references the
            destination address on a point to point interface
            (typically a VPN).
     - broadcast: and *ptp* are mutually exclusive.

    Note: you can have more than one address of the same family
    associated with each interface.
    """
    has_enums = _PY3
    if has_enums:
        import socket
    rawlist = _psplatform.net_if_addrs()
    rawlist.sort(key=lambda x: x[1])  # sort by family
    ret = collections.defaultdict(list)
    for name, fam, addr, mask, broadcast, ptp in rawlist:
        if has_enums:
            try:
                fam = socket.AddressFamily(fam)
            except ValueError:
                if WINDOWS and fam == -1:
                    fam = _psplatform.AF_LINK
                elif (
                    hasattr(_psplatform, "AF_LINK")
                    and fam == _psplatform.AF_LINK
                ):
                    # Linux defines AF_LINK as an alias for AF_PACKET.
                    # We re-set the family here so that repr(family)
                    # will show AF_LINK rather than AF_PACKET
                    fam = _psplatform.AF_LINK
        if fam == _psplatform.AF_LINK:
            # The underlying C function may return an incomplete MAC
            # address in which case we fill it with null bytes, see:
            # https://github.com/giampaolo/psutil/issues/786
            separator = ":" if POSIX else "-"
            while addr.count(separator) < 5:
                addr += "%s00" % separator
        ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp))
    return dict(ret)


def net_if_stats():
    """Return information about each NIC (network interface card)
    installed on the system as a dictionary whose keys are the
    NIC names and value is a namedtuple with the following fields:

     - isup: whether the interface is up (bool)
     - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or
               NIC_DUPLEX_UNKNOWN
     - speed: the NIC speed expressed in mega bits (MB); if it can't
              be determined (e.g. 'localhost') it will be set to 0.
     - mtu: the maximum transmission unit expressed in bytes.
    """
    return _psplatform.net_if_stats()


# =====================================================================
# --- sensors
# =====================================================================


# Linux, macOS
if hasattr(_psplatform, "sensors_temperatures"):

    def sensors_temperatures(fahrenheit=False):
        """Return hardware temperatures. Each entry is a namedtuple
        representing a certain hardware sensor (it may be a CPU, an
        hard disk or something else, depending on the OS and its
        configuration).
        All temperatures are expressed in celsius unless *fahrenheit*
        is set to True.
        """

        def convert(n):
            if n is not None:
                return (float(n) * 9 / 5) + 32 if fahrenheit else n

        ret = collections.defaultdict(list)
        rawdict = _psplatform.sensors_temperatures()

        for name, values in rawdict.items():
            while values:
                label, current, high, critical = values.pop(0)
                current = convert(current)
                high = convert(high)
                critical = convert(critical)

                if high and not critical:
                    critical = high
                elif critical and not high:
                    high = critical

                ret[name].append(
                    _common.shwtemp(label, current, high, critical)
                )

        return dict(ret)

    __all__.append("sensors_temperatures")


# Linux
if hasattr(_psplatform, "sensors_fans"):

    def sensors_fans():
        """Return fans speed. Each entry is a namedtuple
        representing a certain hardware sensor.
        All speed are expressed in RPM (rounds per minute).
        """
        return _psplatform.sensors_fans()

    __all__.append("sensors_fans")


# Linux, Windows, FreeBSD, macOS
if hasattr(_psplatform, "sensors_battery"):

    def sensors_battery():
        """Return battery information. If no battery is installed
        returns None.

         - percent: battery power left as a percentage.
         - secsleft: a rough approximation of how many seconds are left
                     before the battery runs out of power. May be
                     POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED.
         - power_plugged: True if the AC power cable is connected.
        """
        return _psplatform.sensors_battery()

    __all__.append("sensors_battery")


# =====================================================================
# --- other system related functions
# =====================================================================


def boot_time():
    """Return the system boot time expressed in seconds since the epoch."""
    # Note: we are not caching this because it is subject to
    # system clock updates.
    return _psplatform.boot_time()


def users():
    """Return users currently connected on the system as a list of
    namedtuples including the following fields.

     - user: the name of the user
     - terminal: the tty or pseudo-tty associated with the user, if any.
     - host: the host name associated with the entry, if any.
     - started: the creation time as a floating point number expressed in
       seconds since the epoch.
    """
    return _psplatform.users()


# =====================================================================
# --- Windows services
# =====================================================================


if WINDOWS:

    def win_service_iter():
        """Return a generator yielding a WindowsService instance for all
        Windows services installed.
        """
        return _psplatform.win_service_iter()

    def win_service_get(name):
        """Get a Windows service by *name*.
        Raise NoSuchProcess if no service with such name exists.
        """
        return _psplatform.win_service_get(name)


# =====================================================================


def _set_debug(value):
    """Enable or disable PSUTIL_DEBUG option, which prints debugging
    messages to stderr.
    """
    import psutil._common

    psutil._common.PSUTIL_DEBUG = bool(value)
    _psplatform.cext.set_debug(bool(value))


def test():  # pragma: no cover
    from ._common import bytes2human
    from ._compat import get_terminal_size

    today_day = datetime.date.today()
    # fmt: off
    templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s  %s"
    attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times',
             'create_time', 'memory_info', 'status', 'nice', 'username']
    print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE",  # NOQA
                   "STATUS", "START", "TIME", "CMDLINE"))
    # fmt: on
    for p in process_iter(attrs, ad_value=None):
        if p.info['create_time']:
            ctime = datetime.datetime.fromtimestamp(p.info['create_time'])
            if ctime.date() == today_day:
                ctime = ctime.strftime("%H:%M")
            else:
                ctime = ctime.strftime("%b%d")
        else:
            ctime = ''
        if p.info['cpu_times']:
            cputime = time.strftime(
                "%M:%S", time.localtime(sum(p.info['cpu_times']))
            )
        else:
            cputime = ''

        user = p.info['username'] or ''
        if not user and POSIX:
            try:
                user = p.uids()[0]
            except Error:
                pass
        if user and WINDOWS and '\\' in user:
            user = user.split('\\')[1]
        user = user[:9]
        vms = (
            bytes2human(p.info['memory_info'].vms)
            if p.info['memory_info'] is not None
            else ''
        )
        rss = (
            bytes2human(p.info['memory_info'].rss)
            if p.info['memory_info'] is not None
            else ''
        )
        memp = (
            round(p.info['memory_percent'], 1)
            if p.info['memory_percent'] is not None
            else ''
        )
        nice = int(p.info['nice']) if p.info['nice'] else ''
        if p.info['cmdline']:
            cmdline = ' '.join(p.info['cmdline'])
        else:
            cmdline = p.info['name']
        status = p.info['status'][:5] if p.info['status'] else ''

        line = templ % (
            user[:10],
            p.info['pid'],
            memp,
            vms,
            rss,
            nice,
            status,
            ctime,
            cputime,
            cmdline,
        )
        print(line[: get_terminal_size()[0]])  # NOQA


del memoize_when_activated, division
if sys.version_info[0] < 3:
    del num, x  # noqa

if __name__ == "__main__":
    test()
PKok\0T;+ + psutil/_psposix.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Routines common to all posix systems."""

import glob
import os
import signal
import sys
import time

from ._common import MACOS
from ._common import TimeoutExpired
from ._common import memoize
from ._common import sdiskusage
from ._common import usage_percent
from ._compat import PY3
from ._compat import ChildProcessError
from ._compat import FileNotFoundError
from ._compat import InterruptedError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import unicode


if MACOS:
    from . import _psutil_osx


if PY3:
    import enum
else:
    enum = None


__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']


def pid_exists(pid):
    """Check whether pid exists in the current process table."""
    if pid == 0:
        # According to "man 2 kill" PID 0 has a special meaning:
        # it refers to <<every process in the process group of the
        # calling process>> so we don't want to go any further.
        # If we get here it means this UNIX platform *does* have
        # a process with id 0.
        return True
    try:
        os.kill(pid, 0)
    except ProcessLookupError:
        return False
    except PermissionError:
        # EPERM clearly means there's a process to deny access to
        return True
    # According to "man 2 kill" possible error values are
    # (EINVAL, EPERM, ESRCH)
    else:
        return True


# Python 3.5 signals enum (contributed by me ^^):
# https://bugs.python.org/issue21076
if enum is not None and hasattr(signal, "Signals"):
    Negsignal = enum.IntEnum(
        'Negsignal', dict([(x.name, -x.value) for x in signal.Signals])
    )

    def negsig_to_enum(num):
        """Convert a negative signal value to an enum."""
        try:
            return Negsignal(num)
        except ValueError:
            return num

else:  # pragma: no cover

    def negsig_to_enum(num):
        return num


def wait_pid(
    pid,
    timeout=None,
    proc_name=None,
    _waitpid=os.waitpid,
    _timer=getattr(time, 'monotonic', time.time),  # noqa: B008
    _min=min,
    _sleep=time.sleep,
    _pid_exists=pid_exists,
):
    """Wait for a process PID to terminate.

    If the process terminated normally by calling exit(3) or _exit(2),
    or by returning from main(), the return value is the positive integer
    passed to *exit().

    If it was terminated by a signal it returns the negated value of the
    signal which caused the termination (e.g. -SIGTERM).

    If PID is not a children of os.getpid() (current process) just
    wait until the process disappears and return None.

    If PID does not exist at all return None immediately.

    If *timeout* != None and process is still alive raise TimeoutExpired.
    timeout=0 is also possible (either return immediately or raise).
    """
    if pid <= 0:
        # see "man waitpid"
        msg = "can't wait for PID 0"
        raise ValueError(msg)
    interval = 0.0001
    flags = 0
    if timeout is not None:
        flags |= os.WNOHANG
        stop_at = _timer() + timeout

    def sleep(interval):
        # Sleep for some time and return a new increased interval.
        if timeout is not None:
            if _timer() >= stop_at:
                raise TimeoutExpired(timeout, pid=pid, name=proc_name)
        _sleep(interval)
        return _min(interval * 2, 0.04)

    # See: https://linux.die.net/man/2/waitpid
    while True:
        try:
            retpid, status = os.waitpid(pid, flags)
        except InterruptedError:
            interval = sleep(interval)
        except ChildProcessError:
            # This has two meanings:
            # - PID is not a child of os.getpid() in which case
            #   we keep polling until it's gone
            # - PID never existed in the first place
            # In both cases we'll eventually return None as we
            # can't determine its exit status code.
            while _pid_exists(pid):
                interval = sleep(interval)
            return
        else:
            if retpid == 0:
                # WNOHANG flag was used and PID is still running.
                interval = sleep(interval)
                continue

            if os.WIFEXITED(status):
                # Process terminated normally by calling exit(3) or _exit(2),
                # or by returning from main(). The return value is the
                # positive integer passed to *exit().
                return os.WEXITSTATUS(status)
            elif os.WIFSIGNALED(status):
                # Process exited due to a signal. Return the negative value
                # of that signal.
                return negsig_to_enum(-os.WTERMSIG(status))
            # elif os.WIFSTOPPED(status):
            #     # Process was stopped via SIGSTOP or is being traced, and
            #     # waitpid() was called with WUNTRACED flag. PID is still
            #     # alive. From now on waitpid() will keep returning (0, 0)
            #     # until the process state doesn't change.
            #     # It may make sense to catch/enable this since stopped PIDs
            #     # ignore SIGTERM.
            #     interval = sleep(interval)
            #     continue
            # elif os.WIFCONTINUED(status):
            #     # Process was resumed via SIGCONT and waitpid() was called
            #     # with WCONTINUED flag.
            #     interval = sleep(interval)
            #     continue
            else:
                # Should never happen.
                raise ValueError("unknown process exit status %r" % status)


def disk_usage(path):
    """Return disk usage associated with path.
    Note: UNIX usually reserves 5% disk space which is not accessible
    by user. In this function "total" and "used" values reflect the
    total and used disk space whereas "free" and "percent" represent
    the "free" and "used percent" user disk space.
    """
    if PY3:
        st = os.statvfs(path)
    else:  # pragma: no cover
        # os.statvfs() does not support unicode on Python 2:
        # - https://github.com/giampaolo/psutil/issues/416
        # - http://bugs.python.org/issue18695
        try:
            st = os.statvfs(path)
        except UnicodeEncodeError:
            if isinstance(path, unicode):
                try:
                    path = path.encode(sys.getfilesystemencoding())
                except UnicodeEncodeError:
                    pass
                st = os.statvfs(path)
            else:
                raise

    # Total space which is only available to root (unless changed
    # at system level).
    total = st.f_blocks * st.f_frsize
    # Remaining free space usable by root.
    avail_to_root = st.f_bfree * st.f_frsize
    # Remaining free space usable by user.
    avail_to_user = st.f_bavail * st.f_frsize
    # Total space being used in general.
    used = total - avail_to_root
    if MACOS:
        # see: https://github.com/giampaolo/psutil/pull/2152
        used = _psutil_osx.disk_usage_used(path, used)
    # Total space which is available to user (same as 'total' but
    # for the user).
    total_user = used + avail_to_user
    # User usage percent compared to the total amount of space
    # the user can use. This number would be higher if compared
    # to root's because the user has less space (usually -5%).
    usage_percent_user = usage_percent(used, total_user, round_=1)

    # NB: the percentage is -5% than what shown by df due to
    # reserved blocks that we are currently not considering:
    # https://github.com/giampaolo/psutil/issues/829#issuecomment-223750462
    return sdiskusage(
        total=total, used=used, free=avail_to_user, percent=usage_percent_user
    )


@memoize
def get_terminal_map():
    """Get a map of device-id -> path as a dict.
    Used by Process.terminal().
    """
    ret = {}
    ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*')
    for name in ls:
        assert name not in ret, name
        try:
            ret[os.stat(name).st_rdev] = name
        except FileNotFoundError:
            pass
    return ret
PKok\t�|�ZZpsutil/_pslinux.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Linux platform implementation."""

from __future__ import division

import base64
import collections
import errno
import functools
import glob
import os
import re
import socket
import struct
import sys
import warnings
from collections import defaultdict
from collections import namedtuple

from . import _common
from . import _psposix
from . import _psutil_linux as cext
from . import _psutil_posix as cext_posix
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import ZombieProcess
from ._common import bcat
from ._common import cat
from ._common import debug
from ._common import decode
from ._common import get_procfs_path
from ._common import isfile_strict
from ._common import memoize
from ._common import memoize_when_activated
from ._common import open_binary
from ._common import open_text
from ._common import parse_environ_block
from ._common import path_exists_strict
from ._common import supports_ipv6
from ._common import usage_percent
from ._compat import PY3
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import b
from ._compat import basestring


if PY3:
    import enum
else:
    enum = None


# fmt: off
__extra__all__ = [
    'PROCFS_PATH',
    # io prio constants
    "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE",
    "IOPRIO_CLASS_IDLE",
    # connection status constants
    "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1",
    "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
    "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING",
]
# fmt: on


# =====================================================================
# --- globals
# =====================================================================


POWER_SUPPLY_PATH = "/sys/class/power_supply"
HAS_PROC_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid())
HAS_PROC_SMAPS_ROLLUP = os.path.exists('/proc/%s/smaps_rollup' % os.getpid())
HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get")
HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get")

# Number of clock ticks per second
CLOCK_TICKS = os.sysconf("SC_CLK_TCK")
PAGESIZE = cext_posix.getpagesize()
BOOT_TIME = None  # set later
LITTLE_ENDIAN = sys.byteorder == 'little'

# "man iostat" states that sectors are equivalent with blocks and have
# a size of 512 bytes. Despite this value can be queried at runtime
# via /sys/block/{DISK}/queue/hw_sector_size and results may vary
# between 1k, 2k, or 4k... 512 appears to be a magic constant used
# throughout Linux source code:
# * https://stackoverflow.com/a/38136179/376587
# * https://lists.gt.net/linux/kernel/2241060
# * https://github.com/giampaolo/psutil/issues/1305
# * https://github.com/torvalds/linux/blob/
#     4f671fe2f9523a1ea206f63fe60a7c7b3a56d5c7/include/linux/bio.h#L99
# * https://lkml.org/lkml/2015/8/17/234
DISK_SECTOR_SIZE = 512

if enum is None:
    AF_LINK = socket.AF_PACKET
else:
    AddressFamily = enum.IntEnum(
        'AddressFamily', {'AF_LINK': int(socket.AF_PACKET)}
    )
    AF_LINK = AddressFamily.AF_LINK

# ioprio_* constants http://linux.die.net/man/2/ioprio_get
if enum is None:
    IOPRIO_CLASS_NONE = 0
    IOPRIO_CLASS_RT = 1
    IOPRIO_CLASS_BE = 2
    IOPRIO_CLASS_IDLE = 3
else:

    class IOPriority(enum.IntEnum):
        IOPRIO_CLASS_NONE = 0
        IOPRIO_CLASS_RT = 1
        IOPRIO_CLASS_BE = 2
        IOPRIO_CLASS_IDLE = 3

    globals().update(IOPriority.__members__)

# See:
# https://github.com/torvalds/linux/blame/master/fs/proc/array.c
# ...and (TASK_* constants):
# https://github.com/torvalds/linux/blob/master/include/linux/sched.h
PROC_STATUSES = {
    "R": _common.STATUS_RUNNING,
    "S": _common.STATUS_SLEEPING,
    "D": _common.STATUS_DISK_SLEEP,
    "T": _common.STATUS_STOPPED,
    "t": _common.STATUS_TRACING_STOP,
    "Z": _common.STATUS_ZOMBIE,
    "X": _common.STATUS_DEAD,
    "x": _common.STATUS_DEAD,
    "K": _common.STATUS_WAKE_KILL,
    "W": _common.STATUS_WAKING,
    "I": _common.STATUS_IDLE,
    "P": _common.STATUS_PARKED,
}

# https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h
TCP_STATUSES = {
    "01": _common.CONN_ESTABLISHED,
    "02": _common.CONN_SYN_SENT,
    "03": _common.CONN_SYN_RECV,
    "04": _common.CONN_FIN_WAIT1,
    "05": _common.CONN_FIN_WAIT2,
    "06": _common.CONN_TIME_WAIT,
    "07": _common.CONN_CLOSE,
    "08": _common.CONN_CLOSE_WAIT,
    "09": _common.CONN_LAST_ACK,
    "0A": _common.CONN_LISTEN,
    "0B": _common.CONN_CLOSING,
}


# =====================================================================
# --- named tuples
# =====================================================================


# fmt: off
# psutil.virtual_memory()
svmem = namedtuple(
    'svmem', ['total', 'available', 'percent', 'used', 'free',
              'active', 'inactive', 'buffers', 'cached', 'shared', 'slab'])
# psutil.disk_io_counters()
sdiskio = namedtuple(
    'sdiskio', ['read_count', 'write_count',
                'read_bytes', 'write_bytes',
                'read_time', 'write_time',
                'read_merged_count', 'write_merged_count',
                'busy_time'])
# psutil.Process().open_files()
popenfile = namedtuple(
    'popenfile', ['path', 'fd', 'position', 'mode', 'flags'])
# psutil.Process().memory_info()
pmem = namedtuple('pmem', 'rss vms shared text lib data dirty')
# psutil.Process().memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap'))
# psutil.Process().memory_maps(grouped=True)
pmmap_grouped = namedtuple(
    'pmmap_grouped',
    ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty',
     'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap'])
# psutil.Process().memory_maps(grouped=False)
pmmap_ext = namedtuple(
    'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
                         'read_bytes', 'write_bytes',
                         'read_chars', 'write_chars'])
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes',
                       ['user', 'system', 'children_user', 'children_system',
                        'iowait'])
# fmt: on


# =====================================================================
# --- utils
# =====================================================================


def readlink(path):
    """Wrapper around os.readlink()."""
    assert isinstance(path, basestring), path
    path = os.readlink(path)
    # readlink() might return paths containing null bytes ('\x00')
    # resulting in "TypeError: must be encoded string without NULL
    # bytes, not str" errors when the string is passed to other
    # fs-related functions (os.*, open(), ...).
    # Apparently everything after '\x00' is garbage (we can have
    # ' (deleted)', 'new' and possibly others), see:
    # https://github.com/giampaolo/psutil/issues/717
    path = path.split('\x00')[0]
    # Certain paths have ' (deleted)' appended. Usually this is
    # bogus as the file actually exists. Even if it doesn't we
    # don't care.
    if path.endswith(' (deleted)') and not path_exists_strict(path):
        path = path[:-10]
    return path


def file_flags_to_mode(flags):
    """Convert file's open() flags into a readable string.
    Used by Process.open_files().
    """
    modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
    mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
    if flags & os.O_APPEND:
        mode = mode.replace('w', 'a', 1)
    mode = mode.replace('w+', 'r+')
    # possible values: r, w, a, r+, a+
    return mode


def is_storage_device(name):
    """Return True if the given name refers to a root device (e.g.
    "sda", "nvme0n1") as opposed to a logical partition (e.g.  "sda1",
    "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram")
    return True.
    """
    # Re-adapted from iostat source code, see:
    # https://github.com/sysstat/sysstat/blob/
    #     97912938cd476645b267280069e83b1c8dc0e1c7/common.c#L208
    # Some devices may have a slash in their name (e.g. cciss/c0d0...).
    name = name.replace('/', '!')
    including_virtual = True
    if including_virtual:
        path = "/sys/block/%s" % name
    else:
        path = "/sys/block/%s/device" % name
    return os.access(path, os.F_OK)


@memoize
def set_scputimes_ntuple(procfs_path):
    """Set a namedtuple of variable fields depending on the CPU times
    available on this Linux kernel version which may be:
    (user, nice, system, idle, iowait, irq, softirq, [steal, [guest,
     [guest_nice]]])
    Used by cpu_times() function.
    """
    global scputimes
    with open_binary('%s/stat' % procfs_path) as f:
        values = f.readline().split()[1:]
    fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq']
    vlen = len(values)
    if vlen >= 8:
        # Linux >= 2.6.11
        fields.append('steal')
    if vlen >= 9:
        # Linux >= 2.6.24
        fields.append('guest')
    if vlen >= 10:
        # Linux >= 3.2.0
        fields.append('guest_nice')
    scputimes = namedtuple('scputimes', fields)


try:
    set_scputimes_ntuple("/proc")
except Exception as err:  # noqa: BLE001
    # Don't want to crash at import time.
    debug("ignoring exception on import: %r" % err)
    scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0)


# =====================================================================
# --- prlimit
# =====================================================================

# Backport of resource.prlimit() for Python 2. Originally this was done
# in C, but CentOS-6 which we use to create manylinux wheels is too old
# and does not support prlimit() syscall. As such the resulting wheel
# would not include prlimit(), even when installed on newer systems.
# This is the only part of psutil using ctypes.

prlimit = None
try:
    from resource import prlimit  # python >= 3.4
except ImportError:
    import ctypes

    libc = ctypes.CDLL(None, use_errno=True)

    if hasattr(libc, "prlimit"):

        def prlimit(pid, resource_, limits=None):
            class StructRlimit(ctypes.Structure):
                _fields_ = [
                    ('rlim_cur', ctypes.c_longlong),
                    ('rlim_max', ctypes.c_longlong),
                ]

            current = StructRlimit()
            if limits is None:
                # get
                ret = libc.prlimit(pid, resource_, None, ctypes.byref(current))
            else:
                # set
                new = StructRlimit()
                new.rlim_cur = limits[0]
                new.rlim_max = limits[1]
                ret = libc.prlimit(
                    pid, resource_, ctypes.byref(new), ctypes.byref(current)
                )

            if ret != 0:
                errno_ = ctypes.get_errno()
                raise OSError(errno_, os.strerror(errno_))
            return (current.rlim_cur, current.rlim_max)


if prlimit is not None:
    __extra__all__.extend(
        [x for x in dir(cext) if x.startswith('RLIM') and x.isupper()]
    )


# =====================================================================
# --- system memory
# =====================================================================


def calculate_avail_vmem(mems):
    """Fallback for kernels < 3.14 where /proc/meminfo does not provide
    "MemAvailable", see:
    https://blog.famzah.net/2014/09/24/.

    This code reimplements the algorithm outlined here:
    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
        commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773

    We use this function also when "MemAvailable" returns 0 (possibly a
    kernel bug, see: https://github.com/giampaolo/psutil/issues/1915).
    In that case this routine matches "free" CLI tool result ("available"
    column).

    XXX: on recent kernels this calculation may differ by ~1.5% compared
    to "MemAvailable:", as it's calculated slightly differently.
    It is still way more realistic than doing (free + cached) though.
    See:
    * https://gitlab.com/procps-ng/procps/issues/42
    * https://github.com/famzah/linux-memavailable-procfs/issues/2
    """
    # Note about "fallback" value. According to:
    # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
    #     commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
    # ...long ago "available" memory was calculated as (free + cached),
    # We use fallback when one of these is missing from /proc/meminfo:
    # "Active(file)": introduced in 2.6.28 / Dec 2008
    # "Inactive(file)": introduced in 2.6.28 / Dec 2008
    # "SReclaimable": introduced in 2.6.19 / Nov 2006
    # /proc/zoneinfo: introduced in 2.6.13 / Aug 2005
    free = mems[b'MemFree:']
    fallback = free + mems.get(b"Cached:", 0)
    try:
        lru_active_file = mems[b'Active(file):']
        lru_inactive_file = mems[b'Inactive(file):']
        slab_reclaimable = mems[b'SReclaimable:']
    except KeyError as err:
        debug(
            "%s is missing from /proc/meminfo; using an approximation for "
            "calculating available memory"
            % err.args[0]
        )
        return fallback
    try:
        f = open_binary('%s/zoneinfo' % get_procfs_path())
    except IOError:
        return fallback  # kernel 2.6.13

    watermark_low = 0
    with f:
        for line in f:
            line = line.strip()
            if line.startswith(b'low'):
                watermark_low += int(line.split()[1])
    watermark_low *= PAGESIZE

    avail = free - watermark_low
    pagecache = lru_active_file + lru_inactive_file
    pagecache -= min(pagecache / 2, watermark_low)
    avail += pagecache
    avail += slab_reclaimable - min(slab_reclaimable / 2.0, watermark_low)
    return int(avail)


def virtual_memory():
    """Report virtual memory stats.
    This implementation mimics procps-ng-3.3.12, aka "free" CLI tool:
    https://gitlab.com/procps-ng/procps/blob/
        24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L778-791
    The returned values are supposed to match both "free" and "vmstat -s"
    CLI tools.
    """
    missing_fields = []
    mems = {}
    with open_binary('%s/meminfo' % get_procfs_path()) as f:
        for line in f:
            fields = line.split()
            mems[fields[0]] = int(fields[1]) * 1024

    # /proc doc states that the available fields in /proc/meminfo vary
    # by architecture and compile options, but these 3 values are also
    # returned by sysinfo(2); as such we assume they are always there.
    total = mems[b'MemTotal:']
    free = mems[b'MemFree:']
    try:
        buffers = mems[b'Buffers:']
    except KeyError:
        # https://github.com/giampaolo/psutil/issues/1010
        buffers = 0
        missing_fields.append('buffers')
    try:
        cached = mems[b"Cached:"]
    except KeyError:
        cached = 0
        missing_fields.append('cached')
    else:
        # "free" cmdline utility sums reclaimable to cached.
        # Older versions of procps used to add slab memory instead.
        # This got changed in:
        # https://gitlab.com/procps-ng/procps/commit/
        #     05d751c4f076a2f0118b914c5e51cfbb4762ad8e
        cached += mems.get(b"SReclaimable:", 0)  # since kernel 2.6.19

    try:
        shared = mems[b'Shmem:']  # since kernel 2.6.32
    except KeyError:
        try:
            shared = mems[b'MemShared:']  # kernels 2.4
        except KeyError:
            shared = 0
            missing_fields.append('shared')

    try:
        active = mems[b"Active:"]
    except KeyError:
        active = 0
        missing_fields.append('active')

    try:
        inactive = mems[b"Inactive:"]
    except KeyError:
        try:
            inactive = (
                mems[b"Inact_dirty:"]
                + mems[b"Inact_clean:"]
                + mems[b"Inact_laundry:"]
            )
        except KeyError:
            inactive = 0
            missing_fields.append('inactive')

    try:
        slab = mems[b"Slab:"]
    except KeyError:
        slab = 0

    used = total - free - cached - buffers
    if used < 0:
        # May be symptomatic of running within a LCX container where such
        # values will be dramatically distorted over those of the host.
        used = total - free

    # - starting from 4.4.0 we match free's "available" column.
    #   Before 4.4.0 we calculated it as (free + buffers + cached)
    #   which matched htop.
    # - free and htop available memory differs as per:
    #   http://askubuntu.com/a/369589
    #   http://unix.stackexchange.com/a/65852/168884
    # - MemAvailable has been introduced in kernel 3.14
    try:
        avail = mems[b'MemAvailable:']
    except KeyError:
        avail = calculate_avail_vmem(mems)
    else:
        if avail == 0:
            # Yes, it can happen (probably a kernel bug):
            # https://github.com/giampaolo/psutil/issues/1915
            # In this case "free" CLI tool makes an estimate. We do the same,
            # and it matches "free" CLI tool.
            avail = calculate_avail_vmem(mems)

    if avail < 0:
        avail = 0
        missing_fields.append('available')
    elif avail > total:
        # If avail is greater than total or our calculation overflows,
        # that's symptomatic of running within a LCX container where such
        # values will be dramatically distorted over those of the host.
        # https://gitlab.com/procps-ng/procps/blob/
        #     24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764
        avail = free

    percent = usage_percent((total - avail), total, round_=1)

    # Warn about missing metrics which are set to 0.
    if missing_fields:
        msg = "%s memory stats couldn't be determined and %s set to 0" % (
            ", ".join(missing_fields),
            "was" if len(missing_fields) == 1 else "were",
        )
        warnings.warn(msg, RuntimeWarning, stacklevel=2)

    return svmem(
        total,
        avail,
        percent,
        used,
        free,
        active,
        inactive,
        buffers,
        cached,
        shared,
        slab,
    )


def swap_memory():
    """Return swap memory metrics."""
    mems = {}
    with open_binary('%s/meminfo' % get_procfs_path()) as f:
        for line in f:
            fields = line.split()
            mems[fields[0]] = int(fields[1]) * 1024
    # We prefer /proc/meminfo over sysinfo() syscall so that
    # psutil.PROCFS_PATH can be used in order to allow retrieval
    # for linux containers, see:
    # https://github.com/giampaolo/psutil/issues/1015
    try:
        total = mems[b'SwapTotal:']
        free = mems[b'SwapFree:']
    except KeyError:
        _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo()
        total *= unit_multiplier
        free *= unit_multiplier

    used = total - free
    percent = usage_percent(used, total, round_=1)
    # get pgin/pgouts
    try:
        f = open_binary("%s/vmstat" % get_procfs_path())
    except IOError as err:
        # see https://github.com/giampaolo/psutil/issues/722
        msg = (
            "'sin' and 'sout' swap memory stats couldn't "
            + "be determined and were set to 0 (%s)" % str(err)
        )
        warnings.warn(msg, RuntimeWarning, stacklevel=2)
        sin = sout = 0
    else:
        with f:
            sin = sout = None
            for line in f:
                # values are expressed in 4 kilo bytes, we want
                # bytes instead
                if line.startswith(b'pswpin'):
                    sin = int(line.split(b' ')[1]) * 4 * 1024
                elif line.startswith(b'pswpout'):
                    sout = int(line.split(b' ')[1]) * 4 * 1024
                if sin is not None and sout is not None:
                    break
            else:
                # we might get here when dealing with exotic Linux
                # flavors, see:
                # https://github.com/giampaolo/psutil/issues/313
                msg = "'sin' and 'sout' swap memory stats couldn't "
                msg += "be determined and were set to 0"
                warnings.warn(msg, RuntimeWarning, stacklevel=2)
                sin = sout = 0
    return _common.sswap(total, used, free, percent, sin, sout)


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return a named tuple representing the following system-wide
    CPU times:
    (user, nice, system, idle, iowait, irq, softirq [steal, [guest,
     [guest_nice]]])
    Last 3 fields may not be available on all Linux kernel versions.
    """
    procfs_path = get_procfs_path()
    set_scputimes_ntuple(procfs_path)
    with open_binary('%s/stat' % procfs_path) as f:
        values = f.readline().split()
    fields = values[1 : len(scputimes._fields) + 1]
    fields = [float(x) / CLOCK_TICKS for x in fields]
    return scputimes(*fields)


def per_cpu_times():
    """Return a list of namedtuple representing the CPU times
    for every CPU available on the system.
    """
    procfs_path = get_procfs_path()
    set_scputimes_ntuple(procfs_path)
    cpus = []
    with open_binary('%s/stat' % procfs_path) as f:
        # get rid of the first line which refers to system wide CPU stats
        f.readline()
        for line in f:
            if line.startswith(b'cpu'):
                values = line.split()
                fields = values[1 : len(scputimes._fields) + 1]
                fields = [float(x) / CLOCK_TICKS for x in fields]
                entry = scputimes(*fields)
                cpus.append(entry)
        return cpus


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    try:
        return os.sysconf("SC_NPROCESSORS_ONLN")
    except ValueError:
        # as a second fallback we try to parse /proc/cpuinfo
        num = 0
        with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
            for line in f:
                if line.lower().startswith(b'processor'):
                    num += 1

        # unknown format (e.g. amrel/sparc architectures), see:
        # https://github.com/giampaolo/psutil/issues/200
        # try to parse /proc/stat as a last resort
        if num == 0:
            search = re.compile(r'cpu\d')
            with open_text('%s/stat' % get_procfs_path()) as f:
                for line in f:
                    line = line.split(' ')[0]
                    if search.match(line):
                        num += 1

        if num == 0:
            # mimic os.cpu_count()
            return None
        return num


def cpu_count_cores():
    """Return the number of CPU cores in the system."""
    # Method #1
    ls = set()
    # These 2 files are the same but */core_cpus_list is newer while
    # */thread_siblings_list is deprecated and may disappear in the future.
    # https://www.kernel.org/doc/Documentation/admin-guide/cputopology.rst
    # https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964
    # https://lkml.org/lkml/2019/2/26/41
    p1 = "/sys/devices/system/cpu/cpu[0-9]*/topology/core_cpus_list"
    p2 = "/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"
    for path in glob.glob(p1) or glob.glob(p2):
        with open_binary(path) as f:
            ls.add(f.read().strip())
    result = len(ls)
    if result != 0:
        return result

    # Method #2
    mapping = {}
    current_info = {}
    with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
        for line in f:
            line = line.strip().lower()
            if not line:
                # new section
                try:
                    mapping[current_info[b'physical id']] = current_info[
                        b'cpu cores'
                    ]
                except KeyError:
                    pass
                current_info = {}
            else:
                # ongoing section
                if line.startswith((b'physical id', b'cpu cores')):
                    key, value = line.split(b'\t:', 1)
                    current_info[key] = int(value)

    result = sum(mapping.values())
    return result or None  # mimic os.cpu_count()


def cpu_stats():
    """Return various CPU stats as a named tuple."""
    with open_binary('%s/stat' % get_procfs_path()) as f:
        ctx_switches = None
        interrupts = None
        soft_interrupts = None
        for line in f:
            if line.startswith(b'ctxt'):
                ctx_switches = int(line.split()[1])
            elif line.startswith(b'intr'):
                interrupts = int(line.split()[1])
            elif line.startswith(b'softirq'):
                soft_interrupts = int(line.split()[1])
            if (
                ctx_switches is not None
                and soft_interrupts is not None
                and interrupts is not None
            ):
                break
    syscalls = 0
    return _common.scpustats(
        ctx_switches, interrupts, soft_interrupts, syscalls
    )


def _cpu_get_cpuinfo_freq():
    """Return current CPU frequency from cpuinfo if available."""
    ret = []
    with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
        for line in f:
            if line.lower().startswith(b'cpu mhz'):
                ret.append(float(line.split(b':', 1)[1]))
    return ret


if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or os.path.exists(
    "/sys/devices/system/cpu/cpu0/cpufreq"
):

    def cpu_freq():
        """Return frequency metrics for all CPUs.
        Contrarily to other OSes, Linux updates these values in
        real-time.
        """
        cpuinfo_freqs = _cpu_get_cpuinfo_freq()
        paths = glob.glob(
            "/sys/devices/system/cpu/cpufreq/policy[0-9]*"
        ) or glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq")
        paths.sort(key=lambda x: int(re.search(r"[0-9]+", x).group()))
        ret = []
        pjoin = os.path.join
        for i, path in enumerate(paths):
            if len(paths) == len(cpuinfo_freqs):
                # take cached value from cpuinfo if available, see:
                # https://github.com/giampaolo/psutil/issues/1851
                curr = cpuinfo_freqs[i] * 1000
            else:
                curr = bcat(pjoin(path, "scaling_cur_freq"), fallback=None)
            if curr is None:
                # Likely an old RedHat, see:
                # https://github.com/giampaolo/psutil/issues/1071
                curr = bcat(pjoin(path, "cpuinfo_cur_freq"), fallback=None)
                if curr is None:
                    online_path = (
                        "/sys/devices/system/cpu/cpu{}/online".format(i)
                    )
                    # if cpu core is offline, set to all zeroes
                    if cat(online_path, fallback=None) == "0\n":
                        ret.append(_common.scpufreq(0.0, 0.0, 0.0))
                        continue
                    msg = "can't find current frequency file"
                    raise NotImplementedError(msg)
            curr = int(curr) / 1000
            max_ = int(bcat(pjoin(path, "scaling_max_freq"))) / 1000
            min_ = int(bcat(pjoin(path, "scaling_min_freq"))) / 1000
            ret.append(_common.scpufreq(curr, min_, max_))
        return ret

else:

    def cpu_freq():
        """Alternate implementation using /proc/cpuinfo.
        min and max frequencies are not available and are set to None.
        """
        return [_common.scpufreq(x, 0.0, 0.0) for x in _cpu_get_cpuinfo_freq()]


# =====================================================================
# --- network
# =====================================================================


net_if_addrs = cext_posix.net_if_addrs


class _Ipv6UnsupportedError(Exception):
    pass


class NetConnections:
    """A wrapper on top of /proc/net/* files, retrieving per-process
    and system-wide open connections (TCP, UDP, UNIX) similarly to
    "netstat -an".

    Note: in case of UNIX sockets we're only able to determine the
    local endpoint/path, not the one it's connected to.
    According to [1] it would be possible but not easily.

    [1] http://serverfault.com/a/417946
    """

    def __init__(self):
        # The string represents the basename of the corresponding
        # /proc/net/{proto_name} file.
        tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM)
        tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM)
        udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM)
        udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM)
        unix = ("unix", socket.AF_UNIX, None)
        self.tmap = {
            "all": (tcp4, tcp6, udp4, udp6, unix),
            "tcp": (tcp4, tcp6),
            "tcp4": (tcp4,),
            "tcp6": (tcp6,),
            "udp": (udp4, udp6),
            "udp4": (udp4,),
            "udp6": (udp6,),
            "unix": (unix,),
            "inet": (tcp4, tcp6, udp4, udp6),
            "inet4": (tcp4, udp4),
            "inet6": (tcp6, udp6),
        }
        self._procfs_path = None

    def get_proc_inodes(self, pid):
        inodes = defaultdict(list)
        for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)):
            try:
                inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd))
            except (FileNotFoundError, ProcessLookupError):
                # ENOENT == file which is gone in the meantime;
                # os.stat('/proc/%s' % self.pid) will be done later
                # to force NSP (if it's the case)
                continue
            except OSError as err:
                if err.errno == errno.EINVAL:
                    # not a link
                    continue
                if err.errno == errno.ENAMETOOLONG:
                    # file name too long
                    debug(err)
                    continue
                raise
            else:
                if inode.startswith('socket:['):
                    # the process is using a socket
                    inode = inode[8:][:-1]
                    inodes[inode].append((pid, int(fd)))
        return inodes

    def get_all_inodes(self):
        inodes = {}
        for pid in pids():
            try:
                inodes.update(self.get_proc_inodes(pid))
            except (FileNotFoundError, ProcessLookupError, PermissionError):
                # os.listdir() is gonna raise a lot of access denied
                # exceptions in case of unprivileged user; that's fine
                # as we'll just end up returning a connection with PID
                # and fd set to None anyway.
                # Both netstat -an and lsof does the same so it's
                # unlikely we can do any better.
                # ENOENT just means a PID disappeared on us.
                continue
        return inodes

    @staticmethod
    def decode_address(addr, family):
        """Accept an "ip:port" address as displayed in /proc/net/*
        and convert it into a human readable form, like:

        "0500000A:0016" -> ("10.0.0.5", 22)
        "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)

        The IP address portion is a little or big endian four-byte
        hexadecimal number; that is, the least significant byte is listed
        first, so we need to reverse the order of the bytes to convert it
        to an IP address.
        The port is represented as a two-byte hexadecimal number.

        Reference:
        http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html
        """
        ip, port = addr.split(':')
        port = int(port, 16)
        # this usually refers to a local socket in listen mode with
        # no end-points connected
        if not port:
            return ()
        if PY3:
            ip = ip.encode('ascii')
        if family == socket.AF_INET:
            # see: https://github.com/giampaolo/psutil/issues/201
            if LITTLE_ENDIAN:
                ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1])
            else:
                ip = socket.inet_ntop(family, base64.b16decode(ip))
        else:  # IPv6
            ip = base64.b16decode(ip)
            try:
                # see: https://github.com/giampaolo/psutil/issues/201
                if LITTLE_ENDIAN:
                    ip = socket.inet_ntop(
                        socket.AF_INET6,
                        struct.pack('>4I', *struct.unpack('<4I', ip)),
                    )
                else:
                    ip = socket.inet_ntop(
                        socket.AF_INET6,
                        struct.pack('<4I', *struct.unpack('<4I', ip)),
                    )
            except ValueError:
                # see: https://github.com/giampaolo/psutil/issues/623
                if not supports_ipv6():
                    raise _Ipv6UnsupportedError
                else:
                    raise
        return _common.addr(ip, port)

    @staticmethod
    def process_inet(file, family, type_, inodes, filter_pid=None):
        """Parse /proc/net/tcp* and /proc/net/udp* files."""
        if file.endswith('6') and not os.path.exists(file):
            # IPv6 not supported
            return
        with open_text(file) as f:
            f.readline()  # skip the first line
            for lineno, line in enumerate(f, 1):
                try:
                    _, laddr, raddr, status, _, _, _, _, _, inode = (
                        line.split()[:10]
                    )
                except ValueError:
                    raise RuntimeError(
                        "error while parsing %s; malformed line %s %r"
                        % (file, lineno, line)
                    )
                if inode in inodes:
                    # # We assume inet sockets are unique, so we error
                    # # out if there are multiple references to the
                    # # same inode. We won't do this for UNIX sockets.
                    # if len(inodes[inode]) > 1 and family != socket.AF_UNIX:
                    #     raise ValueError("ambiguous inode with multiple "
                    #                      "PIDs references")
                    pid, fd = inodes[inode][0]
                else:
                    pid, fd = None, -1
                if filter_pid is not None and filter_pid != pid:
                    continue
                else:
                    if type_ == socket.SOCK_STREAM:
                        status = TCP_STATUSES[status]
                    else:
                        status = _common.CONN_NONE
                    try:
                        laddr = NetConnections.decode_address(laddr, family)
                        raddr = NetConnections.decode_address(raddr, family)
                    except _Ipv6UnsupportedError:
                        continue
                    yield (fd, family, type_, laddr, raddr, status, pid)

    @staticmethod
    def process_unix(file, family, inodes, filter_pid=None):
        """Parse /proc/net/unix files."""
        with open_text(file) as f:
            f.readline()  # skip the first line
            for line in f:
                tokens = line.split()
                try:
                    _, _, _, _, type_, _, inode = tokens[0:7]
                except ValueError:
                    if ' ' not in line:
                        # see: https://github.com/giampaolo/psutil/issues/766
                        continue
                    raise RuntimeError(
                        "error while parsing %s; malformed line %r"
                        % (file, line)
                    )
                if inode in inodes:  # noqa
                    # With UNIX sockets we can have a single inode
                    # referencing many file descriptors.
                    pairs = inodes[inode]
                else:
                    pairs = [(None, -1)]
                for pid, fd in pairs:
                    if filter_pid is not None and filter_pid != pid:
                        continue
                    else:
                        path = tokens[-1] if len(tokens) == 8 else ''
                        type_ = _common.socktype_to_enum(int(type_))
                        # XXX: determining the remote endpoint of a
                        # UNIX socket on Linux is not possible, see:
                        # https://serverfault.com/questions/252723/
                        raddr = ""
                        status = _common.CONN_NONE
                        yield (fd, family, type_, path, raddr, status, pid)

    def retrieve(self, kind, pid=None):
        if kind not in self.tmap:
            raise ValueError(
                "invalid %r kind argument; choose between %s"
                % (kind, ', '.join([repr(x) for x in self.tmap]))
            )
        self._procfs_path = get_procfs_path()
        if pid is not None:
            inodes = self.get_proc_inodes(pid)
            if not inodes:
                # no connections for this process
                return []
        else:
            inodes = self.get_all_inodes()
        ret = set()
        for proto_name, family, type_ in self.tmap[kind]:
            path = "%s/net/%s" % (self._procfs_path, proto_name)
            if family in (socket.AF_INET, socket.AF_INET6):
                ls = self.process_inet(
                    path, family, type_, inodes, filter_pid=pid
                )
            else:
                ls = self.process_unix(path, family, inodes, filter_pid=pid)
            for fd, family, type_, laddr, raddr, status, bound_pid in ls:
                if pid:
                    conn = _common.pconn(
                        fd, family, type_, laddr, raddr, status
                    )
                else:
                    conn = _common.sconn(
                        fd, family, type_, laddr, raddr, status, bound_pid
                    )
                ret.add(conn)
        return list(ret)


_net_connections = NetConnections()


def net_connections(kind='inet'):
    """Return system-wide open connections."""
    return _net_connections.retrieve(kind)


def net_io_counters():
    """Return network I/O statistics for every network interface
    installed on the system as a dict of raw tuples.
    """
    with open_text("%s/net/dev" % get_procfs_path()) as f:
        lines = f.readlines()
    retdict = {}
    for line in lines[2:]:
        colon = line.rfind(':')
        assert colon > 0, repr(line)
        name = line[:colon].strip()
        fields = line[colon + 1 :].strip().split()

        (
            # in
            bytes_recv,
            packets_recv,
            errin,
            dropin,
            _fifoin,  # unused
            _framein,  # unused
            _compressedin,  # unused
            _multicastin,  # unused
            # out
            bytes_sent,
            packets_sent,
            errout,
            dropout,
            _fifoout,  # unused
            _collisionsout,  # unused
            _carrierout,  # unused
            _compressedout,  # unused
        ) = map(int, fields)

        retdict[name] = (
            bytes_sent,
            bytes_recv,
            packets_sent,
            packets_recv,
            errin,
            errout,
            dropin,
            dropout,
        )
    return retdict


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    duplex_map = {
        cext.DUPLEX_FULL: NIC_DUPLEX_FULL,
        cext.DUPLEX_HALF: NIC_DUPLEX_HALF,
        cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN,
    }
    names = net_io_counters().keys()
    ret = {}
    for name in names:
        try:
            mtu = cext_posix.net_if_mtu(name)
            flags = cext_posix.net_if_flags(name)
            duplex, speed = cext.net_if_duplex_speed(name)
        except OSError as err:
            # https://github.com/giampaolo/psutil/issues/1279
            if err.errno != errno.ENODEV:
                raise
            else:
                debug(err)
        else:
            output_flags = ','.join(flags)
            isup = 'running' in flags
            ret[name] = _common.snicstats(
                isup, duplex_map[duplex], speed, mtu, output_flags
            )
    return ret


# =====================================================================
# --- disks
# =====================================================================


disk_usage = _psposix.disk_usage


def disk_io_counters(perdisk=False):
    """Return disk I/O statistics for every disk installed on the
    system as a dict of raw tuples.
    """

    def read_procfs():
        # OK, this is a bit confusing. The format of /proc/diskstats can
        # have 3 variations.
        # On Linux 2.4 each line has always 15 fields, e.g.:
        # "3     0   8 hda 8 8 8 8 8 8 8 8 8 8 8"
        # On Linux 2.6+ each line *usually* has 14 fields, and the disk
        # name is in another position, like this:
        # "3    0   hda 8 8 8 8 8 8 8 8 8 8 8"
        # ...unless (Linux 2.6) the line refers to a partition instead
        # of a disk, in which case the line has less fields (7):
        # "3    1   hda1 8 8 8 8"
        # 4.18+ has 4 fields added:
        # "3    0   hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0"
        # 5.5 has 2 more fields.
        # See:
        # https://www.kernel.org/doc/Documentation/iostats.txt
        # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
        with open_text("%s/diskstats" % get_procfs_path()) as f:
            lines = f.readlines()
        for line in lines:
            fields = line.split()
            flen = len(fields)
            # fmt: off
            if flen == 15:
                # Linux 2.4
                name = fields[3]
                reads = int(fields[2])
                (reads_merged, rbytes, rtime, writes, writes_merged,
                    wbytes, wtime, _, busy_time, _) = map(int, fields[4:14])
            elif flen == 14 or flen >= 18:
                # Linux 2.6+, line referring to a disk
                name = fields[2]
                (reads, reads_merged, rbytes, rtime, writes, writes_merged,
                    wbytes, wtime, _, busy_time, _) = map(int, fields[3:14])
            elif flen == 7:
                # Linux 2.6+, line referring to a partition
                name = fields[2]
                reads, rbytes, writes, wbytes = map(int, fields[3:])
                rtime = wtime = reads_merged = writes_merged = busy_time = 0
            else:
                raise ValueError("not sure how to interpret line %r" % line)
            yield (name, reads, writes, rbytes, wbytes, rtime, wtime,
                   reads_merged, writes_merged, busy_time)
            # fmt: on

    def read_sysfs():
        for block in os.listdir('/sys/block'):
            for root, _, files in os.walk(os.path.join('/sys/block', block)):
                if 'stat' not in files:
                    continue
                with open_text(os.path.join(root, 'stat')) as f:
                    fields = f.read().strip().split()
                name = os.path.basename(root)
                # fmt: off
                (reads, reads_merged, rbytes, rtime, writes, writes_merged,
                    wbytes, wtime, _, busy_time) = map(int, fields[:10])
                yield (name, reads, writes, rbytes, wbytes, rtime,
                       wtime, reads_merged, writes_merged, busy_time)
                # fmt: on

    if os.path.exists('%s/diskstats' % get_procfs_path()):
        gen = read_procfs()
    elif os.path.exists('/sys/block'):
        gen = read_sysfs()
    else:
        raise NotImplementedError(
            "%s/diskstats nor /sys/block filesystem are available on this "
            "system"
            % get_procfs_path()
        )

    retdict = {}
    for entry in gen:
        # fmt: off
        (name, reads, writes, rbytes, wbytes, rtime, wtime, reads_merged,
            writes_merged, busy_time) = entry
        if not perdisk and not is_storage_device(name):
            # perdisk=False means we want to calculate totals so we skip
            # partitions (e.g. 'sda1', 'nvme0n1p1') and only include
            # base disk devices (e.g. 'sda', 'nvme0n1'). Base disks
            # include a total of all their partitions + some extra size
            # of their own:
            #     $ cat /proc/diskstats
            #     259       0 sda 10485760 ...
            #     259       1 sda1 5186039 ...
            #     259       1 sda2 5082039 ...
            # See:
            # https://github.com/giampaolo/psutil/pull/1313
            continue

        rbytes *= DISK_SECTOR_SIZE
        wbytes *= DISK_SECTOR_SIZE
        retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime,
                         reads_merged, writes_merged, busy_time)
        # fmt: on

    return retdict


class RootFsDeviceFinder:
    """disk_partitions() may return partitions with device == "/dev/root"
    or "rootfs". This container class uses different strategies to try to
    obtain the real device path. Resources:
    https://bootlin.com/blog/find-root-device/
    https://www.systutorials.com/how-to-find-the-disk-where-root-is-on-in-bash-on-linux/.
    """

    __slots__ = ['major', 'minor']

    def __init__(self):
        dev = os.stat("/").st_dev
        self.major = os.major(dev)
        self.minor = os.minor(dev)

    def ask_proc_partitions(self):
        with open_text("%s/partitions" % get_procfs_path()) as f:
            for line in f.readlines()[2:]:
                fields = line.split()
                if len(fields) < 4:  # just for extra safety
                    continue
                major = int(fields[0]) if fields[0].isdigit() else None
                minor = int(fields[1]) if fields[1].isdigit() else None
                name = fields[3]
                if major == self.major and minor == self.minor:
                    if name:  # just for extra safety
                        return "/dev/%s" % name

    def ask_sys_dev_block(self):
        path = "/sys/dev/block/%s:%s/uevent" % (self.major, self.minor)
        with open_text(path) as f:
            for line in f:
                if line.startswith("DEVNAME="):
                    name = line.strip().rpartition("DEVNAME=")[2]
                    if name:  # just for extra safety
                        return "/dev/%s" % name

    def ask_sys_class_block(self):
        needle = "%s:%s" % (self.major, self.minor)
        files = glob.iglob("/sys/class/block/*/dev")
        for file in files:
            try:
                f = open_text(file)
            except FileNotFoundError:  # race condition
                continue
            else:
                with f:
                    data = f.read().strip()
                    if data == needle:
                        name = os.path.basename(os.path.dirname(file))
                        return "/dev/%s" % name

    def find(self):
        path = None
        if path is None:
            try:
                path = self.ask_proc_partitions()
            except (IOError, OSError) as err:
                debug(err)
        if path is None:
            try:
                path = self.ask_sys_dev_block()
            except (IOError, OSError) as err:
                debug(err)
        if path is None:
            try:
                path = self.ask_sys_class_block()
            except (IOError, OSError) as err:
                debug(err)
        # We use exists() because the "/dev/*" part of the path is hard
        # coded, so we want to be sure.
        if path is not None and os.path.exists(path):
            return path


def disk_partitions(all=False):
    """Return mounted disk partitions as a list of namedtuples."""
    fstypes = set()
    procfs_path = get_procfs_path()
    if not all:
        with open_text("%s/filesystems" % procfs_path) as f:
            for line in f:
                line = line.strip()
                if not line.startswith("nodev"):
                    fstypes.add(line.strip())
                else:
                    # ignore all lines starting with "nodev" except "nodev zfs"
                    fstype = line.split("\t")[1]
                    if fstype == "zfs":
                        fstypes.add("zfs")

    # See: https://github.com/giampaolo/psutil/issues/1307
    if procfs_path == "/proc" and os.path.isfile('/etc/mtab'):
        mounts_path = os.path.realpath("/etc/mtab")
    else:
        mounts_path = os.path.realpath("%s/self/mounts" % procfs_path)

    retlist = []
    partitions = cext.disk_partitions(mounts_path)
    for partition in partitions:
        device, mountpoint, fstype, opts = partition
        if device == 'none':
            device = ''
        if device in ("/dev/root", "rootfs"):
            device = RootFsDeviceFinder().find() or device
        if not all:
            if not device or fstype not in fstypes:
                continue
        ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
        retlist.append(ntuple)

    return retlist


# =====================================================================
# --- sensors
# =====================================================================


def sensors_temperatures():
    """Return hardware (CPU and others) temperatures as a dict
    including hardware name, label, current, max and critical
    temperatures.

    Implementation notes:
    - /sys/class/hwmon looks like the most recent interface to
      retrieve this info, and this implementation relies on it
      only (old distros will probably use something else)
    - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon
    - /sys/class/thermal/thermal_zone* is another one but it's more
      difficult to parse
    """
    ret = collections.defaultdict(list)
    basenames = glob.glob('/sys/class/hwmon/hwmon*/temp*_*')
    # CentOS has an intermediate /device directory:
    # https://github.com/giampaolo/psutil/issues/971
    # https://github.com/nicolargo/glances/issues/1060
    basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*'))
    basenames = sorted(set([x.split('_')[0] for x in basenames]))

    # Only add the coretemp hwmon entries if they're not already in
    # /sys/class/hwmon/
    # https://github.com/giampaolo/psutil/issues/1708
    # https://github.com/giampaolo/psutil/pull/1648
    basenames2 = glob.glob(
        '/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*'
    )
    repl = re.compile('/sys/devices/platform/coretemp.*/hwmon/')
    for name in basenames2:
        altname = repl.sub('/sys/class/hwmon/', name)
        if altname not in basenames:
            basenames.append(name)

    for base in basenames:
        try:
            path = base + '_input'
            current = float(bcat(path)) / 1000.0
            path = os.path.join(os.path.dirname(base), 'name')
            unit_name = cat(path).strip()
        except (IOError, OSError, ValueError):
            # A lot of things can go wrong here, so let's just skip the
            # whole entry. Sure thing is Linux's /sys/class/hwmon really
            # is a stinky broken mess.
            # https://github.com/giampaolo/psutil/issues/1009
            # https://github.com/giampaolo/psutil/issues/1101
            # https://github.com/giampaolo/psutil/issues/1129
            # https://github.com/giampaolo/psutil/issues/1245
            # https://github.com/giampaolo/psutil/issues/1323
            continue

        high = bcat(base + '_max', fallback=None)
        critical = bcat(base + '_crit', fallback=None)
        label = cat(base + '_label', fallback='').strip()

        if high is not None:
            try:
                high = float(high) / 1000.0
            except ValueError:
                high = None
        if critical is not None:
            try:
                critical = float(critical) / 1000.0
            except ValueError:
                critical = None

        ret[unit_name].append((label, current, high, critical))

    # Indication that no sensors were detected in /sys/class/hwmon/
    if not basenames:
        basenames = glob.glob('/sys/class/thermal/thermal_zone*')
        basenames = sorted(set(basenames))

        for base in basenames:
            try:
                path = os.path.join(base, 'temp')
                current = float(bcat(path)) / 1000.0
                path = os.path.join(base, 'type')
                unit_name = cat(path).strip()
            except (IOError, OSError, ValueError) as err:
                debug(err)
                continue

            trip_paths = glob.glob(base + '/trip_point*')
            trip_points = set([
                '_'.join(os.path.basename(p).split('_')[0:3])
                for p in trip_paths
            ])
            critical = None
            high = None
            for trip_point in trip_points:
                path = os.path.join(base, trip_point + "_type")
                trip_type = cat(path, fallback='').strip()
                if trip_type == 'critical':
                    critical = bcat(
                        os.path.join(base, trip_point + "_temp"), fallback=None
                    )
                elif trip_type == 'high':
                    high = bcat(
                        os.path.join(base, trip_point + "_temp"), fallback=None
                    )

                if high is not None:
                    try:
                        high = float(high) / 1000.0
                    except ValueError:
                        high = None
                if critical is not None:
                    try:
                        critical = float(critical) / 1000.0
                    except ValueError:
                        critical = None

            ret[unit_name].append(('', current, high, critical))

    return dict(ret)


def sensors_fans():
    """Return hardware fans info (for CPU and other peripherals) as a
    dict including hardware label and current speed.

    Implementation notes:
    - /sys/class/hwmon looks like the most recent interface to
      retrieve this info, and this implementation relies on it
      only (old distros will probably use something else)
    - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon
    """
    ret = collections.defaultdict(list)
    basenames = glob.glob('/sys/class/hwmon/hwmon*/fan*_*')
    if not basenames:
        # CentOS has an intermediate /device directory:
        # https://github.com/giampaolo/psutil/issues/971
        basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*')

    basenames = sorted(set([x.split('_')[0] for x in basenames]))
    for base in basenames:
        try:
            current = int(bcat(base + '_input'))
        except (IOError, OSError) as err:
            debug(err)
            continue
        unit_name = cat(os.path.join(os.path.dirname(base), 'name')).strip()
        label = cat(base + '_label', fallback='').strip()
        ret[unit_name].append(_common.sfan(label, current))

    return dict(ret)


def sensors_battery():
    """Return battery information.
    Implementation note: it appears /sys/class/power_supply/BAT0/
    directory structure may vary and provide files with the same
    meaning but under different names, see:
    https://github.com/giampaolo/psutil/issues/966.
    """
    null = object()

    def multi_bcat(*paths):
        """Attempt to read the content of multiple files which may
        not exist. If none of them exist return None.
        """
        for path in paths:
            ret = bcat(path, fallback=null)
            if ret != null:
                try:
                    return int(ret)
                except ValueError:
                    return ret.strip()
        return None

    bats = [
        x
        for x in os.listdir(POWER_SUPPLY_PATH)
        if x.startswith('BAT') or 'battery' in x.lower()
    ]
    if not bats:
        return None
    # Get the first available battery. Usually this is "BAT0", except
    # some rare exceptions:
    # https://github.com/giampaolo/psutil/issues/1238
    root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0])

    # Base metrics.
    energy_now = multi_bcat(root + "/energy_now", root + "/charge_now")
    power_now = multi_bcat(root + "/power_now", root + "/current_now")
    energy_full = multi_bcat(root + "/energy_full", root + "/charge_full")
    time_to_empty = multi_bcat(root + "/time_to_empty_now")

    # Percent. If we have energy_full the percentage will be more
    # accurate compared to reading /capacity file (float vs. int).
    if energy_full is not None and energy_now is not None:
        try:
            percent = 100.0 * energy_now / energy_full
        except ZeroDivisionError:
            percent = 0.0
    else:
        percent = int(cat(root + "/capacity", fallback=-1))
        if percent == -1:
            return None

    # Is AC power cable plugged in?
    # Note: AC0 is not always available and sometimes (e.g. CentOS7)
    # it's called "AC".
    power_plugged = None
    online = multi_bcat(
        os.path.join(POWER_SUPPLY_PATH, "AC0/online"),
        os.path.join(POWER_SUPPLY_PATH, "AC/online"),
    )
    if online is not None:
        power_plugged = online == 1
    else:
        status = cat(root + "/status", fallback="").strip().lower()
        if status == "discharging":
            power_plugged = False
        elif status in ("charging", "full"):
            power_plugged = True

    # Seconds left.
    # Note to self: we may also calculate the charging ETA as per:
    # https://github.com/thialfihar/dotfiles/blob/
    #     013937745fd9050c30146290e8f963d65c0179e6/bin/battery.py#L55
    if power_plugged:
        secsleft = _common.POWER_TIME_UNLIMITED
    elif energy_now is not None and power_now is not None:
        try:
            secsleft = int(energy_now / power_now * 3600)
        except ZeroDivisionError:
            secsleft = _common.POWER_TIME_UNKNOWN
    elif time_to_empty is not None:
        secsleft = int(time_to_empty * 60)
        if secsleft < 0:
            secsleft = _common.POWER_TIME_UNKNOWN
    else:
        secsleft = _common.POWER_TIME_UNKNOWN

    return _common.sbattery(percent, secsleft, power_plugged)


# =====================================================================
# --- other system functions
# =====================================================================


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    for item in rawlist:
        user, tty, hostname, tstamp, pid = item
        nt = _common.suser(user, tty or None, hostname, tstamp, pid)
        retlist.append(nt)
    return retlist


def boot_time():
    """Return the system boot time expressed in seconds since the epoch."""
    global BOOT_TIME
    path = '%s/stat' % get_procfs_path()
    with open_binary(path) as f:
        for line in f:
            if line.startswith(b'btime'):
                ret = float(line.strip().split()[1])
                BOOT_TIME = ret
                return ret
        raise RuntimeError("line 'btime' not found in %s" % path)


# =====================================================================
# --- processes
# =====================================================================


def pids():
    """Returns a list of PIDs currently running on the system."""
    return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()]


def pid_exists(pid):
    """Check for the existence of a unix PID. Linux TIDs are not
    supported (always return False).
    """
    if not _psposix.pid_exists(pid):
        return False
    else:
        # Linux's apparently does not distinguish between PIDs and TIDs
        # (thread IDs).
        # listdir("/proc") won't show any TID (only PIDs) but
        # os.stat("/proc/{tid}") will succeed if {tid} exists.
        # os.kill() can also be passed a TID. This is quite confusing.
        # In here we want to enforce this distinction and support PIDs
        # only, see:
        # https://github.com/giampaolo/psutil/issues/687
        try:
            # Note: already checked that this is faster than using a
            # regular expr. Also (a lot) faster than doing
            # 'return pid in pids()'
            path = "%s/%s/status" % (get_procfs_path(), pid)
            with open_binary(path) as f:
                for line in f:
                    if line.startswith(b"Tgid:"):
                        tgid = int(line.split()[1])
                        # If tgid and pid are the same then we're
                        # dealing with a process PID.
                        return tgid == pid
                raise ValueError("'Tgid' line not found in %s" % path)
        except (EnvironmentError, ValueError):
            return pid in pids()


def ppid_map():
    """Obtain a {pid: ppid, ...} dict for all running processes in
    one shot. Used to speed up Process.children().
    """
    ret = {}
    procfs_path = get_procfs_path()
    for pid in pids():
        try:
            with open_binary("%s/%s/stat" % (procfs_path, pid)) as f:
                data = f.read()
        except (FileNotFoundError, ProcessLookupError):
            # Note: we should be able to access /stat for all processes
            # aka it's unlikely we'll bump into EPERM, which is good.
            pass
        else:
            rpar = data.rfind(b')')
            dset = data[rpar + 2 :].split()
            ppid = int(dset[1])
            ret[pid] = ppid
    return ret


def wrap_exceptions(fun):
    """Decorator which translates bare OSError and IOError exceptions
    into NoSuchProcess and AccessDenied.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except PermissionError:
            raise AccessDenied(self.pid, self._name)
        except ProcessLookupError:
            self._raise_if_zombie()
            raise NoSuchProcess(self.pid, self._name)
        except FileNotFoundError:
            self._raise_if_zombie()
            if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)):
                raise NoSuchProcess(self.pid, self._name)
            raise

    return wrapper


class Process:
    """Linux process implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "_procfs_path", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None
        self._procfs_path = get_procfs_path()

    def _is_zombie(self):
        # Note: most of the times Linux is able to return info about the
        # process even if it's a zombie, and /proc/{pid} will exist.
        # There are some exceptions though, like exe(), cmdline() and
        # memory_maps(). In these cases /proc/{pid}/{file} exists but
        # it's empty. Instead of returning a "null" value we'll raise an
        # exception.
        try:
            data = bcat("%s/%s/stat" % (self._procfs_path, self.pid))
        except (IOError, OSError):
            return False
        else:
            rpar = data.rfind(b')')
            status = data[rpar + 2 : rpar + 3]
            return status == b"Z"

    def _raise_if_zombie(self):
        if self._is_zombie():
            raise ZombieProcess(self.pid, self._name, self._ppid)

    def _raise_if_not_alive(self):
        """Raise NSP if the process disappeared on us."""
        # For those C function who do not raise NSP, possibly returning
        # incorrect or incomplete result.
        os.stat('%s/%s' % (self._procfs_path, self.pid))

    @wrap_exceptions
    @memoize_when_activated
    def _parse_stat_file(self):
        """Parse /proc/{pid}/stat file and return a dict with various
        process info.
        Using "man proc" as a reference: where "man proc" refers to
        position N always subtract 3 (e.g ppid position 4 in
        'man proc' == position 1 in here).
        The return value is cached in case oneshot() ctx manager is
        in use.
        """
        data = bcat("%s/%s/stat" % (self._procfs_path, self.pid))
        # Process name is between parentheses. It can contain spaces and
        # other parentheses. This is taken into account by looking for
        # the first occurrence of "(" and the last occurrence of ")".
        rpar = data.rfind(b')')
        name = data[data.find(b'(') + 1 : rpar]
        fields = data[rpar + 2 :].split()

        ret = {}
        ret['name'] = name
        ret['status'] = fields[0]
        ret['ppid'] = fields[1]
        ret['ttynr'] = fields[4]
        ret['utime'] = fields[11]
        ret['stime'] = fields[12]
        ret['children_utime'] = fields[13]
        ret['children_stime'] = fields[14]
        ret['create_time'] = fields[19]
        ret['cpu_num'] = fields[36]
        try:
            ret['blkio_ticks'] = fields[39]  # aka 'delayacct_blkio_ticks'
        except IndexError:
            # https://github.com/giampaolo/psutil/issues/2455
            debug("can't get blkio_ticks, set iowait to 0")
            ret['blkio_ticks'] = 0

        return ret

    @wrap_exceptions
    @memoize_when_activated
    def _read_status_file(self):
        """Read /proc/{pid}/stat file and return its content.
        The return value is cached in case oneshot() ctx manager is
        in use.
        """
        with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f:
            return f.read()

    @wrap_exceptions
    @memoize_when_activated
    def _read_smaps_file(self):
        with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid)) as f:
            return f.read().strip()

    def oneshot_enter(self):
        self._parse_stat_file.cache_activate(self)
        self._read_status_file.cache_activate(self)
        self._read_smaps_file.cache_activate(self)

    def oneshot_exit(self):
        self._parse_stat_file.cache_deactivate(self)
        self._read_status_file.cache_deactivate(self)
        self._read_smaps_file.cache_deactivate(self)

    @wrap_exceptions
    def name(self):
        name = self._parse_stat_file()['name']
        if PY3:
            name = decode(name)
        # XXX - gets changed later and probably needs refactoring
        return name

    @wrap_exceptions
    def exe(self):
        try:
            return readlink("%s/%s/exe" % (self._procfs_path, self.pid))
        except (FileNotFoundError, ProcessLookupError):
            self._raise_if_zombie()
            # no such file error; might be raised also if the
            # path actually exists for system processes with
            # low pids (about 0-20)
            if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
                return ""
            raise

    @wrap_exceptions
    def cmdline(self):
        with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f:
            data = f.read()
        if not data:
            # may happen in case of zombie process
            self._raise_if_zombie()
            return []
        # 'man proc' states that args are separated by null bytes '\0'
        # and last char is supposed to be a null byte. Nevertheless
        # some processes may change their cmdline after being started
        # (via setproctitle() or similar), they are usually not
        # compliant with this rule and use spaces instead. Google
        # Chrome process is an example. See:
        # https://github.com/giampaolo/psutil/issues/1179
        sep = '\x00' if data.endswith('\x00') else ' '
        if data.endswith(sep):
            data = data[:-1]
        cmdline = data.split(sep)
        # Sometimes last char is a null byte '\0' but the args are
        # separated by spaces, see: https://github.com/giampaolo/psutil/
        # issues/1179#issuecomment-552984549
        if sep == '\x00' and len(cmdline) == 1 and ' ' in data:
            cmdline = data.split(' ')
        return cmdline

    @wrap_exceptions
    def environ(self):
        with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f:
            data = f.read()
        return parse_environ_block(data)

    @wrap_exceptions
    def terminal(self):
        tty_nr = int(self._parse_stat_file()['ttynr'])
        tmap = _psposix.get_terminal_map()
        try:
            return tmap[tty_nr]
        except KeyError:
            return None

    # May not be available on old kernels.
    if os.path.exists('/proc/%s/io' % os.getpid()):

        @wrap_exceptions
        def io_counters(self):
            fname = "%s/%s/io" % (self._procfs_path, self.pid)
            fields = {}
            with open_binary(fname) as f:
                for line in f:
                    # https://github.com/giampaolo/psutil/issues/1004
                    line = line.strip()
                    if line:
                        try:
                            name, value = line.split(b': ')
                        except ValueError:
                            # https://github.com/giampaolo/psutil/issues/1004
                            continue
                        else:
                            fields[name] = int(value)
            if not fields:
                raise RuntimeError("%s file was empty" % fname)
            try:
                return pio(
                    fields[b'syscr'],  # read syscalls
                    fields[b'syscw'],  # write syscalls
                    fields[b'read_bytes'],  # read bytes
                    fields[b'write_bytes'],  # write bytes
                    fields[b'rchar'],  # read chars
                    fields[b'wchar'],  # write chars
                )
            except KeyError as err:
                raise ValueError(
                    "%r field was not found in %s; found fields are %r"
                    % (err.args[0], fname, fields)
                )

    @wrap_exceptions
    def cpu_times(self):
        values = self._parse_stat_file()
        utime = float(values['utime']) / CLOCK_TICKS
        stime = float(values['stime']) / CLOCK_TICKS
        children_utime = float(values['children_utime']) / CLOCK_TICKS
        children_stime = float(values['children_stime']) / CLOCK_TICKS
        iowait = float(values['blkio_ticks']) / CLOCK_TICKS
        return pcputimes(utime, stime, children_utime, children_stime, iowait)

    @wrap_exceptions
    def cpu_num(self):
        """What CPU the process is on."""
        return int(self._parse_stat_file()['cpu_num'])

    @wrap_exceptions
    def wait(self, timeout=None):
        return _psposix.wait_pid(self.pid, timeout, self._name)

    @wrap_exceptions
    def create_time(self):
        ctime = float(self._parse_stat_file()['create_time'])
        # According to documentation, starttime is in field 21 and the
        # unit is jiffies (clock ticks).
        # We first divide it for clock ticks and then add uptime returning
        # seconds since the epoch.
        # Also use cached value if available.
        bt = BOOT_TIME or boot_time()
        return (ctime / CLOCK_TICKS) + bt

    @wrap_exceptions
    def memory_info(self):
        #  ============================================================
        # | FIELD  | DESCRIPTION                         | AKA  | TOP  |
        #  ============================================================
        # | rss    | resident set size                   |      | RES  |
        # | vms    | total program size                  | size | VIRT |
        # | shared | shared pages (from shared mappings) |      | SHR  |
        # | text   | text ('code')                       | trs  | CODE |
        # | lib    | library (unused in Linux 2.6)       | lrs  |      |
        # | data   | data + stack                        | drs  | DATA |
        # | dirty  | dirty pages (unused in Linux 2.6)   | dt   |      |
        #  ============================================================
        with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f:
            vms, rss, shared, text, lib, data, dirty = (
                int(x) * PAGESIZE for x in f.readline().split()[:7]
            )
        return pmem(rss, vms, shared, text, lib, data, dirty)

    if HAS_PROC_SMAPS_ROLLUP or HAS_PROC_SMAPS:

        def _parse_smaps_rollup(self):
            # /proc/pid/smaps_rollup was added to Linux in 2017. Faster
            # than /proc/pid/smaps. It reports higher PSS than */smaps
            # (from 1k up to 200k higher; tested against all processes).
            # IMPORTANT: /proc/pid/smaps_rollup is weird, because it
            # raises ESRCH / ENOENT for many PIDs, even if they're alive
            # (also as root). In that case we'll use /proc/pid/smaps as
            # fallback, which is slower but has a +50% success rate
            # compared to /proc/pid/smaps_rollup.
            uss = pss = swap = 0
            with open_binary(
                "{}/{}/smaps_rollup".format(self._procfs_path, self.pid)
            ) as f:
                for line in f:
                    if line.startswith(b"Private_"):
                        # Private_Clean, Private_Dirty, Private_Hugetlb
                        uss += int(line.split()[1]) * 1024
                    elif line.startswith(b"Pss:"):
                        pss = int(line.split()[1]) * 1024
                    elif line.startswith(b"Swap:"):
                        swap = int(line.split()[1]) * 1024
            return (uss, pss, swap)

        @wrap_exceptions
        def _parse_smaps(
            self,
            # Gets Private_Clean, Private_Dirty, Private_Hugetlb.
            _private_re=re.compile(br"\nPrivate.*:\s+(\d+)"),
            _pss_re=re.compile(br"\nPss\:\s+(\d+)"),
            _swap_re=re.compile(br"\nSwap\:\s+(\d+)"),
        ):
            # /proc/pid/smaps does not exist on kernels < 2.6.14 or if
            # CONFIG_MMU kernel configuration option is not enabled.

            # Note: using 3 regexes is faster than reading the file
            # line by line.
            # XXX: on Python 3 the 2 regexes are 30% slower than on
            # Python 2 though. Figure out why.
            #
            # You might be tempted to calculate USS by subtracting
            # the "shared" value from the "resident" value in
            # /proc/<pid>/statm. But at least on Linux, statm's "shared"
            # value actually counts pages backed by files, which has
            # little to do with whether the pages are actually shared.
            # /proc/self/smaps on the other hand appears to give us the
            # correct information.
            smaps_data = self._read_smaps_file()
            # Note: smaps file can be empty for certain processes.
            # The code below will not crash though and will result to 0.
            uss = sum(map(int, _private_re.findall(smaps_data))) * 1024
            pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024
            swap = sum(map(int, _swap_re.findall(smaps_data))) * 1024
            return (uss, pss, swap)

        @wrap_exceptions
        def memory_full_info(self):
            if HAS_PROC_SMAPS_ROLLUP:  # faster
                try:
                    uss, pss, swap = self._parse_smaps_rollup()
                except (ProcessLookupError, FileNotFoundError):
                    uss, pss, swap = self._parse_smaps()
            else:
                uss, pss, swap = self._parse_smaps()
            basic_mem = self.memory_info()
            return pfullmem(*basic_mem + (uss, pss, swap))

    else:
        memory_full_info = memory_info

    if HAS_PROC_SMAPS:

        @wrap_exceptions
        def memory_maps(self):
            """Return process's mapped memory regions as a list of named
            tuples. Fields are explained in 'man proc'; here is an updated
            (Apr 2012) version: http://goo.gl/fmebo.

            /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if
            CONFIG_MMU kernel configuration option is not enabled.
            """

            def get_blocks(lines, current_block):
                data = {}
                for line in lines:
                    fields = line.split(None, 5)
                    if not fields[0].endswith(b':'):
                        # new block section
                        yield (current_block.pop(), data)
                        current_block.append(line)
                    else:
                        try:
                            data[fields[0]] = int(fields[1]) * 1024
                        except ValueError:
                            if fields[0].startswith(b'VmFlags:'):
                                # see issue #369
                                continue
                            else:
                                raise ValueError(
                                    "don't know how to interpret line %r"
                                    % line
                                )
                yield (current_block.pop(), data)

            data = self._read_smaps_file()
            # Note: smaps file can be empty for certain processes or for
            # zombies.
            if not data:
                self._raise_if_zombie()
                return []
            lines = data.split(b'\n')
            ls = []
            first_line = lines.pop(0)
            current_block = [first_line]
            for header, data in get_blocks(lines, current_block):
                hfields = header.split(None, 5)
                try:
                    addr, perms, _offset, _dev, _inode, path = hfields
                except ValueError:
                    addr, perms, _offset, _dev, _inode, path = hfields + ['']
                if not path:
                    path = '[anon]'
                else:
                    if PY3:
                        path = decode(path)
                    path = path.strip()
                    if path.endswith(' (deleted)') and not path_exists_strict(
                        path
                    ):
                        path = path[:-10]
                item = (
                    decode(addr),
                    decode(perms),
                    path,
                    data.get(b'Rss:', 0),
                    data.get(b'Size:', 0),
                    data.get(b'Pss:', 0),
                    data.get(b'Shared_Clean:', 0),
                    data.get(b'Shared_Dirty:', 0),
                    data.get(b'Private_Clean:', 0),
                    data.get(b'Private_Dirty:', 0),
                    data.get(b'Referenced:', 0),
                    data.get(b'Anonymous:', 0),
                    data.get(b'Swap:', 0),
                )
                ls.append(item)
            return ls

    @wrap_exceptions
    def cwd(self):
        return readlink("%s/%s/cwd" % (self._procfs_path, self.pid))

    @wrap_exceptions
    def num_ctx_switches(
        self, _ctxsw_re=re.compile(br'ctxt_switches:\t(\d+)')
    ):
        data = self._read_status_file()
        ctxsw = _ctxsw_re.findall(data)
        if not ctxsw:
            raise NotImplementedError(
                "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'"
                "lines were not found in %s/%s/status; the kernel is "
                "probably older than 2.6.23" % (self._procfs_path, self.pid)
            )
        else:
            return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1]))

    @wrap_exceptions
    def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')):
        # Note: on Python 3 using a re is faster than iterating over file
        # line by line. On Python 2 is the exact opposite, and iterating
        # over a file on Python 3 is slower than on Python 2.
        data = self._read_status_file()
        return int(_num_threads_re.findall(data)[0])

    @wrap_exceptions
    def threads(self):
        thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid))
        thread_ids.sort()
        retlist = []
        hit_enoent = False
        for thread_id in thread_ids:
            fname = "%s/%s/task/%s/stat" % (
                self._procfs_path,
                self.pid,
                thread_id,
            )
            try:
                with open_binary(fname) as f:
                    st = f.read().strip()
            except (FileNotFoundError, ProcessLookupError):
                # no such file or directory or no such process;
                # it means thread disappeared on us
                hit_enoent = True
                continue
            # ignore the first two values ("pid (exe)")
            st = st[st.find(b')') + 2 :]
            values = st.split(b' ')
            utime = float(values[11]) / CLOCK_TICKS
            stime = float(values[12]) / CLOCK_TICKS
            ntuple = _common.pthread(int(thread_id), utime, stime)
            retlist.append(ntuple)
        if hit_enoent:
            self._raise_if_not_alive()
        return retlist

    @wrap_exceptions
    def nice_get(self):
        # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f:
        #   data = f.read()
        #   return int(data.split()[18])

        # Use C implementation
        return cext_posix.getpriority(self.pid)

    @wrap_exceptions
    def nice_set(self, value):
        return cext_posix.setpriority(self.pid, value)

    # starting from CentOS 6.
    if HAS_CPU_AFFINITY:

        @wrap_exceptions
        def cpu_affinity_get(self):
            return cext.proc_cpu_affinity_get(self.pid)

        def _get_eligible_cpus(
            self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")
        ):
            # See: https://github.com/giampaolo/psutil/issues/956
            data = self._read_status_file()
            match = _re.findall(data)
            if match:
                return list(range(int(match[0][0]), int(match[0][1]) + 1))
            else:
                return list(range(len(per_cpu_times())))

        @wrap_exceptions
        def cpu_affinity_set(self, cpus):
            try:
                cext.proc_cpu_affinity_set(self.pid, cpus)
            except (OSError, ValueError) as err:
                if isinstance(err, ValueError) or err.errno == errno.EINVAL:
                    eligible_cpus = self._get_eligible_cpus()
                    all_cpus = tuple(range(len(per_cpu_times())))
                    for cpu in cpus:
                        if cpu not in all_cpus:
                            raise ValueError(
                                "invalid CPU number %r; choose between %s"
                                % (cpu, eligible_cpus)
                            )
                        if cpu not in eligible_cpus:
                            raise ValueError(
                                "CPU number %r is not eligible; choose "
                                "between %s" % (cpu, eligible_cpus)
                            )
                raise

    # only starting from kernel 2.6.13
    if HAS_PROC_IO_PRIORITY:

        @wrap_exceptions
        def ionice_get(self):
            ioclass, value = cext.proc_ioprio_get(self.pid)
            if enum is not None:
                ioclass = IOPriority(ioclass)
            return _common.pionice(ioclass, value)

        @wrap_exceptions
        def ionice_set(self, ioclass, value):
            if value is None:
                value = 0
            if value and ioclass in (IOPRIO_CLASS_IDLE, IOPRIO_CLASS_NONE):
                raise ValueError("%r ioclass accepts no value" % ioclass)
            if value < 0 or value > 7:
                msg = "value not in 0-7 range"
                raise ValueError(msg)
            return cext.proc_ioprio_set(self.pid, ioclass, value)

    if prlimit is not None:

        @wrap_exceptions
        def rlimit(self, resource_, limits=None):
            # If pid is 0 prlimit() applies to the calling process and
            # we don't want that. We should never get here though as
            # PID 0 is not supported on Linux.
            if self.pid == 0:
                msg = "can't use prlimit() against PID 0 process"
                raise ValueError(msg)
            try:
                if limits is None:
                    # get
                    return prlimit(self.pid, resource_)
                else:
                    # set
                    if len(limits) != 2:
                        msg = (
                            "second argument must be a (soft, hard) "
                            + "tuple, got %s" % repr(limits)
                        )
                        raise ValueError(msg)
                    prlimit(self.pid, resource_, limits)
            except OSError as err:
                if err.errno == errno.ENOSYS:
                    # I saw this happening on Travis:
                    # https://travis-ci.org/giampaolo/psutil/jobs/51368273
                    self._raise_if_zombie()
                raise

    @wrap_exceptions
    def status(self):
        letter = self._parse_stat_file()['status']
        if PY3:
            letter = letter.decode()
        # XXX is '?' legit? (we're not supposed to return it anyway)
        return PROC_STATUSES.get(letter, '?')

    @wrap_exceptions
    def open_files(self):
        retlist = []
        files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))
        hit_enoent = False
        for fd in files:
            file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd)
            try:
                path = readlink(file)
            except (FileNotFoundError, ProcessLookupError):
                # ENOENT == file which is gone in the meantime
                hit_enoent = True
                continue
            except OSError as err:
                if err.errno == errno.EINVAL:
                    # not a link
                    continue
                if err.errno == errno.ENAMETOOLONG:
                    # file name too long
                    debug(err)
                    continue
                raise
            else:
                # If path is not an absolute there's no way to tell
                # whether it's a regular file or not, so we skip it.
                # A regular file is always supposed to be have an
                # absolute path though.
                if path.startswith('/') and isfile_strict(path):
                    # Get file position and flags.
                    file = "%s/%s/fdinfo/%s" % (
                        self._procfs_path,
                        self.pid,
                        fd,
                    )
                    try:
                        with open_binary(file) as f:
                            pos = int(f.readline().split()[1])
                            flags = int(f.readline().split()[1], 8)
                    except (FileNotFoundError, ProcessLookupError):
                        # fd gone in the meantime; process may
                        # still be alive
                        hit_enoent = True
                    else:
                        mode = file_flags_to_mode(flags)
                        ntuple = popenfile(
                            path, int(fd), int(pos), mode, flags
                        )
                        retlist.append(ntuple)
        if hit_enoent:
            self._raise_if_not_alive()
        return retlist

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        ret = _net_connections.retrieve(kind, self.pid)
        self._raise_if_not_alive()
        return ret

    @wrap_exceptions
    def num_fds(self):
        return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))

    @wrap_exceptions
    def ppid(self):
        return int(self._parse_stat_file()['ppid'])

    @wrap_exceptions
    def uids(self, _uids_re=re.compile(br'Uid:\t(\d+)\t(\d+)\t(\d+)')):
        data = self._read_status_file()
        real, effective, saved = _uids_re.findall(data)[0]
        return _common.puids(int(real), int(effective), int(saved))

    @wrap_exceptions
    def gids(self, _gids_re=re.compile(br'Gid:\t(\d+)\t(\d+)\t(\d+)')):
        data = self._read_status_file()
        real, effective, saved = _gids_re.findall(data)[0]
        return _common.pgids(int(real), int(effective), int(saved))
PKok\�#�!x�x�psutil/_psutil_linux.abi3.sonuȯ��ELF>0$@��@8	@#"     
%
%PPP``�]�m�m���]�m�m��888$$P�td�T�T�T��Q�tdR�td�]�m�mXXGNU!?��CT��Va2���<�Gc�9
�$҈���GHJMOPSTVWX[\�����
U����ȷ��r:�H���$����"ոf�ذ�u
U;hdeG��������w������l��������W�~�_aY�Q���B ������M<V���5f��(���� ����&�H�--�n��6x7N�v�[���8 ��R"z�E�`?�	 ~06W� &�~�u�7��9z��%�+9�n0=&��6iW�<yc6
�&j��@Ha�$���CQ@0<t] 'W��')�@Cd__gmon_start___init_fini_ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizepsutil_PyErr_SetFromOSErrnoWithSyscall__errno_locationstrerrorsprintfPyExc_OSErrorPyObject_CallFunctionPyErr_SetObject_Py_DeallocNoSuchProcessAccessDeniedpsutil_check_pid_rangePyArg_ParseTuple_Py_NoneStructPyExc_ValueErrorPyErr_SetStringpsutil_set_debugPyObject_IsTruePSUTIL_DEBUGpsutil_setupgetenvsocketstrncpyioctlclosePy_BuildValuePyErr_SetFromErrno_Py_TrueStruct_Py_FalseStructsetprioritygetnameinfoPyList_NewgetifaddrsPyList_AppendfreeifaddrsgetpriorityPyUnicode_FromStringpsutil_getpagesizesysconfpsutil_pid_existskillpsutil_raise_for_pidPyExc_RuntimeErrorPyErr_FormatPyInit__psutil_posixPyModule_Create2PyModule_AddIntConstantPyLong_FromLongPyModule_AddObjectPyInit__psutil_linuxpsutil_proc_ioprio_getpsutil_proc_ioprio_setpsutil_proc_cpu_affinity_getpsutil_proc_cpu_affinity_setpsutil_disk_partitionspsutil_userspsutil_net_if_duplex_speedpsutil_linux_sysinfoPyEval_SaveThreadsetmntentPyEval_RestoreThreadgetmntentPyUnicode_DecodeFSDefaultendmntentPyErr_SetFromErrnoWithFilenamestderrfprintffwritefputcsyscall__sched_cpuallocsched_getaffinity__sched_cpufreePyExc_OverflowErrorPyErr_NoMemory__sched_cpucountPySequence_CheckPySequence_SizePyErr_OccurredPySequence_GetItemPyLong_AsLongPyExc_TypeErrorsched_setaffinitysetutentgetutentendutentlibpthread.so.0libc.so.6GLIBC_2.2.5GLIBC_2.7GLIBC_2.3GLIBC_2.3.4GLIBC_2.6� ui	��ii
�ii
�ti	�ii
�ui	��m�$�m�$�m�mHrMR`r�r�r[R�r6�rgR�r�.�rsR�r�*s�Rs/ s�R(s`(@s�RHs�'`s�Rhs@)�s�R�s t t�R@tS`tS�t)S�t?S�tOS�tUSuiS uwS@u�S�o	�o�o�o�o�o!�o#�o%�o.�o4�oL�oA�oD�oE(tYHtShtQ�tH�tN�tV�tXu\(uUHuZp p(p0p8p@pHpPpXp
`phppp
xp�p�p�p�pT�p�p�p�p�p�p�p�p�p�p�p �p"q#q$q&q' q((q)0q*8qW@q+Hq,Pq-Xq/`q0hq1pq2xqJ�qO�q3�q5�q6�q7�q8�q9�q:�q;�q<�q=�q>�q?�q@�qB�qCrDr[rFH��H��OH��t��H����5�O�%�O@�%�Oh����%�Oh�����%�Oh����%�Oh����%�Oh����%�Oh����%�Oh����%�Oh�p����%�Oh�`����%�Oh	�P����%�Oh
�@����%�Oh�0����%�Oh� ����%zOh
�����%rOh�����%jOh���%bOh����%ZOh�����%ROh����%JOh����%BOh����%:Oh����%2Oh����%*Oh�p����%"Oh�`����%Oh�P����%Oh�@����%
Oh�0����%Oh� ����%�Nh�����%�Nh�����%�Nh���%�Nh ����%�Nh!�����%�Nh"����%�Nh#����%�Nh$����%�Nh%����%�Nh&����%�Nh'�p����%�Nh(�`����%�Nh)�P����%�Nh*�@����%�Nh+�0����%�Nh,� ����%zNh-�����%rNh.�����%jNh/���%bNh0����%ZNh1�����%RNh2����%JNh3����%BNh4����%:Nh5����%2Nh6����%*Nh7�p����%"Nh8�`����%Nh9�P����%Nh:�@����%
Nh;�0����%Nh<� ����%�Mh=�����%�Mh>�����%�Mh?��H�=IQH�BQH9�tH�FKH��t	�����H�=QH�5QH)�H��H��?H��H�H�tH�]KH��t��fD���=�Pu/UH�=>KH��tH�=�H�=����h�����P]�����{���f.��AUATI��UH���|���I��8H������L��H�5�*L��H��1�����U1�L��L�%yJH�5�*I�<$����I�<$H��H�����H��tH�mtH��1�]A\A]��H���P���H��1�]A\A]ÐATH��H�5�*1�USH��I��L������1�L��H��IH�5N*H�;�>���H�;H��H������H��tH�mtH��1�[]A\�fDH������H��1�[]A\�f.�ATH��H�54*1�USH��I��L���~���1�L��
H�]IH�5�)H�;���H�;H��H�����H��tH�mtH��1�[]A\�fDH���8���H��1�[]A\�f.�H��H��H�5�-1�H�T$������t"�D$��x*H��HH�H���f.�1�H���f�H��HH�5�)H�8���1���fDH��H��H�5�*1�H�T$�����t2H�|$�����x$H��H���҉H�nHH�H���D1�H���f�H��H�=�(���H��t
H�DH�1�H����UH��1�H�5�*H��@H�T$����A��1�E��tc1Ҿ��:����Ń��tXL�D$H�t$�L�������!��D$H��1��&������t�*����t$ H�=U,1����H��@]�f�����H�dGH�8�l���H��@]�fDUH��1�H�5*H��@H�T$�e���A��1�E��tm1Ҿ�����Ń��thL�D$H�t$�L����������D$H��1��v������t/�z����D$ @tCH�5�FH�=2)1��.���H��@]���K���H��FH�8���H��@]�fDH�5�FH�=�(1����H��@]�DH��H��H�5�*1�H�L$H�T$���A��1�E��t�T$�t$1�������tH�LFH�H���H�FH�8�!�����ff.�@H����AW��AV��AUATUSH����u\����H��E�H��E1�E1�j�H���p���H����H��EH�H��[]A\A]A^A_����u�D�wM��t�I��H��N�,7L��L�%\&D�SH��L��1�H��H���O���I9�u�K�vL��H�=(�D�1�����fDH��H�=�'1��w����h���f�H�EH��@AW1�AVAUATUSH��(�k���H�D$H����H�|$��������fH�l$H�����,���0H��DH�I��I��H��H�uD��M��AUI��L��H�=o%1�����I��XZM����H�|$L��L�$�d���L�$����I�*�NI�,$�VH�+�^I�/�fI�m�nH�mH���wH�}H��t�D�7D�����H;�CI��t�H���=H�} D�����H��H���E�E��
���H�}(D�����I��H��CH�I��M�������E1�H�|$H��t
L�$����L�$H�T$H�H�$H��H��M��t
I�*�BM��tI�,$�RH��t
H�+�cM��t
I�/�tM��tI�m��H�D$H�D$H��([]A\A]A^A_��L����I�,$�����L�����H�+�����H�����I�/�����L����I�m�����L����H�mH��������H�l$H������s���fDH�}(D���\���I��H�rBH�I��M����������DH��L�$�L�L�$M����������f.�L���(����L����M����������f.�L����H����������f.�H�����M����������f.�L��������H�|$E1�E1�1�E1�H����������f�H�|$E1�E1�E1�H��������H�MAE1�E1�1�E1�H�8�J�E1����f�UH��SH�����H�T$H�5�%H���H��1��3�A��1�E��t!�t$1����Ƌ��uH�=�%1��H�H��[]ÐH��@H�8���H��[]�f.�AU1�ATUH��H��@�-�H��t(I��H�T$1�H��H�5_#���uI�,$�`E1�H��@L��]A\A]�1Ҿ���Ń���TH�t$L�D$�L���
�����D$H��1������6�����l$ @����@���>@����@���:@����@�� ��@��@�@�ŀ�Rf����f����f���!f����f����f�� � f��@�Ef�����H�=� ���H��H������H��L���Y��H�E�WH��H�E�����H���7����f�L���(����H�=. ��I��H���m���H��L�����I�E��H��I�E����L��������fDH�=��D�I��H������H��L�����I�EuuH��I�E�����L�����|���f.�H�=4"���I��H������H��L���]��I�Eu%H��I�E�C���L���?��6���f.�H��I�E�����L�����z���DH�=����d����H�=���I�,$���E1��W�H��@L��]A\A]�f.�H�=��4�I��H���
���H��L������I�E�a���H��I�E�����L���{��|���fDH�=����I��H�������H��L���M���I�E����H��I�E�C���L���+��6���fDH�=y��I��H���m���H��L������I�E�����H��I�E�=���L������0���L��������f�H�=�4�I��H���
���H��L������I�E�a���H��I�E���L���{�����fDH�=����I��H�������H��L���M���I�E����H��I�E�����L���+����fDH�=P��I��H���m���H��L������I�E�����H��I�E�����L�������fDH�=��D�I��H������H��L������I�E�q���H��I�E�����L�������fDH�=����I��H������H��L���]���I�E�!���H��I�E�q���L���;��d���fDH�=q��I��H���}���H��L���
���I�E����H��I�E�,���L���������fDH�=)�T�I��H���-���H��L������I�E�����H��I�E���L��������fDH�=���I��H������H��L���m���I�E�1���H��I�E�����L���K����fDH�=���I��H�������H��L������I�E���H��I�E�~���L�����q���H��H�E�M���H������@���ff.���v�fDH����H�=&H��H��1����f���1��f�H��1����A���E��t*�#����t��tH�@9H�8�H��������1�H���f�UH��SH��H��������tH��H��[]�����1���uH��H��[]�/��H��8H��H�5qH�8H��1�[]���AT�H�=;�=�H�����	H�5DH��I���=������H�5/L���!�����1�H�5"L���������H�5L��������l�H�5L��������P�H�5�L�������4�H�5�L��������H�5�L���|������H�5�L���`������H�5�L���D������
H�5�L���(������H�5�L���������
H�5�L�������ut�H�5�L�������u\�H�5wL������uD�H�5mL������u,H��������H��H��tH�5XL�����
�E1�L��A\�f.�DAT�H�=�:�-�H��tp�bH�5�H��I���1���uU1�H�5rL������u@�H�5fL������u(��H�5ZL�������u��L��A\�DE1�L��A\�f.�DAW1�AVAUATUH��SH���x�H���wI��H�T$1�H��H�5������V�i�H�|$H�5+L�5�H����H��I����M����f.�L���X�H��H����H�;���H��H����H�{���I��H���3H�KL�CH��H��L��1���H��H����H��L���4�����H�mt%I�/t-H�+�u���H���
��h����H����I�/u�L�����H�+t�L����H��H���D���L���X��AfDH��4�����H��4H�t$H�8�k�I�,$uL����@E1�H��L��[]A\A]A^A_�L����H�m��I�/tH��t�H�+u�H���D��f�L���8���fDL����H�mu�H�����y���@H�14�#H��1�H�5�H�;��H���H�=����H�3�
�������L���H�����H�����I���fDH��H��H�5H1�H�T$��A��1�E��t3�T$��������t$�‰�H�=e1�����
��H���@H�3H�8�!�H���ff.��H��H��H�51�L�D$H�L$H�T$��A��1�E��t.�L$�T$�����
L$������tH��2H�H����H��2H�8�����AWH��1�H�5HAVA�AUA�@ATUSH��H�T$����u��E�Ic�L�?��M��I��H��I��H�����|$H��L���;��Å���H���	�����8�A��u�H��1H�5GE1�H�8�,�H��L��[]A\A]A^A_�H��I�uL�����H����I�m�/E1��ŐH��1�������I���D1���I��H��twL��H��I����A�ą�u�_f���Hc�L9�s�H��H��H�D�H��s���I��H���i���H��L���'���I��B���H��I�t3��A��u�H���������DH��0H�8���I������L�������H��0�bH��1�H�5�H�;���H���H�=���H�3�
�L����L��������f.�AWH��1�H�5�AVAUATUSH��H�L$H�T$�T�����H�|$������H�|$��I��H����L�l$ ��L���H���1�A��>�I���tb�M�H��uXI���wL��L��D��H��H��I	T�H��I9�tyH�|$H���4�H��H��t&H���$�H�mI��u�H��������H��t`1�H�Ĩ[]A\A]A^A_�f�H�D$H�5�H�PH�!/H�81�����D�|$L�꾀�����u/H�/H��H��.H�5FH�D$H�:�;�H�D$�H��.H�8�����l���AW1�AVAUATUSH���;��I��H���,��f.��[�H��H���f�;u�H�{,��I��H���H�{���I��H�����{L:u.�{M0u(�{Nu"L�CL�H�=�L���������H�=���H��H����f�D�CH��L���*�TL���H�=��I�I��H����H��L����������I�/��I�.tjH�mtCI�,$����L������[�H��H��������c��H��L��[]A\A]A^A_ÐH���x��I�,$�����L���e���L���X���fDL���H���s���L����H��H���	���E1�I�/tYI�.taH��tH�mt_M��tI�,$t*I�mt����E1��^����L��E1���������H���L������I�mu���L������I�.u�L������H������I�/u�L�������H��xH���D���u@�D$hH�=-P1��t$PL�L$PL�D$@H�L$HH�T$8H�t$0���ZYH��x�f�H�,H�8�!��H��x�f.�f�ATH��1�H�5�UE1�H��xH�T$�������1Ҿ��7��Ń����L�D$H�t$�L�����f�F���I��H�D$@D$@H�D$ L��1��D$H�D$`�D$h�D$@D$P�������tF�T$\�D$L�t$N��	¸H�H�=11����I��H��t`�����H��xL��]A\�f��������_t��u/1Ҿ��fDH�=����H��xI��]L��A\�fDH�=������E1��Z��H��xL��]A\�H��H���%s (originated from %s)(is)PSUTIL_DEBUGassume no such process (originated from %s)assume access denied (originated from %s)pid must be a positive integer%02x:(siOOOO)socket(SOCK_DGRAM)ioctl(SIOCGIFFLAGS)upbroadcastloopbackpointopointnotrailersnoarppromiscallmultimasterslavemulticastportselautomediadynamic%s syscall failedRLIMIT_ASRLIMIT_CORERLIMIT_CPURLIMIT_DATARLIMIT_FSIZERLIMIT_MEMLOCKRLIMIT_NOFILERLIMIT_NPROCRLIMIT_RSSRLIMIT_STACKRLIMIT_LOCKSRLIMIT_MSGQUEUERLIMIT_NICERLIMIT_RTPRIORLIMIT_RTTIMERLIMIT_SIGPENDINGRLIM_INFINITY_psutil_posixgetpagesizegetprioritynet_if_addrsnet_if_flagsnet_if_is_runningnet_if_mtusetpriorityversionDUPLEX_HALFDUPLEX_FULLDUPLEX_UNKNOWN_psutil_linuxproc_ioprio_getproc_ioprio_setproc_cpu_affinity_getproc_cpu_affinity_setdisk_partitionsusersnet_if_duplex_speedlinux_sysinfocheck_pid_rangeset_debugpsutil/arch/linux/disk.cpsutil-debug [%s:%d]> setmntent() failed(OOss)iiipsutil/arch/linux/proc.cCPU_ALLOC() failediOinvalid CPU valuecould not allocate a large enough CPU setsequence argument expected, got %R:0.0localhostOOOdi(kkkkkkI)socket()ioctl(SIOCETHTOOL)[ii];�l��<��,���ll�������l�����,���D���p����������$����L���L��\�|�$��<L�|\�����|���,|�H���<����4��dzRx�$`��FJw�?;*3$"<D���B�B�D �G�j
 CBBHO CBB<�h���B�M�A �G�L
 CABGO CAB<�����B�M�A �G�L
 CABGO CAB��jD q
KF
J$X��WD F
FFD���)Dd(\����A�PP{
ACXA0�4���A�PP�
AIX
AGYA����aD H
D`�4��K�D�E �B(�A0�A8�G�\�H�P�Z
8A0A(B BBBI�������X<����B�D�B �B(�A0�A8�D`]hLpXhA`l
8A0A(B BBBH0�D��vA�D�D0S
AABSAA@�����B�D�A �G`y
 DBBA�
 DBBKL��
$H��DP<P��WTB<T���iA�D�G O
DAHO
DALXCA����B�������B��
FHL�8�zB�D�B �B(�A0�D8�DP�
8D0A(B BBBD$h�tD W
ESD��yD \
HH`,�&B�N�H �H(�A0�A8�DP�
8D0A(B BBBAL���B�N�B �B(�A0�A8�G��
8A0A(B BBBCL�P�HB�D�B �B(�A0�A8�D@A
8D0A(B BBBB,LP�dD�X�F�_�A�D
JS@|��QB�M�G��
DBCp
DEGZDB�$�$�m�� 
E�m�m���o`� 
�p �(	���ox���o�o����o�m6 F V f v � � � � � � � � !!&!6!F!V!f!v!�!�!�!�!�!�!�!�!""&"6"F"V"f"v"�"�"�"�"�"�"�"�"##&#6#F#V#f#v#�#�#�#�#�#�#�#�#$$&$MR���������r[R6gR�.sR�*�R/�R`(�R�'�R@)�R�������� t�RSS)S?SOSUSiSwS�SGCC: (GNU) 10.2.1 20210130 (Red Hat 10.2.1-11),�$�,p�'Q,�?9�,�E�9z,6P0<�,�_�@H,[h@Cd,�k�CQl�] �$������XintW�x�W��c�����fvW�zbj}\T�gG�8+:	W;	W�	5j;=l�um@
);�nF��F��R;�R�	
W
g	^�}	�u�
3����,W�R�R�R�*W	R�LR�N3RR:vRPR��lWm���
���W�2
��W�')���'�U	P��R 'W�t}�Rb�,RC=��R�hx�	W��:'�fU�TT	RQ�hH'���R�&j�}�"R��b�2R��pid���l�&��U�TT	�TQ�l'�T	�PP�R &��(��GCexc�R��msg�
(��w ��!m�R��"�!��R
	�&	UvB&P�U��wT	`PQ�Ub&3T	PQ=R��wp&Tv#�9$-�NsR�%��Ls�GCexctR��msgu
(��w `�!mzR��"�!�zR
	&	Uv�%PU��wT	0PQ�U�%37T	PQ3R��w�%Tv%\R�$��\4�IC�]
(��wexcdR�� �!mhR��"0!�hR"�%	Uv%�%m(%P4U��wT	PR|G%3ZT	PR��wV%Tv8A�F �'Qo��9�����Xintc�x�cE
�N��o�������R�N��f�c�zbvG
h�}	T�
NI/�;�h�Y�	R
��	�
�
��
4�	�q�� �
��_
�
 �!L
"�#1$�%�&O'�(�)*,+�,}-�
.�/v0�1�2�3�405|6$7H89L:p;�<,<�=�	>?�@�A�BC3D�E�F�G�H]I�J�K�L/Mk
N�O�PQR#S�T
UFVMW�X�Y7Z�[�\�]�^�_�`�ab�cdCeq	f�g�h%i�
j^k�lm�n�o�p>q	rs�t�uv�wx3yyz�{$|k}~	~K����E������
�����q�<�U	��
�6
�&�����~��	�`����=�K�{�q�����
���:�]
� �����f�����8��
��p�x���	�	�3�$���%
����
������L�'	�����P��4���O���k���^��
�f���U�����h�Y�������������
������0@�1G<3N\T�gG�	8�
+	:	c
	;	cm�5
j�
=
lS
u
m�)��
n�������
�c �
�,2cF��^
�RXcq� �	�
?~����
���& �A1���9 6
�
7�
�8�
]9c
;�9=��(
+U
�
,�
�
-Z
^
.S
�
/
� �U�
0
<�
�
=	c
�
>�Th
J	
�
K`
�
L�(
j
M�0
�

NS8
�
O	@
�
P	H
�
QFP
1
R�X

Sq`l������?N�	�6����Q�	���
8

.8WgfN$�	z�XL)�	�N?
y�
Ik�9

H��G�s

w�?

��
x
K
��
9
K
�
��
�
�
J
�
�
�
|�
�
�
9�
�
�
��)
��?

#�-
z�
h	���
�
.����?
�-G��PG99�'
��������
���\���'���
s
�
&�
1�
<�
G)R�]�h�s�~�����@�9
N+1
d
�3�
- �@g��^`�Q ]@���o�

Oq9
qr9
�sGirqt@dmau@
�v@��
���
��
9�MH�K
b�K
��K

�K
�K
!�\��c�
�c��1
w��
��
���(~u
��	�

&�	�
&��,�
�-�
8
�
!	�
�"N
�$�

X
%�
 
5	.u(
�8	�0�EG{ -
�	"�x;�gA�
g��w=	��/w9;�9G�9���
r�	9�	Gk�#3
F
G
�
�
�c
�G
�@

�@
��gj�P9 �g@	�r y�	 r!�^c��	�"�lc���#"@�c�!	�	�	c$E
�!�Bc!"9c4��"&��K�%L
^�!I4�tS!k(���#"�ac�c!j )c�c9#!�!rc�ccc!t
bc��	�c!*c��#!�
Kc:���!a"�Po!�
Lcp��o!/����c�"�����#!Nc���!d���!�����&�$2
�!#cvc"Uko.c'���7�w(mod��\X(v����)7p�*U	 r*T3)37P�*U|*T	lQ*Q9)O7P�*U|*T	vQ*Q4)h7P*U|*T	�Q*Q0)�7PE*U|*T	�Q*Q2)�7Po*U|*T	�Q*Q1)�7P�*U|*T	�Q*Q8)�7P�*U|*T	�Q*Q7)�7P�*U|*T	�Q*Q6)8P*U|*T	�Q*Q5),8PA*U|*T	�Q*Q3)H8Pk*U|*T	�Q*Q:)d8P�*U|*T	�Q*Q<)�8P�*U|*T	R*Q=)�8P�*U|*T	R*Q>)�8P*U|*T	R*Q?)�8P=*U|*T	-R*Q;)�8:U*U	�+�8*U|*T	?R,��`(��-}�$���-b�4��� �����.��	cRF(ret�	c��/ifr�M�@0��){(�E*U�T*T	�R*Q��)�(�f*U2*T2*Q0)�(8�*U�@*Q?)�(��*Uv*T
�)�(��*Uv)�(t�*U	R1)�1)�+5)t*U	R,�	��/���*-}��-b�/�WM �����.��	c��(ret�	c��/ifr�M��.�����.��\G?0�u2`&.�v���)�0K*U|+3K*U|3�*T0�K54�*		4�*W	S	5�6�*�	�	7�*��6�*


+�5K*Uv8�*�0�6�*/
-
9�*�06�*T
R
+�0K*Uv)`04*U	RQ+w0*U|*Tv:�*�0�0P�:4�*y
w
4�*�
�
6�*�
�
8�*�0�;�*8�*�0!6�*209�*�0!6�*WU+�0K*U})�04*U	�P+�0*U|*T}:�*11P�?4�*|z4�*��6�*��8�*%1�;�*8�*+1%6�*539�*+1%6�*ZX+A1K*U})14$*U	�P+#1*U|*T}:�*P1P1P�D4�*}4�*��6�*��8�*u1�;�*8�*{1%
6�*8
6
9�*{1%6�*]
[
+�1K*U})\14)*U	�S+s1*U|*T}3�*�5ES4�*�
�
4�*�
�
56�*�
�
7�*@�6�*;9+�1K*U}8�*�56�*`^9�*�56�*��+�5K*U})�547*U	HQ+�5*U|*T}:�*22PX4�*��4�*��6�*�8�*52�;�*8�*?2!6�*ca9�*?2!6�*��+U2K*U})24=*U	�P+32*U|*T}:�*`2`2P	] 4�*��4�*��6�*�8�*�2�;�*8�*�2!# 6�*fd9�*�2!6�*��+�2K*U})l24B *U	�P+�2*U|*T}:�*�2�2J3b!4�*��4�*��6�*	8�*�2� ;�*8�*�2(!6�*ig9�*�26�*��+�2K*U})�24G!*U	0Q+�2*U|*T}:�*33P9g"4�*��4�*��6�*8�*53�!;�*8�*?3!-"6�*lj9�*?3!6�*��+U3K*U})34L"*U	6Q+33*U|*T}:�*`3`3P?l#4�*��4�*��6�*8�*�3�";�*8�*�3!2#6�*om9�*�3!6�*��+�3K*U})l34Q#*U	@Q+�3*U|*T}:�*�3�3Pq$4�*��4�*��6�*
8�*�3�#;�*8�*�3!7$6�*rp9�*�3!6�*��+�3K*U})�34V$*U	Q+�3*U|*T}:�*44Pv%4�*��4�*��6�*
8�*%4�$;�*8�*/4!<%6�*us9�*/4!6�*��+E4K*U})44[%*U	�R+#4*U|*T}:�*P4P4P{&4�*��4�*��6�*8�*u4�%;�*8�*4!A&6�*xv9�*4!6�*��+�4K*U})\44`&*U	Q+s4*U|*T}:�*�4�4P!�'4�*��4�*��6�*8�*�4�&;�*8�*�4!F'6�*{y9�*�4!6�*��+�4K*U})�44e'*U	Q+�4*U|*T}:�*�4�4P'�(4�*��4�*��6�*8�*5�';�*8�*5!K(6�*~|9�*5!6�*��+55K*U})�44j(*U	 Q+5*U|*T}:�*@5@5P-�)4�*��4�*��6�*!8�*e5�(;�*8�*o5!P)6�*�9�*o5!6�*��+�5K*U})L54o)*U	)Q+c5*U|*T})/^�)*U0)1/��)*Uv*T	�R*Q��)a/��)*U2*T2*Q0)�/8**U��*Q?)�/�+**Uv*T
�)�/�C**Uv)�1�b**U	�P)�1��**U	�P+�1�*Uv<I	�c+=���=��0�>		��?�*>��	�@>���@>���,����'��~,-}����-b�-� �����.��	cbX(ret�	c��/ifr�M�@0��)�'��+*U�T*T	�R*Q��)�'��+*U2*T2*Q0)(8
,*U�@*Q?)(�,,*Uv*T
!�)&(�D,*Uv)8(tc,*U	�T1E(�1T(�,�*��*���1-}*�
-b*/�NJ B+��(ifa+��.�,	c��.�.�jd.9/���.�	0���.1���.r2�
 �.�3�D!*!A�v/,2P�-.�l	�Y"Q"5P.�l	��"�"+�,K*U��2�3..�m	�%#!#5�.�m	�_#[#+�,K*U|2��..�n	��#�#5�.�n	��#�#+�,K*Us2��..�o	�
$	$5�.�o	�G$C$+-K*U2/.�p	��$}$5.�p	��$�$+"-K*U}2@R/.�y��$�$+�-K*U��2p�/.mz�J%D%5�.�z��%�%1�-K2��/.m{��%�%5.�{� &&+�-K*U|2@50.m|�\&V&5p.�|��&�&+�-K*Us2��0.m}��&�&5�.�}�2'.'+.K*U2�0.m~�l'h'50.�~��'�'+�-K*U})�*^�0*U0)�*�1*U��)M+t81*U	�P*Q~*R|*Xs*Y)l+Z1*U��*T��)�+�1r1*T~)�+�1�1*T~),�1�1*T~1B,�)=-��1*Uv)T-�1�1*T~1v.�B��x2C��(�
C��2cDbuf�
x2Derr�	cE,�	cDn�-Dlen�-E���Dptr��@>k�2��2F9�Bg
���2C}�$�Cb�4�Dpid��E��	cE 	�	cB���3C}�$�Cb�4�Dpid��E��	cGo��6��3H}�(��'�'Hb�8�((16|4I.6t*U	FQJ���6i�R4Kpid�od(V(H�&�))1�6�L�6��3*U�T)�6R44*UsL�6�/4*U�TI�6�*T	ZQ*Q�TM�]c|4Npid]�Dret^	cO�Ho6
��4I
6*UNP�2@)a��54�2�)�)4�20***Q�2�hQ�2�l6�2�*|*R�2�)�)�a54�2�*�*4�2�*�*;�2;�2;�21�)�)_)��5*U�T*T	�S*Q�h*R�l+x)�*U0S�1�)�c6T�1UT
2TQ2��w;"2;.2;:2;D2;P2;\2U�15* �V
2V�15 Q2��w;"2;.2;:2QD2^;P2;\29h25*;i2P�2�.v�p74�2
++4�2M+C+Q3�\63�+�+R�2�.�.�74�2,,4�2;,9,;3;31�.�1�.�)�.�=7*Uv*T	�T*Q�\)�.~T7*U0+�.t*U	�TPR406W�84c4b,^,6o4�,�,RR4i6i6]�74c4�,�,;o41x6�)K6�8*T01]6�Wi_%�r� 9�5�����XintW���c�x�fl�}\T�gG�8�	+:	W	;	W�
�5j	=l�	um)�n�$<0P
0
0�\bWq
0�}�W�
0
j^���W�
0
q
j�?���
j�69 6.	�
7�	�8�	]9W	;�9=��(+|	�,$	�-�	^.�	�/
0 0|�0:<�	�=	W	�>jThJ>	�K�	�L�(	jM�0	�
N�8	�O>@	�PDH	�Q�P	1RPX	
S�`.�g	^�.g-
�W	 t6�	�s�	k0�
0
0�	j0�
0
0�
	0�
0
0�	0�
0
0j	0
0
0w
	05
0
0�0P
0
0M0k
0
0�0�
0
0�0�
0
0	lW�
LW�
0
�
c/�0�
�
W�	B09��modJ0-�,#9�DU	�sT3?9�pU|T	�RQ
bT9��U|T	�RQ0l9��U|T	�RQ1�9��U|T	�RQ��9��
��� �9z���9�����Xintc�3�o"�o��o����0�d��Y	��c	��	�	��	�	a�	�	��	� 
�	�(
�	�0
�	�8
5	�@
~	�H
;	�P
�	�X
�	�`
,�h
�
cp
Act
P
vx
�G�
oU�
���
���
T&��
�/	��
0	��
1	��
�2	��
3
-�
[5c�
�7�������	���	X��	�ca���
9Y��
9���f�����}\T�gG�8;	+:	c	;	c;5jn	=l�	ums)n�nFy\	R�_ts�
���
����m(5	�7�	�8�	9�	5:�	�;	c 	*<	c$�
cgj�jWcJ��G``��Ly�"
9c���k(����4����
�����
�����"dc���))��B�J��t�)*cr��I
4���w��9z��
}"�P-L-b2��-�-~��-�-^`L.@.Q���I��.�.N��/t/9�l0Z0��11+1�Cp�K)�1z1 �9J!:/�"T	.Q#:"Uv��<	��1�1$��<	�22#�:f"UvX�=	�,2(2$�=	�f2b2#�:f"U���>	��2�2$��>	��2�2#�:f"Us@mF�33$��F��3�3!�;f�"Uv#%<f"Uv�TmG��3�3$P�G�X4V4#�;f"U��mH��4{4%~;�H��4�4#�;f"Us&5;��I��4�4#D;f"U|!�9r	"U0!�9V-	"Uv"T	�R"Q��!8:JE	"U} L:� a:�!�:��	"U~"Tv"Q!�:y�	"U|"Ts!�:J�	"U}!;4�	"U} 5;�!h;4�	"U}!�;4
"U}!�;�@
"T	�S"Q	�S"R#!�;�
i
"U	�S"T1"QB!
<�
�
"U:#<4"U}'wm'H>p�
�� 0<���9�����Xintc�3�o"�ox�c��o����0�d��e	��c	��	�	��	�	a�	�	��	� 
�	�(
�	�0
�	�8
5	�@
~	�H
;	�P
�	�X
�	�`
,�h
�
cp
Act
P
vx
�G�
oU�
���
���
T&��
�/	��
0	��
1	��
�2	��
3
-�
[5c�
�7�������	���	X��	�cm���
9e��
9���f����c�zb�}\T�gG�8Y	+:	c	;	c1Y5	j�	=	l	u	m�)��	nd��	���
���
��( 
��;
�����w9�~		���$
9 ��$�
cgj�Nct8 
uc��-�0Y
V�)o���.������
�����	c�L	%�"9c@��a�Vo �cq-�I4���
R����2
�I�
��$7
yc��-�

��"dc�����!-8o9ok(�P��
��f�*c������`?���}�(�55b�8�Y5S5��$��~ len�-�5�5!pid���~ i��5�5"��9636�����~#@	7"h���6�6"��o�6�6#�	�"m�	�P7J7$�	"��	��7�7%N@&Uv#�	�"��	-�7�7'�?�(,@��&Ts(<@�&Uv'U@�%�@�&T	T(�?fk&U�T&T	T&Q��~&R��~'�?�'�?�(�@��&T	PT(�@c�&T�&Q}'�@PMR�0=&�w}R(�8
8bR8�P8J8 cpuS	c�8�8"�Sc(99"" Sc�9�9"�Sc�:�:!pidT��"�U-�:�:"�V�<;.;"�W��;�;)��#	�	"�x
-�<�<#�
"�z�x=n=#@+
"����=�=%>&U~#p]
"��
�>>%�>&U~(�>@{
&Us $ &%�>%&U}&T~#��
"m��L>F>$�"����>�>%Q?&U}(`=f&U�T&T	�T&Q��(='&UA(�=�E&T|&Qv(�=�]&Uv'�=�(�=��&T	 T(>��&Uv'6>�(G>q�&U0(^>V�&U|&Tv(�>��&Uv'�>P(?�:&T	�S&Q	�S&Rb(7?]c&U	�S&T1&QB%D?h&U:�<��<y��
}<"��>�>b<2�?
?!pid=�d"�>	cc?_? >c�hm>c�l" 	?	c�?�?*��<�Fp
+&�?�?+%@#@+K@I@%�<!&U�&T1(�<f�
&U�T&T	�S&Q�d&R�h&X�l''=P�*�0<t��}*"�s@o@b*2��@�@!pid+�l"�,	cA�@" ,cjAbA"m,c�A�A,3T<T</�+P/B-B+DUBSB%g<!&U�&T1(J<f�&U�T&T	�T&Q�l(�<9�&U	�S'�<P-�c3.qc/whoc.�$c-�c].qc/whoc0wm0H>��
��  �@H�!��9��@���Xinth�x�h��t����9��9��f��zb{=�h}�9\T�gG	�8I
+:	h
;	h!I	5j|
=l
um�)|�nT���9�	g 	2�
?!	4a
!	5a
	I�
s 	K
�
7!	L
�� �	:�
� 	<
a
!	=	�
_ 	>�
� 	?�(
� 	@�,
� 	A�L&!	B�L!	H�P� 	M�T� 	S�\V 	T�l��9go�� 
D
.!
>��L��"
9h���k(���4�+�� 
A
I
4�Ij��@H��}�}ByBb(��B�But��B�B��xClC9�D�CJ �E�D� ��E�E� �YFCF�?aA�!$
-z $
-EG?GaA� $
��G�G� $
hKHCHsA�!$*-z $*-�H�H � $*�� $*h!0
�7	�
I	I"0
�7	�GICI#�B�$U!`
j�8	��I}I"`
�8	��I�I#xB�$U~!�
��9	��I�I"�
�9	�/J+J#XB�$Uv!�	�:	�iJeJ"
�:	��J�J% B�$U|#kB�$U|!�
~m@��J�J"�
�@�.K(K%C�h$U#6C�$U!�mA�}KwK"@�A��K�K#C�$U~!pmB�LL"��B�L{L#&C�$Uv!�bmC��L�L" �C�	MM#�B�$U|!P��D�GM?M&�B�%A3�$U0&A+&%A�%@A�$Us,%UA�$Us%�A
$U	xT%�A�>$U	�T$T$Q~$Rv%�A�\$U}$T|&%B�&=B�%�B�$Us�&�B�&�B�GB���! @Cd<'�����XintW���c�v}�fj�}\T�gG�8�+:	W;	W�	�5j=l�um
)�n�"��.�	;S!Bx!c�!-�p	3q!	XY!		3h!	
d �!	d(�!	d0�!	
d8�!	d@�!	dHM!	@Ppad	@R�!	dX_!	d`�!	Lh_f	Cl
dC-
vS-g
^�k
(.w���.�.�W��p�.@Cd�} .�M�Mb0.�M�M#p��LC�U���C`7U	�T�Cw�5�(# �CQ�(��9�����Xintc���o�����fxc�}<3N\T�gG�8
	+:	c	;	c�

5j=	=l�	umB)=�nH�N�
y
�

I

k
�
9

H��	G
��	w
��	�
�
����9
�
����
J

|%%
/9::
D�OO
Y�dd
n'
yy
����
��
��
�\��
�'��
�
��
��
�


*
?
#T
.i
9~
D�
O�
Z�
e�
p�
{�"@�	GS!N'	�	q#(N	�!)N	|#*G�#+�-	%	q#.N	�!/N	|#0G	�#1Nd#2�4	U	�"5G	h"6G;"719	�	�":N	�";N	�#<N	�#=N	�#>Nlmi?Gdce@GI#AaC	�	S"DNo"E�G		S"HN	!#I�)9�"J�L	Y	#MN	�"NN�"O5�
��	O
�9	q
�9	�
�Girq
�@dma
�@	�
�@
�@#
�R#
�$fr
�*�#
�0�#
�6�#
�<te1
�BUY��)�%X#
�}	x
�N	�

�N	_"
��
���
�
�9H
��b
���
��

��
��!
�	\�
�c�

�c�
�ew
�
�
�
v$"
�H�(
�a	�
�}	&
���",aLcmdb�	�#c�	�"d�	"e�	�#f�	�g�	�"h�	�#i�	�"j�	�!k�	�"l�	2"m�	J"n�	�"o�	#p�	�"q� 	|"rQ$a�a9gj��ac�ck(T���2
�j)c�c9�#>v�vc-dT���rc	ccc*c6	T��:T�CQ��}:&T!NNb:6T`NZN�;���~ �<	c�N�N!ret=	cTOPO �#>	c�O�O �#?��O�O "@	c�O�O"ifrA9��X"Ba�� �CTP
P#�t�D$�iD�W_
%�uPsP&�C	�
'U�T'T	�R'Q��~&�C��
'U2'T2'Q|&D��
'U��'Q?&UD��
'Uv'T
F�&�D�
'U	�T&�Dn"'Uv(�D�&�D�N'U	�T&�D�m'U	�T)�Dn'Uv*"#��+�##4�L,i_%$>$>&I:;9II:;9
:;9I8	7I
<4:;9I?<4:;9I?<
4:;9I4G:;9.?:;9'I<I.?:;9'<.?:;9'I<.?:;9'<.?:;9'I<.?:;9'I@�B��1���B.?:;9'I@�B:;9I�B4:;9I4:;9I�B��1��14:;9I U!4:;9I�B"U#I$!I/%.?:;9'I@�B%:;9I$>$>&II7I	:;9I
>I:;9(:;9

:;9I8<'II'4:;9I?<4:;9I?<'I>I:;9>I:;9((I!I/
:;9I8
:;9I8:;9
:;9I4:;9I 4:;9I!.?:;9'I<".?:;9'I<#$.?:;9'<%.?:;9'<&.?:;9'I<'.?:;9'I@�B(4:;9I�B)��1*���B+��1,.:;9'I@�B-:;9I�B.4:;9I�B/4:;9I0
:;91��12U31R�BUXYW41�B5U641�B71U8191:1R�BXYW;41<.:;9'I =:;9I>4:;9I?@A
:;9B.:;9'I C:;9ID4:;9IE4:;9IF!I/G.:;9'I@�BH:;9I�BI���B1J.?:;9'@�BK:;9I�BL���B1M.?:;9'I N:;9IO.?:;9'I@�BP.1@�BQ41R1R�BXYWS.1@�BT1U1R�BUXYWV1W.?<n:;%$>$>&I:;9II:;9	
:;9I8
7I<'I
I:;9I''I4:;9II!I/4:;9I.?:;9'I<.?:;9'I<.?:;9'I@�B4:;9I�B��1���B��1%:;9I$>$>&II:;9	
:;9I8

:;9I8:;9I
!I/7I4:;9I?<<<4:;9I.?:;9'I<I.?:;9'<.?:;9'I<.?:;9'<.?:;9'I<.?:;9'I@�B:;9I�B4:;9I�B4:;9I
:;9U ��1!��1"���B#��1$U%&'.?<n:;%:;9I$>$>&II:;9	
:;9I8

:;9I8:;9I
!I/7I4:;9I?<<4:;9I?<:;94:;9I>I:;9(.?:;9'I<I.?:;9'I<.?:;9'I<.?:;9'<.?:;9'<.?:;9'I@�B:;9I�B4:;9I 4:;9I�B!4:;9I"4:;9I�B#U$U%��1&���B'��1(��1)
:;9*1R�BUXYW+1�B,1R�BXYW-.:;9'I .:;9I/:;9I0.?<n:;%:;9I$>&I$>I!I/I	:;9

:;9I87I<
:;9:;9
:;9I84:;9I.?:;9'<.?:;9'I<.?:;9'<I.?:;9'I<.?:;9'I<.?:;9'I@�B:;9I�B4:;9I�B4:;9I�B
:;94:;9I !U"U#��1$���B%��1&��1%$>$>&I:;9II:;9
:;9I8	7I
<4:;9I?<
:;9I8
I!I/!I74:;9I.?:;9'I<I.?:;9'I@�B:;9I�B4:;9I��1���B��1%:;9I$>$>&II:;9	
:;9I8
7I<>I:;9
(((I!I/:;9
:;9I8:;9
:;9I
:;9I4:;9I.?:;9'I<I.?:;9'I<.?:;9'I<.?:;9'I@�B:;9I�B4:;9I 4:;9I�B!4:;9I�B"4:;9I#
:;9$1R�BUXYW%1�B&��1'���B(��1)��1*.:;9'I +:;9I,.?<n:;k.�
psutil/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6m_psutil_common.ctypes.hstdio.htypes.hpyport.htime.hobject.hpyerrors.h_psutil_common.hstdlib.hmodsupport.habstract.hstring.herrno.h=	�$�=w:	�X:X<���I=�Xt����$n$\$����;=�Xt����#�#\#����;=�Xt����8�8yJ
Ct�L��z�4	�Y2�2J
@t�L	�
M
t��t�.��	K�	Y
���
psutil/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6m/usr/include/netinet/usr/include/net/usr/include/asm-generic/usr/include/linux_psutil_posix.cstddef.htypes.hstdio.htypes.hunistd.hstdint.hpyport.htime.hobject.hboolobject.hmethodobject.hmoduleobject.hpyerrors.hresource.hresource.hsocket_type.hsockaddr.hsocket.hin.hconfname.hif.hifaddrs.hint-ll64.h	types.h
if_packet.h
_psutil_common.hnetdb.hlistobject.hunicodeobject.hmodsupport.hioctl.hsocket.hlongobject.hsignal.herrno.h<built-in>3	�'�3v
J3v�
J�=-[/_fsY�	t.Z]'	Y�X:�t:zP:z�P�=-[/[fsY�	u.[Y	uR�	Y�X	ztPX:�|f:
JAt=-^�ZtKp�	t�:

�:s
.:s.
.:s<

�	Y�8	@	�	-��
^�
^X	#
	Y
Y��	�L
IY	\K�	Y
`�	lt�95`525*�XY�	��XJ
��	;	B	
' 	�
	������%L)J	�J	Z	K�q	?	0	��	=	�<
�
�tK	<�<XX	KXK�X�X�X�X�X��	l����������%L)J7�X�
]�
�tK		<.tXJt�����������z���	A�o;;-	D�v	
<:�~t:�Z�h>�-^�.L�fp.	�f5��5
35)�Y�t��J�=�~�/�fsY��u	X���������������	��~��	�	/Ij��t��	�~@��	�	/Ij���	7���	�	/I2���	=���	�	/I2���	� �����	/	;Z�	�����	�	/Ij���	����	�	/Ij���	��~��	�	/Ij��X��	B��~��	�	/Ij���	��~��	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	��~��	�	/Ij��X	���}�>��>KXuI��L.j�lJt=W	[
X.\dX
&�h�./�/	�X	g	EA 	
�
t	K	G? 	�=	I/ 	X	7�0	�	X�	<�	�	<�	<�	<�	<�	<�	<�	<�	<�	<�	<N	<N	<N	<J	
�	Y����<�J�
psutil/usr/include/bits/usr/include/opt/python/cp36-cp36m/include/python3.6m/usr/include/syspsutil/arch/linux_psutil_linux.ctypes.hstdio.hpyport.htime.hobject.hmethodobject.hmoduleobject.h_psutil_common.hmem.hnet.husers.hdisk.hproc.hmodsupport.h	9�0	_ 	XK	K	<K	<LZX	nf<��
psutil/arch/linux/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/opt/python/cp36-cp36m/include/python3.6m/usr/include/syspsutil/arch/linux/../..disk.cstddef.htypes.hstdio.hlibio.hpyport.htime.hobject.hpystate.hpyerrors.hmntent.h_psutil_common.hlistobject.hmodsupport.hunicodeobject.hceval.h<built-in>8	�98y58y.�Z�
t��Y�lt=Y;=X	.j�	��	=	��	=	�.X	A	�
�	�tf�J�f�fj���	b�=t�=yJ	��fXf��	�t��	\$�!.	�X����
psutil/arch/linux/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6mpsutil/arch/linux/../..proc.cstddef.htypes.hstdio.hlibio.htypes.hpyport.htime.hobject.hpyerrors.hsched.h_psutil_common.hsched.hlongobject.habstract.hlistobject.herrno.hunistd.hmodsupport.h<built-in>8	0<)8J?t�=-Zg.Z
-0�
e>Y	�t�88
JAtX>,\U)WJ)�<WJX+ZtK	�t>
>y
_>y�
{�	�o<	uWu;	K	�
�.	��
X	�
g�
:�#q ��	��
Sft��t�[
hJX='.�1'<	
<X"!X
@
��/;
j�.r1'<J.	��
[ 
f�^$�, >m>y
_>y�
���
�����ff	.�zfX	]�JpJ	Y	�	\	�T	@.�.
XXb+.	X<"(	Nu�.�	���
psutil/arch/linux/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6mpsutil/arch/linux/../..users.cstddef.htypes.hstdio.htypes.hpyport.htime.hobject.hutmp.hlistobject.hmodsupport.hunicodeobject.hutmp.h_psutil_common.h.	�@.0.,�X=�Y	 �`�	�	h3JX	=	�.JX	=	�
ff*fJ<'.
�	�	��	�	�
�	��ft��`�"�Y
	r.�����
p�	=u�#<ffXtXttY<d>:XYU���f��f��o�
psutil/arch/linux/usr/include/bits/usr/include/opt/python/cp36-cp36m/include/python3.6m/usr/include/sys/usr/include/asm-generic/usr/include/linuxpsutil/arch/linux/../..mem.ctypes.hstdio.hpyport.htime.hobject.hint-ll64.hposix_types.hsysinfo.hmodsupport.hpyerrors.hsysinfo.h_psutil_common.h6	@C
6	M�M
2	t��i?�
psutil/arch/linux/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/opt/python/cp36-cp36m/include/python3.6m/usr/include/sys/usr/include/asm-generic/usr/include/linux/hdlc/usr/include/linuxpsutil/arch/linux/../..net.cstddef.htypes.hstdio.hstdint.hpyport.htime.hobject.hsockaddr.hsocket.hint-ll64.hioctl.hif.h	ethtool.h	unistd.hmodsupport.hioctl.hstring.h_psutil_common.h
socket.hsocket_type.herrno.h<built-in><	�C9<uX<u� <t<J��/�iMzt<�YzX[�[Z	YS)XX-	[L	1O���=Zu	h�X.�-	e�.�RJ.< 
q��	/	;Y�tz_dsttimesyscallpsutil_setup/project_typeobject_objectob_refcntdoubleNoSuchProcessPy_ssize_tfloat_py_xdecref_tmplong long unsigned inttimezoneunsigned charpsutil_set_debugstrerror_py_decref_tmpPSUTIL_DEBUGshort unsigned intPyObject_IsTruepsutil_PyErr_SetFromOSErrnoWithSyscalltz_minuteswestPyObject_CallFunctionAccessDeniedpsutil/_psutil_common.cob_typeselfPyErr_SetObject__errno_locationPyObject__ssize_tfullmsglong long intGNU C17 10.2.1 20210130 (Red Hat 10.2.1-11) -mtune=generic -march=x86-64 -g -O3 -fwrapv -fPICPyArg_ParseTuplePyExc_ValueError_Py_Deallocshort intargsPSUTIL_CONN_NONE__pid_t_Py_NoneStructpsutil_check_pid_rangePyErr_SetStringsprintfgetenvPyExc_OSError_SC_EQUIV_CLASS_MAXifr_ifrnm_copyifa_addr_SC_THREAD_PRIO_PROTECTsin6_flowinfoifr_ifruPyModule_Create2getnameinfo__priority_which_t_SC_VERSIONPy_BuildValue_SC_NL_NMAXm_methods_longobjectslot_SC_SYNCHRONIZED_IO_SC_THREAD_PRIORITY_SCHEDULING_SC_NPROCESSORS_ONLNsa_datam_base_SC_TIMEOUTSsockaddr_SC_BASE_SC_PII_OSI_COTSsockaddr_un_SC_THREAD_SAFE_FUNCTIONS_SC_ATEXIT_MAXsockaddr_ns_SC_STREAM_MAXifru_slavepsutil_posix_getpriority_SC_PRIORITIZED_IOpy_ptp_SC_V6_ILP32_OFF32_SC_THREAD_SPORADIC_SERVERsll_pkttype__socket_typeifu_dstaddr_SC_SHRT_MIN_SC_USHRT_MAX_SC_NL_TEXTMAX_SC_STREAMS__rlimit_resourceIFF_PORTSEL_SC_THREAD_DESTRUCTOR_ITERATIONS_SC_PIPE_SC_BC_DIM_MAXpsutil_getpagesize_SC_MAPPED_FILES_SC_2_C_BIND_SC_MQ_OPEN_MAX_SC_XOPEN_SHM_SC_INT_MAX_SC_2_FORT_DEVkill_SC_XOPEN_XPG2_SC_NZERO_SC_XOPEN_XPG4IFF_NOTRAILERS_SC_CPUTIME_SC_PII_INTERNET_SC_V7_LP64_OFF64_SC_LEVEL3_CACHE_SIZE_SC_MB_LEN_MAXifreq__u6_addr16__caddr_t_py_tmpsockaddr_ipxsll_hatypegetifaddrsifru_broadaddr_SC_REALTIME_SIGNALS__RLIMIT_LOCKSm_freemoduledefpy_netmask_SC_DEVICE_SPECIFIC_Ruint32_tin_addr_tmem_start_SC_SAVED_IDS__RLIM_NLIMITS_SC_2_C_DEV_SC_XBS5_LPBIG_OFFBIGob_base_SC_2_C_VERSION_SC_SEM_VALUE_MAX_SC_SCHAR_MAXifru_map_SC_SSIZE_MAX_SC_2_UPEPyExc_RuntimeErrorfreeifaddrsRLIMIT_COREifa_name_SC_INT_MIN_SC_BC_BASE_MAX__u6_addr8_SC_POLLsysconfml_flags_SC_SYSTEM_DATABASE_Rsockaddr_dlsll_halen__RLIMIT_NPROC_SC_2_LOCALEDEFIFF_MULTICASTsin_family_SC_XOPEN_XPG3_SC_T_IOV_MAX_SC_LEVEL1_ICACHE_ASSOCin_port_tpy_str_SC_SYMLOOP_MAXretval_SC_TRACE_LOGifa_ifu__u6_addr32append_flag_SC_THREAD_CPUTIMEsin_zero_SC_CHAR_MAX_SC_XBS5_ILP32_OFFBIG_SC_PII_INTERNET_DGRAMs_addrpy_address_SC_2_PBS_TRACK__u16psutil_net_if_flags_SC_FILE_ATTRIBUTES_SC_ASYNCHRONOUS_IO_SC_FSYNC__RLIMIT_NICEsockaddr_inarp_SC_DEVICE_SPECIFICsockaddr_ax25ifa_netmaskIFF_UP_SC_THREAD_ATTR_STACKSIZE_SC_REGEX_VERSION_SC_MEMLOCK_SC_DELAYTIMER_MAX_SC_LONG_BIT_SC_SEM_NSEMS_MAXsockaddr_isoPyModule_AddObjectPyModule_AddIntConstant_SC_XOPEN_STREAMS_SC_LEVEL1_ICACHE_LINESIZE_SC_SIGNALSsll_family__RLIMIT_OFILEIFF_SLAVEioctl_SC_2_PBS_ACCOUNTING_SC_AIO_MAX_SC_LEVEL2_CACHE_LINESIZE_SC_XOPEN_VERSIONmod_methodssa_family_t_SC_CLK_TCK_SC_SHELLsll_protocol_SC_UIO_MAXIOV_SC_TZNAME_MAXifru_data_SC_SPORADIC_SERVER_SC_MEMLOCK_RANGE_SC_AVPHYS_PAGES__RLIMIT_NLIMITS_SC_V7_ILP32_OFFBIG_SC_PII_XTIclosesll_ifindexflag_namesock_SC_V7_LPBIG_OFFBIG_SC_C_LANG_SUPPORT_RSOCK_DCCP_SC_LEVEL3_CACHE_ASSOCuint8_t_SC_FILE_SYSTEMifru_netmask_SC_PAGESIZE_SC_V6_ILP32_OFFBIGSOCK_PACKET__id_t_SC_SIGQUEUE_MAX_SC_SPAWNpsutil_posix_setpriority_SC_DEVICE_IO_SC_V6_LPBIG_OFFBIG_SC_2_VERSIONifru_mtu_SC_LEVEL4_CACHE_SIZEml_nameSOCK_DGRAMm_sizeIFF_LOOPBACK_SC_USER_GROUPS_RPyModuleDef_Slotvisitprocsin_port_SC_LINE_MAXsockaddr_eonpsutil/_psutil_posix.cIFF_AUTOMEDIAlladdrpy_broadcast_SC_LEVEL1_DCACHE_ASSOC_SC_HOST_NAME_MAX_SC_C_LANG_SUPPORT__RLIMIT_RSS_SC_THREAD_STACK_MINIFF_RUNNING_SC_SEMAPHORES_SC_UINT_MAX_SC_CHILD_MAX__RLIMIT_MSGQUEUEPyUnicode_FromString_SC_NGROUPS_MAX_SC_SINGLE_PROCESSIFF_ALLMULTI__be16__in6_usin_addr_SC_TTY_NAME_MAX_SC_PII_INTERNET_STREAMRLIMIT_AS_SC_MEMORY_PROTECTIONPyModuleDef_Basem_name_SC_XOPEN_CRYPTPyCFunctionpsutil_net_if_is_runningifru_newname_Py_FalseStructRLIMIT_FSIZE_SC_CHAR_BIT_SC_LEVEL1_DCACHE_SIZEIFF_NOARP_SC_CLOCK_SELECTIONm_initifrn_namesin6_addrpsutil_net_if_mtu_SC_TIMERSfreefunc_SC_BC_SCALE_MAX_SC_ULONG_MAXuint16_tsin6_port_SC_MQ_PRIO_MAX_SC_TRACE_SC_SPIN_LOCKSifru_flagsaddrlen_SC_LEVEL1_DCACHE_LINESIZE_SC_BC_STRING_MAXPyLong_FromLongmem_endSOCK_STREAMRLIMIT_DATA_SC_V7_ILP32_OFF32_SC_TRACE_SYS_MAX_SC_FD_MGMT_SC_REGEXPsin6_familyIFF_PROMISCRLIMIT_CPUPyInit__psutil_posix_SC_LEVEL1_ICACHE_SIZE_SC_ADVISORY_INFO__RLIMIT_RTPRIO_SC_SHRT_MAX_SC_XBS5_LP64_OFF64__builtin_strncpy_SC_READER_WRITER_LOCKS_SC_SYSTEM_DATABASE_SC_XOPEN_REALTIME_THREADS_SC_THREAD_ROBUST_PRIO_PROTECT_SC_2_CHAR_TERM_SC_PASS_MAX_SC_FIFOm_slots_SC_ARG_MAXifru_hwaddrml_doc_SC_2_PBS_CHECKPOINTPyMethodDef_SC_XOPEN_REALTIMEPRIO_USERifru_dstaddrpsutil_getpagesize_pywrapper_SC_2_FORT_RUNsocket_SC_TRACE_EVENT_FILTERpsutil_raise_for_pid_SC_RE_DUP_MAX_SC_SCHAR_MINsockaddr_in_SC_THREAD_ROBUST_PRIO_INHERIT_SC_THREADSPyList_Append_SC_PII__RLIMIT_SIGPENDING_SC_TRACE_INHERIT_SC_WORD_BIT_SC_XBS5_ILP32_OFF32_SC_PII_OSI_MRLIMIT_NOFILEm_traverse_SC_2_SW_DEV_SC_OPEN_MAX_SC_XOPEN_UNIXsockaddr_in6_SC_AIO_LISTIO_MAXPyErr_SetFromErrno_SC_PII_OSI_SC_UCHAR_MAX_SC_MONOTONIC_CLOCKm_clearpy_tupleifaddrSOCK_RAW_SC_PRIORITY_SCHEDULINGm_doc_SC_SELECT_SC_NETWORKING_SC_TIMER_MAX_SC_TRACE_EVENT_NAME_MAX_SC_V6_LP64_OFF64_SC_GETGR_R_SIZE_MAX_SC_LEVEL2_CACHE_SIZE_SC_LOGIN_NAME_MAX_SC_EXPR_NEST_MAXIFF_POINTOPOINT_SC_NPROCESSORS_CONF__RLIMIT_RTTIMEifru_addr__socklen_ttraverseprocSOCK_SEQPACKETPRIO_PROCESSsockaddr_atpsutil_pid_existsifa_flags_SC_SS_REPL_MAX_SC_RAW_SOCKETS_SC_BARRIERS_SC_CHAR_MIN_SC_LEVEL4_CACHE_LINESIZEpsutil_convert_ipaddr_SC_THREAD_PROCESS_SHARED_SC_NL_MSGMAX_Py_TrueStructsin6_scope_idm_index_SC_LEVEL4_CACHE_ASSOC_SC_CHARCLASS_NAME_MAX_SC_PII_OSI_CLTSpsutil_net_if_addrspy_retlist_SC_TYPED_MEMORY_OBJECTSml_meth__RLIMIT_MEMLOCKbase_addr_SC_2_PBS_SC_PHYS_PAGESIFF_MASTER_SC_PII_SOCKETIFF_DEBUG_SC_MULTI_PROCESS_SC_LEVEL2_CACHE_ASSOC__priority_whichsa_familyifmap_SC_THREAD_KEYS_MAXPyErr_FormatIFF_BROADCAST_SC_THREAD_THREADS_MAX_SC_GETPW_R_SIZE_MAXifa_dataSOCK_NONBLOCKPRIO_PGRP_SC_2_PBS_MESSAGE_SC_RTSIG_MAXsockaddr_ll_SC_THREAD_ATTR_STACKADDRPyList_NewPyModuleDef_SC_FILE_LOCKING_SC_SHARED_MEMORY_OBJECTS_SC_TRACE_NAME_MAX_SC_COLL_WEIGHTS_MAX_SC_XOPEN_ENH_I18N_SC_XOPEN_LEGACY_SC_JOB_CONTROLIFF_DYNAMICifa_nextRLIMIT_STACK_SC_MESSAGE_PASSING_SC_NL_LANGMAX_SC_IOV_MAX_SC_USER_GROUPSSOCK_CLOEXEC_SC_IPV6_SC_LEVEL3_CACHE_LINESIZE_SC_2_PBS_LOCATEifru_ivalue_SC_NL_SETMAX_SC_NL_ARGMAXifu_broadaddrnic_name_SC_THREAD_PRIO_INHERITsll_addr_SC_TRACE_USER_EVENT_MAXinquirysockaddr_x25SOCK_RDM_SC_AIO_PRIO_DELTA_MAX_SC_XOPEN_XCU_VERSIONpsutil_proc_cpu_affinity_getpsutil_userspsutil_disk_partitionspsutil_proc_ioprio_setpsutil_net_if_duplex_speedpsutil_linux_sysinfopsutil_proc_ioprio_getpsutil_proc_cpu_affinity_setPyInit__psutil_linuxpsutil/_psutil_linux.c_IO_buf_end_flags2py_dev_old_offsetPyThreadStateendmntentPyEval_SaveThread_IO_save_end_IO_write_endmnt_dir_IO_write_ptr_IO_buf_base_markers_IO_read_endstderrsetmntent_lock_cur_columnmnt_fsnamePyEval_RestoreThread_posfprintfmnt_passnomnt_opts__builtin_fputcpy_mountp_sbufentry_IO_FILE__builtin_fwritefile__pad4_IO_marker_shortbuf_IO_write_base_unused2_IO_read_ptrPyUnicode_DecodeFSDefaultPyErr_SetFromErrnoWithFilename__pad1__pad2__pad3__pad5mnt_type__off64_t_chain__off_t_IO_backup_base_savemtab_path_mode_IO_read_base_vtable_offset_IO_save_base_filenopsutil/arch/linux/disk.c_IO_lock_tgetmntentmnt_freqPySequence_GetItemncpuscpucount_s__bitsPyExc_OverflowErrorPyErr_NoMemoryPySequence_SizePyLong_AsLongsched_getaffinity__sched_cpufreePyErr_OccurreditemiodataIOPRIO_WHO_PROCESSpy_listcpu_numsetsizepy_cpu_setseq_len__cpu_maskioprio__sched_cpuallocPySequence_Check__cpupsutil/arch/linux/proc.ccpu_set_tioclass__sched_cpucountPyExc_TypeErrorsched_setaffinitypy_username__unusedut_lineexit_statustv_sec__s2_lenpsutil/arch/linux/users.c__s1ut_idut_hostut_addr_v6ut_typesetutentut_userpy_hostname__resultut_tvendutentutmppy_ttye_exitut_sessionut_pid__s1_lenut_exitgetutenttv_usece_terminationprocs__u32loadsfreehightotalramuptime__kernel_long_tbufferramsharedramtotalhighfreeswap__kernel_ulong_ttotalswapmem_unitfreerampsutil/arch/linux/mem.cclock_typemdio_supportpsutil_ethtool_cmd_speedifru_settingsmaxrxpktraw_hdlc_protospeed_hidlciethcmdifs_ifsuparityfr_proto_pvcreservedautonegmaxtxpkt__u8timeoutphy_addresst391t392cisco_protoethtool_cmdlp_advertisingencodingeth_tp_mdixfr_proto_pvc_infoeth_tp_mdix_ctrlintervalmasterpsutil/arch/linux/net.craw_hdlcfr_protociscoif_settingste1_settingsclock_rateloopbackecmdsupportedn391n392n393slot_mapsync_serial_settingsfr_pvc_infotransceiverduplexmemsetfr_pvcuint_speedsync07U7��U�0>T>IUI��T�XcP��U�*�U���T��U�*�T�0QUQ��U�xP�V��V��V��V��V��V��U�&�U���P�V
#V�V
#V��V
#VUG\G��U�^ePe|V��Vf|V��VkrV��Vc�P�A\+>P��U���U���T��U���T���	���PBVHTUTiVj�V%PHTPPTUTE�U�PbTb�V���T���V�E�T�P�	����P��V�
	��

P
Q
VV
J	��JWVWE	����P!
3
PcrPr�\�D
\V
E\��V�
VV
JVW*V��\��\4
D
\JW\��
RQ�*@
RQ���\*@\��0���P��V��0�*@V*EV��V��V�E	
�P��E	\�	0�	"	P"	/	]/	E	0�/	J	]/	J	]J	�	
�P�J	�	\J	_	0�_	r	Pr	{	]{	�	0�{	�	]{	�	]�	�	
�S��	�	\�	�	0��	�	P�	�	]�	�	0��	�	]�	�	]�
%
HQ��
%\�
�
0��
P]%0��	
]*]*]V
�

�P�V
�
\V
o
0�o
�
P�
�
]�
�
0��
�
]�
�
]�
�

�P��
�
\�
�
0��
�
P�
�
]�
�
0��
�
]�
�
]�
E
0Q��
E\�
0�"P"/]/E0�/J]/J]W�
6Q�W�\Wo0�o�P��]��0���]��]��
@Q���\��0���P��]��0���]��]�E
Q��E\�0�"P"/]/E0�/J]/J]J�
�R�J�\J_0�_rPr]�0��]�]��
Q���\��0���P��]��0���]��]�5

Q��5
\��0��
P

]
5
0�
:
]
:
]:
�

 Q�:
�
\:
O
0�O
b
Pb
o
]o
�
0�o
�
]o
�
]�
�

)Q��
�
\�
�
0��
�
P�
�
]�
�
0��
�
]�
�
]U��U�
T
U��T�8	��8SPS�V��U��VjuP��PU��U�$T$��T�KV�V��Vm�VY�^^^��^m�^*<P<�����*�0���P��Z�����0��Z�����0�m�0���S��0���Z��0�*Y0�Y�\��0�(>P>�\(\(0��m\m�P��\��0�*Y0�Y�S�B0�BNPN�S;S;�0��mSm�0���S��P��0�*s0�y�_�e0�elPl|_�_M_M�0��m_m�0���S��0���Z��0�*s0�y�]�p0��]_]_�0���P�m]m�0���S��0���Z��0���Z����'Z'����Z����'Z'����\(\		��\(\��S;S	��S;S��_M_		��_M_��]_]		��]_]������Q�m����Z��Z�Z��Z�Z��\��\m\��\6\��S��S(mS��S6VS��_��_Hm_��_Vm_��]��]��]��]`hUh~�U�`hTh~�T���U��S��U�S!�U�!CSCI�U���T�VU�T�V U !�T�!DVDHQHI�T���U���U���T��U���T���P��P���U����T���U�F�U���T�.V./�T�/EVEF�T�P'T/>T/?�U�/?V��U���U���P��X���U�.P.�\��PUz�U�T]V]z�T�h0�hlPl�]�z]��P��SGWPWZS�S_mS�0���P��V��0��Vm0�mzV�0���P��Q��_�0�(_(�0���_�m0�mz_�0���P�S0�6S6�0���S�m0�mzS+P+�\�z\]aPavVZ�V_V�PV�PV�_(P_		�_(P_S6GS		S6GS��0���V�Vhm0�mzV��V�VmzV	��0���_0�hm0�uz_��_��0���Shm0���S��\05U5��U�0>T>[U[��T�c���������0��*S��S��P�*\c�\��V�P*V��V��_P*_��_��V*V��V��V*V��V��_U&�U�T/U/&�T���S170�7�S��S&S9�]��A��	]	A�])A���]��A��]��\17P7�\��|���\��\&\17P9C\]�\�1\��\�\90�9CV]tPt�V��V��P�&V�0���]�0�-P-�]��0���]�0�&]��	s $ &�7CUFaUa�	s $ &���	s $ &���	s $ &�&	s $ &���^exPx�^��^&^��^��^��^��]��0�&]��]&]��U���U���T��U���T����h�=$�l�!���R��P��P���h�=$�l�!���R���d��1�Ut�U�TUt�T�7IPIOQORT\gP<Ip=&�IOq=&�ORt=&�RVT<Ip
��IOq
��OVQ$6�l$71�UH�U�TH�T�8OPO8S8LPLMS_HS%P%M]_�]��]��UH]�0���P�\M0�_h\h}0�}�\��0���\\8F0�S0�SdPd_M0�_�0��H_h0�h�P�^M0�_�0���^^8F0��0���P�VM0�_}0�}�V��0���P��VV8F0�qA2�_�2�82�q�s����X�8s��_�s����X��s��8s��qws���:�w}s���0�}�	s������	s������4���4�A__�_A__�_A^_�^	A^_�^AV_}V	AV_}VA\h}\		A\h}\��__8F_��_8_8H_��^.^FF0���^^8^
��VV.8VFH0���V.8V��\\FH0���\\��]��]��U
]Ud�U�Td�T�UQ�U�TUQ�T�;0�;ZPZ�V�
V
P$V*NV��P��P��T���L�
��@$���
��!���Q
�0���P��\�<0������fr��kr��������������[f���� (��(;��;M��M_��_r������������(�� (��(H��@H��Hp��`p���������	4
?
JR��*E��*E�	
�
*�	
	BSZm�� 6<�� (�(6�����hhmu���mu������hhuz��������hm��������]�����{~��������&��&%)C]���*�������� 000h�����`h��8F��.FF��.��.8FF��.8��
FH��
������
������8` ��x� 	 
  0$E
P�T�U�m�m�m�m�op r�u�0$`$!�$7�uC�mj�$v�m������'��`(��@)a��)�*�$�.v=/�Q6n rhx�r��n�shx t`������������\[���m��m��T��u�p#.?Vn��� ���9�.>Z0=&w`?��E��CQ��7���'6
:M`s������0<t'<La p��������6i��<y�$�;Qh�����06W��9z	�%�3BYo 'W����� &����u�@H%DQfz ����&j�"�	 	�')	#	@Cd8	crtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.0__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entry_psutil_common.c_psutil_posix.cpsutil_net_if_mtupsutil_net_if_is_runningpsutil_posix_setprioritypsutil_convert_ipaddrpsutil_net_if_addrspsutil_posix_getprioritypsutil_net_if_flagspsutil_getpagesize_pywrappermoduledefmod_methods_psutil_linux.cdisk.cproc.cusers.cmem.cnet.c__FRAME_END____dso_handle_DYNAMIC__GNU_EH_FRAME_HDR__TMC_END___GLOBAL_OFFSET_TABLE_getenv@@GLIBC_2.2.5PyList_NewPySequence_Checkendmntent@@GLIBC_2.2.5PyModule_AddIntConstant__errno_location@@GLIBC_2.2.5strncpy@@GLIBC_2.2.5getpriority@@GLIBC_2.2.5_ITM_deregisterTMCloneTablePyEval_RestoreThreadPyErr_SetFromErrnoPyInit__psutil_linux_Py_DeallocPyErr_NoMemoryPyErr_SetObject__sched_cpucount@@GLIBC_2.6psutil_proc_cpu_affinity_getpsutil_proc_cpu_affinity_set_finipsutil_net_if_duplex_speedPyExc_RuntimeErrorPyInit__psutil_posixPyErr_SetStringPyExc_ValueErrorPyExc_TypeErrorsetpriority@@GLIBC_2.2.5psutil_getpagesizeioctl@@GLIBC_2.2.5close@@GLIBC_2.2.5PySequence_GetItemgetnameinfo@@GLIBC_2.2.5sched_setaffinity@@GLIBC_2.3.4fputc@@GLIBC_2.2.5endutent@@GLIBC_2.2.5PyLong_FromLongPySequence_Sizepsutil_proc_ioprio_getPyList_AppendPyExc_OSErrorfprintf@@GLIBC_2.2.5_Py_FalseStructsyscall@@GLIBC_2.2.5__gmon_start__PyObject_CallFunctionPyExc_OverflowErrorPy_BuildValuekill@@GLIBC_2.2.5PyErr_OccurredPyModule_Create2PyLong_AsLongpsutil_raise_for_pidpsutil_proc_ioprio_setpsutil_PyErr_SetFromOSErrnoWithSyscallgetutent@@GLIBC_2.2.5getmntent@@GLIBC_2.2.5setmntent@@GLIBC_2.2.5_Py_NoneStructgetifaddrs@@GLIBC_2.3__sched_cpufree@@GLIBC_2.7PyObject_IsTruePyArg_ParseTuplepsutil_pid_existspsutil_disk_partitionsNoSuchProcess__sched_cpualloc@@GLIBC_2.7_Py_TrueStructfreeifaddrs@@GLIBC_2.3setutent@@GLIBC_2.2.5psutil_set_debugPyUnicode_DecodeFSDefaultPyUnicode_FromStringPyEval_SaveThreadPyModule_AddObjectAccessDeniedsysconf@@GLIBC_2.2.5PSUTIL_DEBUGpsutil_userssysinfo@@GLIBC_2.2.5PyErr_SetFromErrnoWithFilenamePyErr_Formatsprintf@@GLIBC_2.2.5fwrite@@GLIBC_2.2.5_ITM_registerTMCloneTablesched_getaffinity@@GLIBC_2.3.4strerror@@GLIBC_2.2.5psutil_check_pid_range__cxa_finalize@@GLIBC_2.2.5_initpsutil_setupstderr@@GLIBC_2.2.5psutil_linux_sysinfosocket@@GLIBC_2.2.5.symtab.strtab.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str.debug_loc.debug_ranges88$.���o``�8  �@���H���o���U���oxx�d��(nB  x  s    ~0$0$� �EE	�2PP���T�T���U�U���m�]��m�]��m�]��m�]���o�_p�p`� r b` ��u�e�0�e/��e�	/gSw���#9�c,/0��#:�B�PE5���!D	�L	d�SPKok\��G��r�r,psutil/__pycache__/_pswindows.cpython-39.pycnu�[���a

��?h��@s�dZddlZddlZddlZddlZddlZddlZddlZddlm	Z	ddl
mZddlmZddlm
Z
ddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%zddl
mZ&Wnle'�y�Z(zRe)e(��*��+d��r�e�,�dd k�r�d!Z-e-d"7Z-e-d#7Z-e.e-��n�WYdZ([(n
dZ([(00e�rddl/Z/ndZ/gd$�Z0d%Z1d&Z2d'ej3vZ4e/du�r0d(Z5ne/�6d)d*d(i�Z7e7j5Z5e&j8ej9e&j:ej;e&j<ej=e&j>ej?e&j@ejAe&jBejCe&jDejEe&jFejGe&jHejIe&jJejKe&jLejMe&jNe1e&jOejPi
ZQe/du�r�Gd+d,�d,e/j6�ZReS��TeRjU�e/du�r�dZVdZWd-ZXd.ZYn Gd/d0�d0e/j6�ZZeS��TeZjU�e[ddd-d.d1d2d d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdB�Z\e	dCgdD��Z]e	dEgdF��Z^e	dGgdH��Z_e	dIe_j`dJ�Zae	dKdLdMg�Zbe	dNdOdP�cebj`��Zde	dQgdR��ZeedSdT�dUdV��ZfdWdX�ZgedYdZ��Zhd[d\�Zid]d^�Zje&jkZkd_d`�Zldadb�Zmdcdd�Zndedf�Zodgdh�Zpdidj�Zqdkdl�Zrdmdn�Zsdoatdpdq�Zud�drds�Zvdtdu�Zwdvdw�Zxdxdy�Zydzd{�Zzda{d|d}�Z|d~d�Z}d�d��Z~d�d��ZGd�d��d��Z�e&j�Z�e&j�Z�e&j�Z�d�d��Z�d�d�d��Z�d�d��Z�d�d��Z�Gd�d��d��Z�dS)�z Windows platform implementation.�N)�
namedtuple�)�_common)�ENCODING)�
ENCODING_ERRS)�AccessDenied)�
NoSuchProcess)�TimeoutExpired)�	conn_tmap)�conn_to_ntuple)�debug)�
isfile_strict)�memoize)�memoize_when_activated)�parse_environ_block)�
usage_percent)�PY3)�long)�	lru_cache��range)�unicode)�ABOVE_NORMAL_PRIORITY_CLASS)�BELOW_NORMAL_PRIORITY_CLASS)�HIGH_PRIORITY_CLASS)�IDLE_PRIORITY_CLASS)�NORMAL_PRIORITY_CLASS)�REALTIME_PRIORITY_CLASS)�_psutil_windowszdll load failed�z3this Windows version is too old (< Windows Vista); z:psutil 3.4.2 is the latest version which supports Windows z2000, XP and 2003 server)�win_service_iter�win_service_getrrrrrr�IOPRIO_VERYLOW�
IOPRIO_LOW�
IOPRIO_NORMAL�IOPRIO_HIGH�CONN_DELETE_TCB�AF_LINKZ
DELETE_TCBi+Z__pypy__����
AddressFamilyr'c@s$eZdZeZeZeZeZeZeZdS)�PriorityN)	�__name__�
__module__�__qualname__rrrrrr�r.r.�=/usr/local/lib64/python3.9/site-packages/psutil/_pswindows.pyr*ssr*��c@seZdZdZdZdZdZdS)�
IOPriorityrrr0r1N)r+r,r-r"r#r$r%r.r.r.r/r2�sr2�����	�
���
��������)�num_handles�ctx_switches�	user_time�kernel_time�create_time�num_threads�	io_rcount�	io_wcount�	io_rbytes�	io_wbytes�io_count_others�io_bytes_others�num_page_faults�	peak_wset�wset�peak_paged_pool�
paged_pool�peak_non_paged_pool�non_paged_pool�pagefile�
peak_pagefile�mem_private�	scputimes)�user�system�idle�	interrupt�dpc�svmem)�total�	available�percent�used�free�pmem)�rss�vmsrPrQrRrSrTZpeak_nonpaged_poolZ
nonpaged_poolrWrX�private�pfullmem)�uss�
pmmap_grouped�pathrg�	pmmap_extzaddr perms � �pio)Z
read_countZwrite_count�
read_bytes�write_bytes�other_countZother_bytesi)�maxsizecCs@d�|�d�dd��}t�|�}|t|�d�}tj�||�S)z�Convert paths using native DOS format like:
        "\Device\HarddiskVolume1\Windows\systemew\file.txt"
    into:
        "C:\Windows\systemew\file.txt".
    �\Nr1)�join�split�cextZQueryDosDevice�len�osrm)�sZrawdriveZdriveletter�	remainderr.r.r/�convert_dos_path�s
r}cCs&tr|St|t�r|S|�tt�SdS)zmEncode a unicode string to a byte string by using the default fs
    encoding + "replace" error handler.
    N)r�
isinstance�str�encoderr)r{r.r.r/�
py2_strencode�s

r�cCst��S�N)rx�getpagesizer.r.r.r/r��sr�c
CsJt��}|\}}}}|}|}|}||}t|||dd�}	t|||	||�S)z&System virtual memory as a namedtuple.r�Zround_)rx�virtual_memrr`)
�memZtotphysZ	availphysZ_totsysZ	_availsysraZavailrerdrcr.r.r/�virtual_memory�sr�cCspt��}|d}|d}||}|dkrBt��}td||�}nd}d}||}t|d�}t�||||dd�S)z=Swap system memory as a (total, used, free, sin, sout) tuple.rr0g{�G�z�?�r)rxr�Zswap_percent�int�roundrZsswap)r�Z
total_physZtotal_systemraZpercentswaprdrercr.r.r/�swap_memory�s
r�cCsPtrt|t�r|jtdd�}t�|�\}}||}t||dd�}t�	||||�S)z'Return disk usage associated with path.�strict)�errorsrr�)
rr~�bytes�decoderrx�
disk_usagerrZ
sdiskusage)rmrarerdrcr.r.r/r�sr�cCst�|�}dd�|D�S)zReturn disk partitions.cSsg|]}tj|��qSr.)rZ	sdiskpart��.0�xr.r.r/�
<listcomp>+�z#disk_partitions.<locals>.<listcomp>)rx�disk_partitions)�all�rawlistr.r.r/r�(s
r�cCs<t��\}}}tdd�tt���D��}t||||j|j�S)z)Return system CPU times as a named tuple.cSsg|]}t|��qSr.)�sum)r��nr.r.r/r�9r�zcpu_times.<locals>.<listcomp>)rx�	cpu_timesrZ�zip�
per_cpu_timesr^r_)r[r\r]Z
percpu_summedr.r.r/r�3s
�r�cCs:g}t��D](\}}}}}t|||||�}|�|�q|S)z6Return system per-CPU times as a list of named tuples.)rxr�rZ�append)�retr[r\r]r^r_�itemr.r.r/r�?s
r�cCst��S)z0Return the number of logical CPUs in the system.)rx�cpu_count_logicalr.r.r.r/r�Hsr�cCst��S)z-Return the number of CPU cores in the system.)rx�cpu_count_coresr.r.r.r/r�Msr�cCs$t��\}}}}d}t�||||�S)zReturn CPU statistics.r)rx�	cpu_statsrZ	scpustats)rEZ
interruptsZ_dpcsZsyscallsZsoft_interruptsr.r.r/r�Rs
�r�cCs(t��\}}d}t�t|�|t|��gS)zMReturn CPU frequency.
    On Windows per-cpu frequency is not supported.
    r�)rx�cpu_freqrZscpufreq�float)�currZmax_Zmin_r.r.r/r�[sr�FcCs*tst��dat��}tdd�|D��S)z�Return the number of processes in the system run queue averaged
    over the last 1, 5, and 15 minutes respectively as a tuple.
    TcSsg|]}t|d��qS)r0)r�)r��loadr.r.r/r�sr�zgetloadavg.<locals>.<listcomp>)�_loadavg_inititializedrxZinit_loadavg_counter�
getloadavg�tuple)Z	raw_loadsr.r.r/r�gs
r�cCs�|tvr(td|d�dd�tD��f��t|\}}t�|||�}t�}|D]D}|\}}}	}
}}}
t|||	|
||t|dkr~|
ndd�}|�|�qLt	|�S)z�Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    z+invalid %r kind argument; choose between %sz, cSsg|]}t|��qSr.)�reprr�r.r.r/r��r�z#net_connections.<locals>.<listcomp>r(N)�pid)
r
�
ValueErrorrvrx�net_connections�setr�TCP_STATUSES�add�list)�kind�_pidZfamilies�typesr�r�r��fd�fam�type�laddr�raddr�statusr��ntr.r.r/r�{s.���
r�cCszi}t��}|��D]`\}}ts>t|t�s6Jt|���t|�}|\}}}}tt	d�r^t	�
|�}t	�||||d�||<q|S)z)Get NIC stats (isup, duplex, speed, mtu).�	NicDuplex�)rx�net_if_stats�itemsrr~rr�r��hasattrrr�Z	snicstats)r�Zrawdict�namer�ZisupZduplex�speedZmtur.r.r/r��s

r�cCst��}tdd�|��D��S)zsReturn network I/O statistics for every network interface
    installed on the system as a dict of raw tuples.
    cSsg|]\}}t|�|f�qSr.�r�)r��k�vr.r.r/r��r�z#net_io_counters.<locals>.<listcomp>)rx�net_io_counters�dictr��r�r.r.r/r��sr�cCs8g}t��D]&}t|�}t|d�|d<|�|�q|S)z,Return the addresses associated to each NIC.r)rx�net_if_addrsr�r�r�)r�r�r.r.r/r��sr�cCsdt��\}}}}|dk}t|d@�}t|d@�}|r8dS|s@|rHtj}n|dkrVtj}t�|||�S)zReturn battery information.r�r6Nr()rx�sensors_battery�boolrZPOWER_TIME_UNLIMITEDZPOWER_TIME_UNKNOWNZsbattery)Z
acline_status�flagsrcZsecsleftZ
power_pluggedZ
no_batteryZchargingr.r.r/r��sr�cCs,tt���}t|t�dkr tS|a|SdS)z:The system boot time expressed in seconds since the epoch.rN)r�rx�	boot_time�abs�_last_btimer�r.r.r/r��s
r�cCsHg}t��}|D]2}|\}}}t|�}t�|d||d�}|�|�q|S)z:Return currently connected users as a list of namedtuples.N)rx�usersr�rZsuserr�)�retlistr�r�r[�hostnameZtstampr�r.r.r/r��s
r�ccs*t��D]\}}tt|�t|��VqdS)z*Yields a list of WindowsService instances.N)rxZwinservice_enumerate�WindowsServicer�)r��display_namer.r.r/r �sr cCst|d�}|��d|_|S)zBOpen a Windows service and return it as a WindowsService instance.Nr�)r��
_query_config�
_display_name)r�Zservicer.r.r/r!�s
r!c@s�eZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
ejdd��Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$S)%r�z(Represents an installed Windows service.cCs||_||_dSr�)�_namer�)�selfr�r�r.r.r/�__init__szWindowsService.__init__cCs d|j|jf}d|jj|fS)Nz(name=%r, display_name=%r)z%s%s)r�r��	__class__r+)r��detailsr.r.r/�__str__s
�zWindowsService.__str__cCsd|��t|�fS)Nz
<%s at %s>)r��id�r�r.r.r/�__repr__szWindowsService.__repr__cCst|t�stS|j|jkSr�)r~r��NotImplementedr��r��otherr.r.r/�__eq__s
zWindowsService.__eq__cCs
||kSr�r.r�r.r.r/�__ne__szWindowsService.__ne__cCs\|���$t�|j�\}}}}Wd�n1s20Ytt|�t|�t|�t|�d�S)N)r��binpath�username�
start_type)�_wrap_exceptionsrxZwinservice_query_configr�r�r�)r�r�r�r�r�r.r.r/r� s

�(�zWindowsService._query_configcCsP|��� t�|j�\}}Wd�n1s.0Y|dkrDd}t||d�S)Nr)r�r�)r�rxZwinservice_query_statusr�r�)r�r�r�r.r.r/�
_query_status-s

.zWindowsService._query_statusc
cs�z
dVWnxty�}z`t|�r>d|j}td|j|d��n0|jtjtjfvrld|j}td|j|d��n�WYd}~n
d}~00dS)z{Ctx manager which translates bare OSError and WindowsError
        exceptions into NoSuchProcess and AccessDenied.
        Nz2service %r is not querable (not enough privileges)�r�r��msgzservice %r does not exist)	�OSError�is_permission_errr�r�winerrorrxZERROR_INVALID_NAMEZERROR_SERVICE_DOES_NOT_EXISTr)r��errr�r.r.r/r�4s 
���
zWindowsService._wrap_exceptionscCs|jS)z�The service name. This string is how a service is referenced
        and can be passed to win_service_get() to get a new
        WindowsService instance.
        )r�r�r.r.r/r�MszWindowsService.namecCs|jS)z_The service display name. The value is cached when this class
        is instantiated.
        )r�r�r.r.r/r�TszWindowsService.display_namecCs|��dS)zwThe fully qualified path to the service binary/exe file as
        a string, including command line arguments.
        r��r�r�r.r.r/r�ZszWindowsService.binpathcCs|��dS)z,The name of the user that owns this service.r�r�r�r.r.r/r�`szWindowsService.usernamecCs|��dS)zRA string which can either be "automatic", "manual" or
        "disabled".
        r�r�r�r.r.r/r�dszWindowsService.start_typecCs|��dS)zzThe process PID, if any, else None. This can be passed
        to Process class to control the service's process.
        r��r�r�r.r.r/r�lszWindowsService.pidcCs|��dS)zService status as a string.r�r�r�r.r.r/r�rszWindowsService.statuscCstt�|����S)zService long description.)r�rxZwinservice_query_descrr�r�r.r.r/�descriptionvszWindowsService.descriptioncCs>|��}|�|���|��|d<|��|d<|��|d<|S)zUUtility method retrieving all the information above as a
        dictionary.
        r�r�r�)r��updater�r�r�r�)r��dr.r.r/�as_dict|szWindowsService.as_dictN)r+r,r-�__doc__r�r�r�r�r�r�r��
contextlib�contextmanagerr�r�r�r�r�r�r�r�r�r�r.r.r.r/r�s&

r�cCs@t|t�sJ|��|jtjtjfvr(dSt|dd�tjtjfvS)z*Return True if this is a permission error.Tr�r()	r~r��errno�EPERM�EACCES�getattrrxZERROR_ACCESS_DENIEDZERROR_PRIVILEGE_NOT_HELD)�excr.r.r/r��s
�r�cCsFt|t�sJ|��t|�r&t||d�S|jtjkr>t||d�S|�dS)z3Convert OSError into NoSuchProcess or AccessDenied.�r�r�N)r~r�r�rr�ZESRCHr)r�r�r�r.r.r/�convert_oserror�srcst����fdd��}|S)zDDecorator which converts OSError into NoSuchProcess or AccessDenied.c
sTz�|g|�Ri|��WStyN}zt||j|jd��WYd}~n
d}~00dS)Nr)r�rr�r�)r��args�kwargsr���funr.r/�wrapper�sz wrap_exceptions.<locals>.wrapper��	functools�wraps�rrr.rr/�wrap_exceptions�srcst����fdd��}|S)z�Workaround for https://github.com/giampaolo/psutil/issues/875.
    See: https://stackoverflow.com/questions/4457745#4457745.
    cs�d}d}t|�D]z}z�|g|�Ri|��WSty�}z@|}|jtkrrt�|�t|dd�}WYd}~q�WYd}~qd}~00qd��||�}t|j	|j
|d��dS)N�-C��6?�!r0�{�G�z�?zH{} retried {} times, converted to AccessDenied as it's stillreturning {}r�)r�WindowsErrorr��ERROR_PARTIAL_COPY�time�sleep�min�formatrr�r�)r�rr�delay�times�_r�r�rr.r/r�s"

��z)retry_error_partial_copy.<locals>.wrapperrr
r.rr/�retry_error_partial_copy�src@s�eZdZdZgd�Zdd�Zdd�Zdd�Zed	d
��Z	dd�Z
eed
d���Zee
dd���Zee
dd���Zdd�Zdd�Zedd��Zedd��Zdd�Zedd��Zedd ��ZedNd"d#��Zed$d%��ZedOd'd(��Zed)d*��Zed+d,��Zed-d.��Zed/d0��Zed1d2��Zee
d3d4���Zed5d6��Z edPd8d9��Z!ed:d;��Z"ed<d=��Z#ed>d?��Z$ed@dA��Z%edBdC��Z&edDdE��Z'edFdG��Z(edHdI��Z)edJdK��Z*edLdM��Z+d!S)Q�Processz1Wrapper class around underlying C implementation.)�_cacher��_ppidr�cCs||_d|_d|_dSr�)r�r�r)r�r�r.r.r/r��szProcess.__init__cCs|j�|�|j�|�dSr�)�
_proc_infoZcache_activate�exer�r.r.r/�
oneshot_enterszProcess.oneshot_entercCs|j�|�|j�|�dSr�)rZcache_deactivaterr�r.r.r/�oneshot_exit
szProcess.oneshot_exitcCs$t�|j�}t|�tt�ks J�|S)zOReturn multiple information about this process as a
        raw tuple.
        )rxZ	proc_infor�ry�	pinfo_map�r�r�r.r.r/rszProcess._proc_infocCs,|jdkrdS|jdkrdStj�|���S)zbReturn process name, which on Windows is always the final
        part of the executable.
        rzSystem Idle Processr3�System)r�rzrm�basenamerr�r.r.r/r�s


zProcess.namec
Cs�trbzt�|j�}Wqnty^}z2|jdkrHtd|�t|j|j���WYd}~qnd}~00nt�|j�}t	szt
|�}|�d�r�t|�S|S)N�z%r translated into AccessDeniedru)
�PYPYrxZproc_exer�rr�rrr�rr��
startswithr})r�rr�r.r.r/r#s

zProcess.exec
Cs�tjtjkrdztj|jdd�}Wqtty`}z(t|�rJtj|jdd�}n�WYd}~qtd}~00ntj|jdd�}tr||Sdd�|D�SdS)NT)Zuse_pebFcSsg|]}t|��qSr.r�)r�r{r.r.r/r�Jr�z#Process.cmdline.<locals>.<listcomp>)rxZWINVERZWINDOWS_8_1Zproc_cmdliner�r�r�r)r�r�r�r.r.r/�cmdline8szProcess.cmdlinecCs6t�|j�}|r*ts*t|t�s*Jt|���tt|��Sr�)	rxZproc_environr�rr~rr�rr�)r�Zustrr.r.r/�environLszProcess.environcCs4zt�|jWSty.t|j|j��Yn0dSr�)�ppid_mapr��KeyErrorrr�r�r.r.r/�ppidTszProcess.ppidcCs�zt�|j�WSty�}z�t|�r�td�|��}|td|td|td|td|td|td|td|td	|td
|tdf
WYd}~S�WYd}~n
d}~00dS)Nz*attempting memory_info() fallback (slower)rPrQrRrSrTrUrVrWrXrY)rxZproc_memory_infor�r�r�rrr )r�r��infor.r.r/�_get_raw_meminfoZs$









�zProcess._get_raw_meminfocCs(|��}|d}|d}t||f|�S)Nr0r5)r-rf)r��trgrhr.r.r/�memory_infoqszProcess.memory_infocCs,|��}t�|j�}|t�9}t||f�Sr�)r/rxZproc_memory_ussr�r�rj)r�Z	basic_memrkr.r.r/�memory_full_info{s
zProcess.memory_full_infoc
cs�zt�|j�}Wn4tyD}zt||j|j��WYd}~nFd}~00|D]6\}}}}t|�}tsjt|�}t	|�}||||fVqJdSr�)
rxZproc_memory_mapsr�r�rr�r}rr��hex)r��rawr��addr�permrmrgr.r.r/�memory_maps�s&zProcess.memory_mapscCst�|j�Sr�)rx�	proc_killr�r�r.r.r/�kill�szProcess.killcCsX|tjkrt�|j�n<|ttdt��ttdt��fvrHt�|j|�nd}t	|��dS)NZCTRL_C_EVENTZCTRL_BREAK_EVENTzPonly SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals are supported on Windows)
�signal�SIGTERMrxr6r�r��objectrzr7r�)r��sigr�r.r.r/�send_signal�s
��zProcess.send_signalNcCs�|durtj}nt|d�}ttdtj�}|dur<|�|nd}zt�|j|�}Wn:tjyvt||j|j��Yntj	y�d}Yn0d}t
|j�s�|S|r�|�|kr�t||j|jd��t�|�t|dd�}q�dS)Ni��	monotonicrrr0r)
rxZINFINITEr�r�rZ	proc_waitr�r	r�ZTimeoutAbandoned�
pid_existsrr)r��timeoutZcext_timeout�timerZstop_atZ	exit_coderr.r.r/�wait�s$	


zProcess.waitcCs2|jdvrdSt�|j�\}}t|�dt|�S)N�rr3zNT AUTHORITY\SYSTEMru)r�rxZ
proc_usernamer�)r��domainr[r.r.r/r��s
zProcess.usernameFc
Csvzt�|j�\}}}|WStyp}z@t|�rZ|r6�td�|��tdWYd}~S�WYd}~n
d}~00dS)Nz*attempting create_time() fallback (slower)rH)rx�
proc_timesr�r�r�rrr )r�Z	fast_only�_userZ_system�createdr�r.r.r/rH�szProcess.create_timecCs|��tdS)NrI)rr r�r.r.r/rI�szProcess.num_threadscCs<t�|j�}g}|D]"\}}}t�|||�}|�|�q|Sr�)rxZproc_threadsr�rZpthreadr�)r�r�r��	thread_id�utimeZstime�ntupler.r.r/�threads�szProcess.threadsc
Cs~zt�|j�\}}}WnVtyl}z>t|�s0�td�|��}|td}|td}WYd}~n
d}~00t�	||dd�S)Nz(attempting cpu_times() fallback (slower)rFrGr�)
rxrDr�r�r�rrr rZ	pcputimes)r�r[r\Z_createdr�r,r.r.r/r��s"zProcess.cpu_timescCst�|jd�dS)NT�rxZproc_suspend_or_resumer�r�r.r.r/�suspendszProcess.suspendcCst�|jd�dS)NFrKr�r.r.r/�resumeszProcess.resumecCs4|jdvrt|j|j��t�|j�}ttj�|��S)NrB)	r�rr�rxZproc_cwdr�rzrm�normpath)r�rmr.r.r/�cwd
s
zProcess.cwdcCsd|jdvrgSt�}t�|j�}|D]6}t|�}t|�r$tsDt|�}t�	|d�}|�
|�q$t|�S)NrBr()r�r�rxZproc_open_filesr}r
rr�rZ	popenfiler�r�)r�r�Zraw_file_names�_filerIr.r.r/�
open_filess
zProcess.open_files�inetcCst||jd�S)N)r�)r�r�)r�r�r.r.r/r�'szProcess.net_connectionscCs t�|j�}tdurt|�}|Sr�)rxZproc_priority_getr��enumr*�r��valuer.r.r/�nice_get+szProcess.nice_getcCst�|j|�Sr�)rxZproc_priority_setr�rTr.r.r/�nice_set2szProcess.nice_setcCs t�|j�}tdurt|�}|Sr�)rxZproc_io_priority_getr�rSr2r!r.r.r/�
ionice_get6szProcess.ionice_getcCs>|rd}t|��|ttttfvr,td|��t�|j|�dS)Nz&value argument not accepted on Windowsz%s is not a valid priority)	�	TypeErrorr"r#r$r%r�rxZproc_io_priority_setr�)r�ZioclassrUr�r.r.r/�
ionice_set=s�zProcess.ionice_setcCs�zt�|j�}Wn~ty�}zft|�s*�td�|��}|td|td|td|td|td|tdf}WYd}~n
d}~00t|�S)Nz*attempting io_counters() fallback (slower)rJrKrLrMrNrO)	rxZproc_io_countersr�r�r�rrr rp)r�r�r�r,r.r.r/�io_countersKs





�zProcess.io_counterscCs t�|j�}|rtjStjSdSr�)rxZproc_is_suspendedr�rZSTATUS_STOPPEDZSTATUS_RUNNING)r�Z	suspendedr.r.r/r�^szProcess.statuscCsdd�}t�|j�}||�S)Ncs�fdd�td�D�S)Ncsg|]}d|>�@r|�qS)rr.)r��i�r�r.r/r�ir�zBProcess.cpu_affinity_get.<locals>.from_bitmask.<locals>.<listcomp>�@rr]r.r]r/�from_bitmaskhsz.Process.cpu_affinity_get.<locals>.from_bitmask)rxZproc_cpu_affinity_getr�)r�r_�bitmaskr.r.r/�cpu_affinity_getfszProcess.cpu_affinity_getcCsndd�}tttt����}|D]4}||vrt|ttf�sFtd|��qtd|��q||�}t	�
|j|�dS)NcSs.|std|��d}|D]}|d|O}q|S)Nzinvalid argument %rrr0)r�)Zls�out�br.r.r/�
to_bitmaskpsz,Process.cpu_affinity_set.<locals>.to_bitmaskz&invalid CPU %r; an integer is requiredzinvalid CPU %r)r�rryr�r~r�rrYr�rxZproc_cpu_affinity_setr�)r�rUrdZallcpus�cpur`r.r.r/�cpu_affinity_setns�zProcess.cpu_affinity_setc
Csfzt�|j�WSty`}z:t|�rJtd�|��tdWYd}~S�WYd}~n
d}~00dS)Nz*attempting num_handles() fallback (slower)rD)rxZproc_num_handlesr�r�r�rrr )r�r�r.r.r/rD�szProcess.num_handlescCs|��td}t�|d�S)NrEr)rr rZpctxsw)r�rEr.r.r/�num_ctx_switches�szProcess.num_ctx_switches)N)F)rR),r+r,r-r��	__slots__r�rrrrr�rrrr'r(r+r-r/r0r5r7r<rAr�rHrIrJr�rLrMrOrQr�rVrWrXrZr[r�rarfrDrgr.r.r.r/r�s�

	


*

















	r)r()NN)�r�r�r�rrzr8�sysr�collectionsrr�rrrrrr	r
rrr
rrrrZ_compatrrrrrrrrrrrrrx�ImportErrorr�r�lowerr&�getwindowsversionr��RuntimeErrorrSZ__extra__all__r&r�builtin_module_namesr%r'�IntEnumr)ZMIB_TCP_STATE_ESTABZCONN_ESTABLISHEDZMIB_TCP_STATE_SYN_SENTZ
CONN_SYN_SENTZMIB_TCP_STATE_SYN_RCVDZ
CONN_SYN_RECVZMIB_TCP_STATE_FIN_WAIT1ZCONN_FIN_WAIT1ZMIB_TCP_STATE_FIN_WAIT2ZCONN_FIN_WAIT2ZMIB_TCP_STATE_TIME_WAITZCONN_TIME_WAITZMIB_TCP_STATE_CLOSEDZ
CONN_CLOSEZMIB_TCP_STATE_CLOSE_WAITZCONN_CLOSE_WAITZMIB_TCP_STATE_LAST_ACKZ
CONN_LAST_ACKZMIB_TCP_STATE_LISTENZCONN_LISTENZMIB_TCP_STATE_CLOSINGZCONN_CLOSINGZMIB_TCP_STATE_DELETE_TCBZPSUTIL_CONN_NONEZ	CONN_NONEr�r*�globalsr��__members__r"r#r$r%r2r�r rZr`rf�_fieldsrjrlrvrnrpr}r�r�r�r�Zdisk_io_countersr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r r!r�Zpidsr>r)r�rrrrr.r.r.r/�<module>s6��



�

�!���


				
0


PKok\�U��*psutil/__pycache__/__init__.cpython-39.pycnu�[���a

��?hB\�@s�dZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZzddl
Z
Wney�dZ
Yn0ddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*dd lm+Z+dd!lm,Z,dd"lm-Z-dd#lm.Z.dd$lm/Z/dd%lm0Z0dd&lm1Z1dd'lm2Z2dd(lm3Z3dd)lm4Z4dd*lm5Z5dd+lm6Z6dd,lm7Z7dd-lm8Z8dd.lm9Z9dd/lm:Z:dd0lm;Z;dd1lm<Z<dd2lm=Z=dd3lm>Z>dd4lm?Z?dd5lm@ZAdd6lBmCZDdd7lBmEZEdd8lBmFZFdd9lBmGZHdd:lBmIZIe �rVd;ZJdd<lmKZLdd=lKmMZMdd>lKmNZNdd?lKmOZOdd@lKmPZP�ne8�r�ddAlmQZLddBlRmSZSddClRmTZTddDlRmUZUddElRmVZVddFlRmWZWddGlRmXZXddHlQmYZYddIlQmZZZddJlQm[Z[ddKlQm\Z\ddLlQm]Z]n~e!�rddMlm^ZLnje�rddNlm_ZLnVe7�rFddOlm`ZLddPl`maZaddQl`mbZbd;ZJn&e�r^ddRlmcZLd;ZJneddSe
je��gdT�Zfef�geLjh�eieLjjdU��r�ddVlmkZkel�ZmdZneoek�D]4Znen�pdW��r�en�q��r�ereken�emen<ef�sen��q�[m[neLjtZtdXZudYZvewdZd[�ev�xd\�D��Zyered]ej�Zzda{da|e}�Z~eev��d\d^��ereLj�d_d�k�r�d`eLj�j�Z�e�da7Z�eieLj�d_��r�e�dbd\��dcd[�e�eLj�j��D��evf7Z�ne�ddev7Z�e�deereLj�dfdg�7Z�e�dh7Z�ee���eieLdi��r�eLj�Z�ndjdk�Z�dldm�Z�Gdndo�doe}�Zje�dpd[�eoej�D��Z�Gdqdr�drej�Z�dsdt�Z�dudv�Z�ia�e��Z�d�dwdx�Z�dydz�e�_�d{e�j�_d�d|d}�Z�d�dd��Z�d�d�d��Z�ze���j�e��iZ�Wne��y�iZ�Yn0ze���j�e�d~d��iZ�Wne��y�iZ�Yn0d�d��Z�d�d��Z�d�d��Z�d�d�d��Z�e����Z�e����Z�d�d�d��Z�d�d��Z�eieLd���r8d�d�d��Z�ef�sd��eied���sPeieLd���rteied���rdej�Z�neLj�Z�ef�sd��d�d��Z�d�d��Z�d�d��Z�d�d�d��Z�d�d�d��Z�e��eAj�d��e�_�d�e�j�_d�d�d��Z�e��eAj�d��e�_�d�e�j�_d�d�d��Z�d�d��Z�d�d��Z�eieLd���rd�d�d��Z�ef�sd��eieLd���r2d�d��Z�ef�sd��eieLd���rPd�d��Z�ef�sd��d�d��Z�d�d��Z�e8�rvd�d��Z�d�d��Z�d�d��Z�d�d��Z�[?[e
jydd�k�r�[�[�e�d�k�r�e��dS)�a/psutil is a cross-platform library for retrieving information on
running processes and system utilization (CPU, memory, disks, network,
sensors) in Python. Supported platforms:

 - Linux
 - Windows
 - macOS
 - FreeBSD
 - OpenBSD
 - NetBSD
 - Sun Solaris
 - AIX

Works with Python versions 2.7 and 3.6+.
�)�divisionN�)�_common)�AIX)�BSD)�
CONN_CLOSE)�CONN_CLOSE_WAIT)�CONN_CLOSING)�CONN_ESTABLISHED)�CONN_FIN_WAIT1)�CONN_FIN_WAIT2)�
CONN_LAST_ACK)�CONN_LISTEN)�	CONN_NONE)�
CONN_SYN_RECV)�
CONN_SYN_SENT)�CONN_TIME_WAIT)�FREEBSD)�LINUX)�MACOS)�NETBSD)�NIC_DUPLEX_FULL)�NIC_DUPLEX_HALF)�NIC_DUPLEX_UNKNOWN)�OPENBSD)�OSX)�POSIX)�POWER_TIME_UNKNOWN)�POWER_TIME_UNLIMITED)�STATUS_DEAD)�STATUS_DISK_SLEEP)�STATUS_IDLE)�
STATUS_LOCKED)�
STATUS_PARKED)�STATUS_RUNNING)�STATUS_SLEEPING)�STATUS_STOPPED)�STATUS_TRACING_STOP)�STATUS_WAITING)�
STATUS_WAKING)�
STATUS_ZOMBIE)�SUNOS)�WINDOWS)�AccessDenied)�Error)�
NoSuchProcess)�TimeoutExpired)�
ZombieProcess)�debug)�memoize_when_activated)�wrap_numbers)�PY3)�PermissionError)�ProcessLookupError)�SubprocessTimeoutExpired)�longz/proc)�_pslinux)�IOPRIO_CLASS_BE)�IOPRIO_CLASS_IDLE)�IOPRIO_CLASS_NONE)�IOPRIO_CLASS_RT)�
_pswindows)�ABOVE_NORMAL_PRIORITY_CLASS)�BELOW_NORMAL_PRIORITY_CLASS)�HIGH_PRIORITY_CLASS)�IDLE_PRIORITY_CLASS)�NORMAL_PRIORITY_CLASS)�REALTIME_PRIORITY_CLASS)�CONN_DELETE_TCB)�IOPRIO_HIGH)�
IOPRIO_LOW)�
IOPRIO_NORMAL)�IOPRIO_VERYLOW)�_psosx)�_psbsd)�_pssunos)�
CONN_BOUND)�	CONN_IDLE)�_psaixzplatform %s is not supported)Gr.r/r1r-r0�version_info�__version__r$r!r%r r&r'r*rr)r"r(r"r#r
rrrrrrrr
rr	r�AF_LINKrrrrrrrrrrrrrr+r,r�Process�Popen�
pid_exists�pids�process_iter�
wait_procs�virtual_memory�swap_memory�	cpu_times�cpu_percent�cpu_times_percent�	cpu_count�	cpu_stats�net_io_counters�net_connections�net_if_addrs�net_if_stats�disk_io_counters�disk_partitions�
disk_usage�users�	boot_time�rlimit)�
_psutil_posixZRLIMzGiampaolo Rodola'z6.1.0cCsg|]}t|��qS�)�int)�.0�numrlrl�;/usr/local/lib64/python3.9/site-packages/psutil/__init__.py�
<listcomp>��rq�.�	monotonic��versionz!version conflict: %r C extension z.module was built for another version of psutilz (%s instead of %s)cCsg|]}|�qSrlrl�rn�xrlrlrprq�rrz (different than %s)z;; you may try to 'pip uninstall psutil', manually remove %s�__file__z%the existing psutil install directoryz1 or clean the virtual env somehow, then reinstall�ppid_mapc
CsBi}t�D]2}zt�|���||<Wq
ttfy:Yq
0q
|S)z{Return a {pid: ppid, ...} dict for all running processes in
        one shot. Used to speed up Process.children().
        )rW�_psplatformrT�ppidr/r1)�ret�pidrlrlrp�	_ppid_maps
rcCs6t��}t||�}|dkr dnd}tj�|��|�S)z(Format seconds in a human readable form.i�Qz%H:%M:%Sz%Y-%m-%d %H:%M:%S)�timerm�datetime�
fromtimestamp�strftime)Zsecs�nowZsecs_ago�fmtrlrlrp�_pprint_secssr�c@s�eZdZdZd�dd�Zd�dd�Zdd	�Zd
d�ZeZdd
�Z	dd�Z
dd�Zdd�Ze
dd��Zejdd��Zd�dd�Zdd�Zdd�Zdd�Zed d!��Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd�d0d1�Ze �red2d3��Z!d4d5�Z"d6d7�Z#d8d9�Z$e%e&j'd:��rd;d<�Z(e%e&j'd=��r6d�d>d?�Z)e%e&j'd@��rNd�dAdB�Z*e%e&j'dC��rfd�dDdE�Z+e%e&j'dF��r|dGdH�Z,e%e&j'dI��r�dJdK�Z-e.�r�dLdM�Z/dNdO�Z0dPdQ�Z1e%e&j'dR��r�dSdT�Z2d�dUdV�Z3d�dWdX�Z4edYdZ��Z5ed[d\��Z6e7j8d]d^�d_d`��Z9dadb�Z:d�ddde�Z;e%e&j'df��r0d�dhdi�Z<djdk�Z=d�dmdn�Z>e7j8dod^�d�dpdq��Z?e �rfdrds�Z@dtdu�ZAdvdw�ZBdxdy�ZCdzd{�ZDd|d}�ZEd�d~d�ZFdS)�rTaRepresents an OS process with the given PID.
    If PID is omitted current process PID (os.getpid()) is used.
    Raise NoSuchProcess if PID does not exist.

    Note that most of the methods of this class do not make sure that
    the PID of the process being queried has been reused. That means
    that you may end up retrieving information for another process.

    The only exceptions for which process identity is pre-emptively
    checked and guaranteed are:

     - parent()
     - children()
     - nice() (set)
     - ionice() (set)
     - rlimit() (set)
     - cpu_affinity (set)
     - suspend()
     - resume()
     - send_signal()
     - terminate()
     - kill()

    To prevent this problem for all other methods you can use
    is_running() before querying the process.
    NcCs|�|�dS�N)�_init)�selfr~rlrlrp�__init__>szProcess.__init__FcCsR|durt��}nrts4t|ttf�s4d|}t|��|dkrLd|}t|��ztj	�
|�Wn&ty�d|}t||d��Yn0||_
d|_d|_d|_d|_d|_d|_t��|_d|_t�|�|_d|_d|_t|_|jdf|_z|� �|_WnVt!�y
YnDt"�yYn2t�yL|�sBd}t||d��nd|_Yn0dS)	Nzpid must be an integer (got %r)rz'pid must be a positive integer (got %s)z!process PID out of range (got %s)��msgFzprocess PID not foundT)#�os�getpid�_PY3�
isinstancermr9�	TypeError�
ValueErrorr{�cextZcheck_pid_range�
OverflowErrorr/�_pid�_name�_exe�_create_time�_gone�_pid_reused�_hash�	threading�RLock�_lock�_ppidrT�_proc�_last_sys_cpu_times�_last_proc_cpu_times�	_SENTINEL�	_exitcoder~�_ident�
_get_identr-r1)r�r~�_ignore_nspr�rlrlrpr�AsL

z
Process._initcCs2tr |jjdd�|_|j|jfS|j|��fSdS)aReturn a (pid, uid) tuple which is supposed to identify a
        Process instance univocally over time. The PID alone is not
        enough, as it can be assigned to a new process after this one
        terminates, so we add process creation time to the mix. We need
        this in order to prevent killing the wrong process later on.
        This is also known as PID reuse or PID recycling problem.

        The reliability of this strategy mostly depends on
        create_time() precision, which is 0.01 secs on Linux. The
        assumption is that, after a process terminates, the kernel
        won't reuse the same PID after such a short period of time
        (0.01 secs). Technically this is inherently racy, but
        practically it should be good enough.
        T)Z	fast_onlyN)r,r��create_timer�r~�r�rlrlrpr�tszProcess._get_identc	Cst��}|j|d<|jr"|j|d<|����|jr<d|d<n`z|��|d<|��|d<WnBtyrd|d<Yn*t	y�d|d<Ynt
y�Yn0|jtdfvr�|j|d<|j
dur�t|j
�|d<d	|jj|jjd
�dd�|��D��fWd�S1�s0YdS)
Nr~�namezterminated + PID reused�statusZzombieZ
terminated�exitcode�startedz	%s.%s(%s)�, cSsg|]\}}d||f�qS)z%s=%rrl)rn�k�vrlrlrprq�rrz#Process.__str__.<locals>.<listcomp>)�collections�OrderedDictr~r��oneshotr�r�r�r1r/r-r�r�r�r��	__class__�
__module__�__name__�join�items)r��inforlrlrp�__str__�s2





�zProcess.__str__cCsht|t�stStstr\|j\}}|j\}}||kr\|r\|s\z|��tkWStyZYn0|j|jkSr�)	r�rT�NotImplementedrrr�r�r*r.)r��otherZpid1Zident1Zpid2Zident2rlrlrp�__eq__�s


zProcess.__eq__cCs
||kSr�rl)r�r�rlrlrp�__ne__�szProcess.__ne__cCs|jdurt|j�|_|jSr�)r��hashr�r�rlrlrp�__hash__�s
zProcess.__hash__cCs.|js|��s*|jr*d}t|j|j|d��dS)z9Raises NoSuchProcess in case process PID has been reused.z4process no longer exists and its PID has been reusedr�N)r��
is_runningr/r~r�)r�r�rlrlrp�_raise_if_pid_reused�szProcess._raise_if_pid_reusedcCs|jS)zThe process PID.)r�r�rlrlrpr~�szProcess.pidc
cs|j��t|d�rdVn�z�|j�|�|j�|�|j�|�trP|j�|�|j�	�dVW|j�
|�|j�
|�|j�
|�tr�|j�
|�|j��n@|j�
|�|j�
|�|j�
|�tr�|j�
|�|j��0Wd�n1s�0YdS)a#Utility context manager which considerably speeds up the
        retrieval of multiple process information at the same time.

        Internally different process info (e.g. name, ppid, uids,
        gids, ...) may be fetched by using the same routine, but
        only one information is returned and the others are discarded.
        When using this context manager the internal routine is
        executed once (in the example below on name()) and the
        other info are cached.

        The cache is cleared when exiting the context manager block.
        The advice is to use this every time you retrieve more than
        one information about the process. If you're lucky, you'll
        get a hell of a speedup.

        >>> import psutil
        >>> p = psutil.Process()
        >>> with p.oneshot():
        ...     p.name()  # collect multiple info
        ...     p.cpu_times()  # return cached value
        ...     p.cpu_percent()  # return cached value
        ...     p.create_time()  # return cached value
        ...
        >>>
        �_cacheN)r��hasattrr\Zcache_activate�memory_infor|r�uidsr�Z
oneshot_enterZcache_deactivateZoneshot_exitr�rlrlrpr��s.

�zProcess.oneshotcCst}|durvt|ttttf�s2dt|�}t|��t|�}||}|rvdt|�dkrXdndd�	t
t|��f}t|��i}|p�|}|�
��||D]f}z$|dkr�|j}	nt||�}
|
�}	Wn4ttfy�|}	Ynty�|r�Yq�Yn0|	||<q�Wd�n1�s0Y|S)	a�Utility method returning process information as a
        hashable dictionary.
        If *attrs* is specified it must be a list of strings
        reflecting available Process class' attribute names
        (e.g. ['cpu_times', 'name']) else all public (read
        only) attributes are assumed.
        *ad_value* is the value which gets assigned in case
        AccessDenied or ZombieProcess exception is raised when
        retrieving that particular process information.
        Nzinvalid attrs type %szinvalid attr name%s %sr�srur�r~)�_as_dict_attrnamesr��list�tuple�set�	frozenset�typer��lenr��map�reprr�r�r~�getattrr-r1�NotImplementedError)r��attrs�ad_valueZvalid_namesr��
invalid_namesZretdict�lsr�r}�methrlrlrp�as_dict!s<�



*zProcess.as_dictcCsrtdurtnt�d}|j|kr$dS|��}|durn|��}zt|�}|��|krX|WSWntylYn0dS)z�Return the parent process as a Process object pre-emptively
        checking whether PID has been reused.
        If no parent is known return None.
        Nr)�_LOWEST_PIDrWr~r|r�rTr/)r�Z
lowest_pidr|�ctime�parentrlrlrpr�Ps

zProcess.parentcCs,g}|��}|dur(|�|�|��}q|S)z�Return the parents of this process as a list of Process
        instances. If no parents are known return an empty list.
        N)r��append)r��parents�procrlrlrpr�cs

zProcess.parentscCst|js|jrdSz2|t|j�k|_|jr>t�|j�t|j��WdStyVYdStynd|_YdS0dS)z�Return whether this process is running.

        It also checks if PID has been reused by another process, in
        which case it will remove the process from `process_iter()`
        internal cache and return False.
        FTN)r�r�rTr~�_pids_reused�addr/r1r�rlrlrpr�ns
zProcess.is_runningcCs2|��tr|j��S|jp$|j��|_|jSdS)z`The process parent PID.
        On Windows the return value is cached after first call.
        N)r�rr�r|r�r�rlrlrpr|�s

zProcess.ppidc	Cs�tr|jdur|jS|j��}trtt|�dkrtz|��}WnttfyPYn$0|rtt	j
�|d�}|�|�rt|}||_||j_|S)z>The process name. The return value is cached after first call.N�r)
r,r�r�r�rr��cmdliner-r1r��path�basename�
startswith)r�r�r�Z
extended_namerlrlrpr��s

zProcess.namec
s��fdd�}�jdur�z�j��}Wn.tyR}z||d�WYd}~Sd}~00|szz||d�}WntyxYn0|�_�jS)z�The process executable as an absolute path.
        May also be an empty string.
        The return value is cached after first call.
        csd���}|rRttd�rRttd�rR|d}tj�|�rRtj�|�rRt�|tj�rR|St|t	�r`|�|S)N�access�X_OKr)
r�r�r�r��isabs�isfiler�r�r�r-)�fallbackr��exer�rlrp�guess_it�s
�
��
zProcess.exe.<locals>.guess_itN)r�)r�r�r�r-)r�r�r��errrlr�rpr��s
 zProcess.execCs
|j��S)z3The command line this process has been called with.)r�r�r�rlrlrpr��szProcess.cmdlinecCs(z|j��WSty"tYS0dS)z2The process current status as a STATUS_* constant.N)r�r�r1r*r�rlrlrpr��szProcess.statuscCs\trNtdurd}t|��|��j}zt�|�jWStyJt|�YS0n
|j	�
�SdS)ztThe name of the user that owns the process.
        On UNIX this is calculated by using *real* process uid.
        Nz0requires pwd module shipped with standard python)r�pwd�ImportErrorr��real�getpwuid�pw_name�KeyError�strr��username)r�r�Zreal_uidrlrlrpr��s
zProcess.usernamecCs|jdur|j��|_|jS)z�The process creation time as a floating point number
        expressed in seconds since the epoch.
        The return value is cached after first call.
        N)r�r�r�r�rlrlrpr�s
zProcess.create_timecCs
|j��S)z6Process current working directory as an absolute path.)r��cwdr�rlrlrpr�
szProcess.cwdcCs*|dur|j��S|��|j�|�dS)z'Get or set process niceness (priority).N)r�Znice_getr�Znice_set)r��valuerlrlrp�nices
zProcess.nicecCs
|j��S)zVReturn process UIDs as a (real, effective, saved)
            namedtuple.
            )r�r�r�rlrlrpr�szProcess.uidscCs
|j��S)zVReturn process GIDs as a (real, effective, saved)
            namedtuple.
            )r��gidsr�rlrlrpr�"szProcess.gidscCs
|j��S)zVThe terminal associated with this process, if any,
            else None.
            )r��terminalr�rlrlrpr�(szProcess.terminalcCs
|j��S)zcReturn the number of file descriptors opened by this
            process (POSIX only).
            )r��num_fdsr�rlrlrpr�.szProcess.num_fds�io_counterscCs
|j��S)a
Return process I/O statistics as a
            (read_count, write_count, read_bytes, write_bytes)
            namedtuple.
            Those are the number of read/write calls performed and the
            amount of bytes read and written by the process.
            )r�r�r�rlrlrpr�7szProcess.io_counters�
ionice_getcCs@|dur&|durd}t|��|j��S|��|j�||�SdS)a�Get or set process I/O niceness (priority).

            On Linux *ioclass* is one of the IOPRIO_CLASS_* constants.
            *value* is a number which goes from 0 to 7. The higher the
            value, the lower the I/O priority of the process.

            On Windows only *ioclass* is used and it can be set to 2
            (normal), 1 (low) or 0 (very low).

            Available on Linux and Windows > Vista only.
            Nz$'ioclass' argument must be specified)r�r�r�r�Z
ionice_set)r�Zioclassr�r�rlrlrp�ioniceCs
zProcess.ionicerjcCs|dur|��|j�||�S)a-Get or set process resource limits as a (soft, hard)
            tuple.

            *resource* is one of the RLIMIT_* constants.
            *limits* is supposed to be a (soft, hard) tuple.

            See "man prlimit" for further info.
            Available on Linux and FreeBSD only.
            N)r�r�rj)r��resourceZlimitsrlrlrprj[s
zProcess.rlimit�cpu_affinity_getcCsl|durtt|j����S|��|sTt|jd�r>|j��}nttt	t
dd����}|j�tt|���dS)a-Get or set process CPU affinity.
            If specified, *cpus* must be a list of CPUs for which you
            want to set the affinity (e.g. [0, 1]).
            If an empty list is passed, all egible CPUs are assumed
            (and set).
            (Windows, Linux and BSD only).
            N�_get_eligible_cpusT��percpu)
�sortedr�r�rr�r�rr��ranger�r\Zcpu_affinity_setr�)r�Zcpusrlrlrp�cpu_affinitylszProcess.cpu_affinity�cpu_numcCs
|j��S)aZReturn what CPU this process is currently running on.
            The returned number should be <= psutil.cpu_count()
            and <= len(psutil.cpu_percent(percpu=True)).
            It may be used in conjunction with
            psutil.cpu_percent(percpu=True) to observe the system
            workload distributed across CPUs.
            )r�rr�rlrlrpr�szProcess.cpu_num�environcCs
|j��S)z�The environment variables of the process as a dict.  Note: this
            might not reflect changes made after the process started.
            )r�rr�rlrlrpr�szProcess.environcCs
|j��S)z\Return the number of handles opened by this process
            (Windows only).
            )r��num_handlesr�rlrlrpr	�szProcess.num_handlescCs
|j��S)zkReturn the number of voluntary and involuntary context
        switches performed by this process.
        )r��num_ctx_switchesr�rlrlrpr
�szProcess.num_ctx_switchescCs
|j��S)z2Return the number of threads used by this process.)r��num_threadsr�rlrlrpr�szProcess.num_threads�threadscCs
|j��S)z�Return threads opened by process as a list of
            (id, user_time, system_time) namedtuples representing
            thread id and thread CPU times (user/system).
            On OpenBSD this method requires root access.
            )r�rr�rlrlrpr�szProcess.threadsc
Cs0|��t�}g}|sr|��D]P\}}||jkrz&t|�}|��|��krT|�|�WqttfylYq0qn�t	�
t�}|��D]\}}||�|�q�t�}|jg}	|	�r,|	�
�}||vr�q�|�|�||D]T}
z6t|
�}|��|��k}|�r|�|�|	�|
�Wq�ttf�y&Yq�0q�q�|S)u(Return the children of this process as a list of Process
        instances, pre-emptively checking whether PID has been reused.
        If *recursive* is True return all the parent descendants.

        Example (A == this process):

         A ─┐
            │
            ├─ B (child) ─┐
            │             └─ X (grandchild) ─┐
            │                                └─ Y (great grandchild)
            ├─ C (child)
            └─ D (child)

        >>> import psutil
        >>> p = psutil.Process()
        >>> p.children()
        B, C, D
        >>> p.children(recursive=True)
        B, X, Y, C, D

        Note that in the example above if process X disappears
        process Y won't be listed as the reference to process A
        is lost.
        )r�rr�r~rTr�r�r/r1r��defaultdictr�r��popr�)r��	recursiverzr}r~r|�childZreverse_ppid_map�seen�stackZ	child_pidZintimerlrlrp�children�s@





zProcess.childrenc
s|duo|dk}|dur0|dkr0d|}t|��t�p8d��fdd�}|rv|�}|j��}t�|�|�}|j��}n<|j}|j}|�}|j��}|dus�|dur�||_||_dS|j|j|j	|j	}	||}
||_||_z|	|
d}Wnt
�yYdS0|�}t|d�SdS)	aReturn a float representing the current process CPU
        utilization as a percentage.

        When *interval* is 0.0 or None (default) compares process times
        to system CPU times elapsed since last call, returning
        immediately (non-blocking). That means that the first time
        this is called it will return a meaningful 0.0 value.

        When *interval* is > 0.0 compares process times to system CPU
        times elapsed before and after the interval (blocking).

        In this case is recommended for accuracy that this function
        be called with at least 0.1 seconds between calls.

        A value > 100.0 can be returned in case of processes running
        multiple threads on different CPU cores.

        The returned value is explicitly NOT split evenly between
        all available logical CPUs. This means that a busy loop process
        running on a system with 2 logical CPUs will be reported as
        having 100% CPU utilization instead of 50%.

        Examples:

          >>> import psutil
          >>> p = psutil.Process(os.getpid())
          >>> # blocking
          >>> p.cpu_percent(interval=1)
          2.0
          >>> # non-blocking (percentage since last call)
          >>> p.cpu_percent(interval=None)
          2.9
          >>>
        N�r�!interval is not positive (got %r)rcs
t��Sr�)�_timerrl��num_cpusrlrp�timer sz"Process.cpu_percent.<locals>.timer�d)r�r_r�r\r��sleepr�r��user�system�ZeroDivisionError�round)
r��interval�blockingr�rZst1Zpt1Zst2Zpt2Z
delta_procZ
delta_timeZoverall_cpus_percentZsingle_cpu_percentrlrrpr]�s<#



zProcess.cpu_percentcCs
|j��S)a%Return a (user, system, children_user, children_system)
        namedtuple representing the accumulated process time, in
        seconds.
        This is similar to os.times() but per-process.
        On macOS and Windows children_user and children_system are
        always set to 0.
        )r�r\r�rlrlrpr\Ts	zProcess.cpu_timescCs
|j��S)aReturn a namedtuple with variable fields depending on the
        platform, representing memory information about the process.

        The "portable" fields available on all platforms are `rss` and `vms`.

        All numbers are expressed in bytes.
        )r�r�r�rlrlrpr�_s	zProcess.memory_infor�)�replacementcCs|��Sr�)r�r�rlrlrp�memory_info_exjszProcess.memory_info_excCs
|j��S)a]This method returns the same information as memory_info(),
        plus, on some platform (Linux, macOS, Windows), also provides
        additional metrics (USS, PSS and swap).
        The additional metrics provide a better representation of actual
        process memory usage.

        Namely USS is the memory which is unique to a process and which
        would be freed if the process was terminated right now.

        It does so by passing through the whole process address.
        As such it usually requires higher user privileges than
        memory_info() and is considerably slower.
        )r��memory_full_infor�rlrlrpr$nszProcess.memory_full_info�rsscCs�ttjj�}||vr,d|t|�f}t|��|tjjvr>|jn|j}|�}t	||�}t
p^t�j}|dksxd|}t|��|t
|�dS)a�Compare process memory to total physical system memory and
        calculate process memory utilization as a percentage.
        *memtype* argument is a string that dictates what type of
        process memory you want to compare against (defaults to "rss").
        The list of available strings can be obtained like this:

        >>> psutil.Process().memory_info()._fields
        ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss')
        z&invalid memtype %r; valid types are %rrz`can't calculate process memory percent because total physical system memory is not positive (%r)r)r�r{Zpfullmem�_fieldsr�r�Zpmemr�r$r��
_TOTAL_PHYMEMrZ�total�float)r�ZmemtypeZvalid_typesr�ZfunZmetricsr�Ztotal_phymemrlrlrp�memory_percent~s*
�
��
��zProcess.memory_percent�memory_mapsTc	s�|j��}|r�i�|D]P}|d}|dd�}ztdd��||��|<Wqtyd|�|<Yq0qtj���fdd��D�Stj��fdd�|D�SdS)	a�Return process' mapped memory regions as a list of namedtuples
            whose fields are variable depending on the platform.

            If *grouped* is True the mapped regions with the same 'path'
            are grouped together and the different memory fields are summed.

            If *grouped* is False every mapped region is shown as a single
            entity and the namedtuple will also include the mapped region's
            address space ('addr') and permission set ('perms').
            ��NcSs||Sr�rl)rx�yrlrlrp�<lambda>�rrz%Process.memory_maps.<locals>.<lambda>cs g|]}�|g�|�R��qSrlrl)rnr���d�ntrlrprq�rrz'Process.memory_maps.<locals>.<listcomp>csg|]}�|��qSrlrlrw)r2rlrprq�rr)r�r+r�r�r{Z
pmmap_groupedZ	pmmap_ext)r�Zgrouped�itZtuplr��numsrlr0rpr+�s
zProcess.memory_mapscCs
|j��S)z�Return files opened by process as a list of
        (path, fd) namedtuples including the absolute file name
        and file descriptor number.
        )r��
open_filesr�rlrlrpr5�szProcess.open_files�inetcCs|j�|�S)aTReturn socket connections opened by process as a list of
        (fd, family, type, laddr, raddr, status) namedtuples.
        The *kind* parameter filters for connections that match the
        following criteria:

        +------------+----------------------------------------------------+
        | Kind Value | Connections using                                  |
        +------------+----------------------------------------------------+
        | inet       | IPv4 and IPv6                                      |
        | inet4      | IPv4                                               |
        | inet6      | IPv6                                               |
        | tcp        | TCP                                                |
        | tcp4       | TCP over IPv4                                      |
        | tcp6       | TCP over IPv6                                      |
        | udp        | UDP                                                |
        | udp4       | UDP over IPv4                                      |
        | udp6       | UDP over IPv6                                      |
        | unix       | UNIX socket (both UDP and TCP protocols)           |
        | all        | the sum of all the possible families and protocols |
        +------------+----------------------------------------------------+
        )r�rb�r��kindrlrlrprb�szProcess.net_connectionsrbcCs|j|d�S)N�r8)rbr7rlrlrp�connections�szProcess.connectionscCs�|jdkrJ|j��|��|jdkr2d}t|��zt�|j|�Wnfty�trtt|j�rtt|j|j	|j
��nd|_t|j|j	��Yn t
y�t|j|j	��Yn0dS)Nrz�preventing sending signal to process with PID 0 as it would affect every process in the process group of the calling process (os.getpid()) instead of PID 0T)r~r�r�r��killr7rrVr1r�r�r�r/r6r-�r��sigr�rlrlrp�_send_signal�s
�zProcess._send_signalcCsPtr|�|�n<|��|tjkr@|��s@d}t|j|j|d��|j	�
|�dS)z�Send a signal *sig* to process pre-emptively checking
        whether PID has been reused (see signal module constants) .
        On Windows only SIGTERM is valid and is treated as an alias
        for kill().
        zprocess no longer existsr�N)rr>r��signal�SIGTERMr�r/r~r�r��send_signalr<rlrlrprA�szProcess.send_signalcCs(tr|�tj�n|��|j��dS)z�Suspend process execution with SIGSTOP pre-emptively checking
        whether PID has been reused.
        On Windows this has the effect of suspending all process threads.
        N)rr>r?�SIGSTOPr�r��suspendr�rlrlrprC
szProcess.suspendcCs(tr|�tj�n|��|j��dS)z�Resume process execution with SIGCONT pre-emptively checking
        whether PID has been reused.
        On Windows this has the effect of resuming all process threads.
        N)rr>r?�SIGCONTr�r��resumer�rlrlrprEszProcess.resumecCs(tr|�tj�n|��|j��dS)z�Terminate the process with SIGTERM pre-emptively checking
        whether PID has been reused.
        On Windows this is an alias for kill().
        N)rr>r?r@r�r�r;r�rlrlrp�	terminate#szProcess.terminatecCs(tr|�tj�n|��|j��dS)zjKill the current process with SIGKILL pre-emptively checking
        whether PID has been reused.
        N)rr>r?�SIGKILLr�r�r;r�rlrlrpr;.szProcess.killcCs@|dur|dksd}t|��|jtur,|jS|j�|�|_|jS)a�Wait for process to terminate and, if process is a children
        of os.getpid(), also return its exit code, else None.
        On Windows there's no such limitation (exit code is always
        returned).

        If the process is already terminated immediately return None
        instead of raising NoSuchProcess.

        If *timeout* (in seconds) is specified and process is still
        alive raise TimeoutExpired.

        To wait for multiple Process(es) use psutil.wait_procs().
        Nrz"timeout must be a positive integer)r�r�r�r��wait)r��timeoutr�rlrlrprH8s
zProcess.wait)N)F)NN)N)NN)N)N)F)N)r%)T)r6)r6)N)Gr�r��__qualname__�__doc__r�r�r�r��__repr__r�r�r�r��propertyr~�
contextlib�contextmanagerr�r�r�r�r�r3r|r�r�r�r�r�r�r�r�rr�r�r�r�r�r{rTr�r�rjrrrr,r	r
rrrr]r\r�rZdeprecated_methodr#r$r*r+r5rbr:r>rArCrErFr;rHrlrlrlrprT"s�

3

B
/
*	






F
]






$



rTcCs"g|]}|�d�s|dvr|�qS)�_>r�r�r:rjrEr#r�r�rArHrr�rCr;rF)r�rwrlrlrprqRs�csJeZdZdZdd�Zdd�Zdd�Zdd	�Zd
d�Zd�fd
d�	Z	�Z
S)rUaSame as subprocess.Popen, but in addition it provides all
    psutil.Process methods in a single class.
    For the following methods which are common to both classes, psutil
    implementation takes precedence:

    * send_signal()
    * terminate()
    * kill()

    This is done in order to avoid killing another process in case its
    PID has been reused, fixing BPO-6973.

      >>> import psutil
      >>> from subprocess import PIPE
      >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE)
      >>> p.name()
      'python'
      >>> p.uids()
      user(real=1000, effective=1000, saved=1000)
      >>> p.username()
      'giampaolo'
      >>> p.communicate()
      ('hi', None)
      >>> p.terminate()
      >>> p.wait(timeout=2)
      0
      >>>
    cOs(tj|i|��|_|j|jjdd�dS)NT)r�)�
subprocessrU�_Popen__subprocr�r~�r��args�kwargsrlrlrpr�|szPopen.__init__cCstttt�ttj���Sr�)rr��dirrUrQr�rlrlrp�__dir__�sz
Popen.__dir__cCst|jd�r|j��|S)N�	__enter__)r�rRrXr�rlrlrprX�s
zPopen.__enter__cOsjt|jd�r|jj|i|��S|jr.|j��|jr>|j��z|jrP|j��W|��n
|��0dS)N�__exit__)r�rRrY�stdout�close�stderr�stdinrHrSrlrlrprY�s

zPopen.__exit__cCsfzt�||�WSty`zt�|j|�WYStyZd|jj|f}t|��Yn0Yn0dS)Nz!%s instance has no attribute '%s')�object�__getattribute__�AttributeErrorrRr�r�)r�r�r�rlrlrpr_�s�zPopen.__getattribute__Ncs0|jjdur|jjStt|��|�}||j_|Sr�)rR�
returncode�superrUrH)r�rIr}�r�rlrprH�s
z
Popen.wait)N)r�r�rJrKr�rWrXrYr_rH�
__classcell__rlrlrcrprU^s
rUcCstt���}|da|S)z&Return a list of current running PIDs.r)rr{rWr��r}rlrlrprW�srWcCs0|dkrdS|dkr"tr"|t�vSt�|�SdS)z�Return True if given PID exists in the current process list.
    This is faster than doing "pid in psutil.pids()" and
    should be preferred.
    rFN)rrWr{rV�r~rlrlrprV�s

rVc	#s�fdd�}�fdd�}t���tt��}t����}||}||}|D]}||�qJtrzt��}td|�||�qXz�tt	��
��t	t�|��
���}	|	D]V\}}
z2|
dur�||�}
|dur�|
j
||d�|
_|
VWq�ty�||�Yq�0q�W�an�a0dS)a�Return a generator yielding a Process instance for all
    running processes.

    Every new Process instance is only created once and then cached
    into an internal table which is updated every time this is used.
    Cache can optionally be cleared via `process_iter.clear_cache()`.

    The sorting order in which processes are yielded is based on
    their PIDs.

    *attrs* and *ad_value* have the same meaning as in
    Process.as_dict(). If *attrs* is specified as_dict() is called
    and the resulting dict is stored as a 'info' attribute attached
    to returned Process instance.
    If *attrs* is an empty list it will retrieve all process info
    (slow).
    cst|�}|�|j<|Sr�)rTr~)r~r��Zpmaprlrpr��s
zprocess_iter.<locals>.addcs��|d�dSr�)rrfrgrlrp�remove�szprocess_iter.<locals>.removez-refreshing Process instance for reused PID %sN)r�r�)�_pmap�copyr�rW�keysr�rr2rr�r��dict�fromkeysr�r�r/)r�r�r�rh�a�bZnew_pidsZ	gone_pidsr~r�r�rlrgrprX�s2


"
rXcCst��Sr�)ri�clearrlrlrlrpr/	rrr/z$Clear process_iter() internal cache.c	s��fdd�}|dur.|dks.d|}t|��t��t|�}�dur\t��s\d�}t|��|durnt�|}|r�|dur�|dkr�q�|D]J}dt|�}|dur�t|t�|�}|dkr�q�|||�q�|||�q�|�}qn|r�|D]}||d�q�|�}t��t|�fS)a,Convenience function which waits for a list of processes to
    terminate.

    Return a (gone, alive) tuple indicating which processes
    are gone and which ones are still alive.

    The gone ones will have a new *returncode* attribute indicating
    process exit status (may be None).

    *callback* is a function which gets called every time a process
    terminates (a Process instance is passed as callback argument).

    Function will return as soon as all processes terminate or when
    *timeout* occurs.
    Differently from Process.wait() it will not raise TimeoutExpired if
    *timeout* occurs.

    Typical use case is:

     - send SIGTERM to a list of processes
     - give them some time to terminate
     - send SIGKILL to those ones which are still alive

    Example:

    >>> def on_terminate(proc):
    ...     print("process {} terminated".format(proc))
    ...
    >>> for p in procs:
    ...    p.terminate()
    ...
    >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate)
    >>> for p in alive:
    ...     p.kill()
    cshz|j|d�}Wn"ty"YnBty2Yn20|dusD|��sd||_��|��durd�|�dS)N)rI)rHr0�_SubprocessTimeoutExpiredr�rar�)r�rIra��callback�gonerlrp�
check_gone2s
zwait_procs.<locals>.check_goneNrz*timeout must be a positive integer, got %szcallback %r is not a callableg�?)r�r��callabler�rr��minr�)	ZprocsrIrsrur��alive�deadliner�Zmax_timeoutrlrrrprY
s8%

rYTcCs.|rt��}nt��}|dur*|dkr*d}|S)azReturn the number of logical CPUs in the system (same as
    os.cpu_count() in Python 3.4).

    If *logical* is False return the number of physical cores only
    (e.g. hyper thread CPUs are excluded).

    Return None if undetermined.

    The return value is cached after first call.
    If desired cache can be cleared like this:

    >>> psutil.cpu_count.cache_clear()
    Nr)r{Zcpu_count_logicalZcpu_count_cores)�logicalr}rlrlrpr_os
r_FcCs|st��St��SdS)a�Return system-wide CPU times as a namedtuple.
    Every CPU time represents the seconds the CPU has spent in the
    given mode. The namedtuple's fields availability varies depending on the
    platform:

     - user
     - system
     - idle
     - nice (UNIX)
     - iowait (Linux)
     - irq (Linux, FreeBSD)
     - softirq (Linux)
     - steal (Linux >= 2.6.11)
     - guest (Linux >= 2.6.24)
     - guest_nice (Linux >= 3.2.0)

    When *percpu* is True return a list of namedtuples for each CPU.
    First element of the list refers to first CPU, second element
    to second CPU and so on.
    The order of the list is consistent across calls.
    N)r{r\Z
per_cpu_timesrrlrlrpr\�sr\rcCs0t|�}tr,|t|dd�8}|t|dd�8}|S)zWGiven a cpu_time() ntuple calculates the total CPU time
    (including idle time).
    ZguestrZ
guest_nice)�sumrr�)�timesZtotrlrlrp�
_cpu_tot_time�s
	r}cCs&t|�}||j8}|t|dd�8}|S)zlGiven a cpu_time() ntuple calculates the busy CPU time.
    We do so by subtracting all idle CPU times.
    Ziowaitr)r}�idler�)r|�busyrlrlrp�_cpu_busy_time�s
r�cCs\|j|jksJ||f��g}tjjD],}t||�t||�}td|�}|�|�q$tj|�S)Nr)r&r{�	scputimesr��maxr�)�t1�t2Zfield_deltas�field�field_deltarlrlrp�_cpu_times_deltas�s
r�c
Cs�t��j}|duo|dk}|dur:|dkr:d|}t|��dd�}|s�|r\t�}t�|�nt�|�pjt�}t�t|<||t|�Sg}|r�tdd�}t�|�nt	�|�p�tdd�}tdd�t	|<t
|t	|�D]\}}	|�|||	��q�|SdS)	a�Return a float representing the current system-wide CPU
    utilization as a percentage.

    When *interval* is > 0.0 compares system CPU times elapsed before
    and after the interval (blocking).

    When *interval* is 0.0 or None compares system CPU times elapsed
    since last call or module import, returning immediately (non
    blocking). That means the first time this is called it will
    return a meaningless 0.0 value which you should ignore.
    In this case is recommended for accuracy that this function be
    called with at least 0.1 seconds between calls.

    When *percpu* is True returns a list of floats representing the
    utilization as a percentage for each CPU.
    First element of the list refers to first CPU, second element
    to second CPU and so on.
    The order of the list is consistent across calls.

    Examples:

      >>> # blocking, system-wide
      >>> psutil.cpu_percent(interval=1)
      2.0
      >>>
      >>> # blocking, per-cpu
      >>> psutil.cpu_percent(interval=1, percpu=True)
      [2.0, 1.0]
      >>>
      >>> # non-blocking (percentage since last call)
      >>> psutil.cpu_percent(interval=None)
      2.9
      >>>
    NrrrcSsNt||�}t|�}t|�}z||d}Wnty>YdS0t|d�SdS)Nrrr)r�r}r�rr)r�r��times_delta�	all_deltaZ
busy_deltaZ	busy_percrlrlrp�	calculates
zcpu_percent.<locals>.calculateTr)r��current_thread�identr�r\r�r�_last_cpu_times�get�_last_per_cpu_times�zipr��
r r�tidr!r�r�r�r}Ztot1r�rlrlrpr]�s,#



r]c
Cs�t��j}|duo|dk}|dur:|dkr:d|}t|��dd�}|s�|r\t�}t�|�nt�|�pjt�}t�t|<||t|�Sg}|r�tdd�}t�|�nt	�|�p�tdd�}tdd�t	|<t
|t	|�D]\}}	|�|||	��q�|SdS)	a�Same as cpu_percent() but provides utilization percentages
    for each specific CPU time as is returned by cpu_times().
    For instance, on Linux we'll get:

      >>> cpu_times_percent()
      cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0,
                 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
      >>>

    *interval* and *percpu* arguments have the same meaning as in
    cpu_percent().
    NrrrcSsdg}t||�}t|�}dtd|�}|D]0}||}t|d�}ttd|�d�}|�|�q(tj|�S)NgY@rr)r�r}r�rrwr�r{r�)r�r�r4r�r�Zscaler�Z
field_percrlrlrpr�Ns

z$cpu_times_percent.<locals>.calculateTr)r�r�r�r�r\r�r�_last_cpu_times_2r��_last_per_cpu_times_2r�r�r�rlrlrpr^;s,


r^cCst��S)zReturn CPU statistics.)r{r`rlrlrlrpr`vsr`�cpu_freqcCs�t��}|r|Stt|��}|dkr(dS|dkr8|dSd\}}}d}|D]6}||j7}trl|jdurld}qJ||j7}||j7}qJ||}|r�d}	}
n||}	||}
t�	||	|
�SdS)a:Return CPU frequency as a namedtuple including current,
        min and max frequency expressed in Mhz.

        If *percpu* is True and the system supports per-cpu frequency
        retrieval (Linux only) a list of frequencies is returned for
        each CPU. If not a list with one element is returned.
        rNr)rrrFT)
r{r�r)r��currentrrwr�rZscpufreq)rr}rZcurrsZminsZmaxsZset_none�cpur�Zmin_Zmax_rlrlrpr�}s.



�
getloadavgcCst��}|ja|S)a�Return statistics about system memory usage as a namedtuple
    including the following fields, expressed in bytes:

     - total:
       total physical memory available.

     - available:
       the memory that can be given instantly to processes without the
       system going into swap.
       This is calculated by summing different memory values depending
       on the platform and it is supposed to be used to monitor actual
       memory usage in a cross platform fashion.

     - percent:
       the percentage usage calculated as (total - available) / total * 100

     - used:
        memory used, calculated differently depending on the platform and
        designed for informational purposes only:
        macOS: active + wired
        BSD: active + wired + cached
        Linux: total - free

     - free:
       memory not being used at all (zeroed) that is readily available;
       note that this doesn't reflect the actual memory available
       (use 'available' instead)

    Platform-specific fields:

     - active (UNIX):
       memory currently in use or very recently used, and so it is in RAM.

     - inactive (UNIX):
       memory that is marked as not used.

     - buffers (BSD, Linux):
       cache for things like file system metadata.

     - cached (BSD, macOS):
       cache for various things.

     - wired (macOS, BSD):
       memory that is marked to always stay in RAM. It is never moved to disk.

     - shared (BSD):
       memory that may be simultaneously accessed by multiple processes.

    The sum of 'used' and 'available' does not necessarily equal total.
    On Windows 'available' and 'free' are the same.
    )r{rZr(r'rerlrlrprZ�s5rZcCst��S)a�Return system swap memory statistics as a namedtuple including
    the following fields:

     - total:   total swap memory in bytes
     - used:    used swap memory in bytes
     - free:    free swap memory in bytes
     - percent: the percentage usage
     - sin:     no. of bytes the system has swapped in from disk (cumulative)
     - sout:    no. of bytes the system has swapped out from disk (cumulative)

    'sin' and 'sout' on Windows are meaningless and always set to 0.
    )r{r[rlrlrlrpr[�s
r[cCs
t�|�S)z�Return disk usage statistics about the given *path* as a
    namedtuple including total, used and free space expressed in bytes
    plus the percentage usage.
    )r{rg)r�rlrlrprgsrgcCs
t�|�S)a3Return mounted partitions as a list of
    (device, mountpoint, fstype, opts) namedtuple.
    'opts' field is a raw string separated by commas indicating mount
    options which may vary depending on the platform.

    If *all* parameter is False return physical devices only and ignore
    all others.
    )r{rf)�allrlrlrprfs	rfcCs�trt|d�ni}tjfi|��}|s2|r.iSdS|r@t|d�}ttdtj�}|rt|��D]\}}||�||<qZ|S|dd�t	|�
��D��SdS)a�Return system disk I/O statistics as a namedtuple including
    the following fields:

     - read_count:  number of reads
     - write_count: number of writes
     - read_bytes:  number of bytes read
     - write_bytes: number of bytes written
     - read_time:   time spent reading from disk (in ms)
     - write_time:  time spent writing to disk (in ms)

    Platform specific:

     - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms)
     - read_merged_count (Linux): number of merged reads
     - write_merged_count (Linux): number of merged writes

    If *perdisk* is True return the same information for every
    physical disk installed on the system as a dictionary
    with partition names as the keys and the namedtuple
    described above as the values.

    If *nowrap* is True it detects and adjust the numbers which overflow
    and wrap (restart from 0) and add "old value" to "new value" so that
    the returned numbers will always be increasing or remain the same,
    but never decrease.
    "disk_io_counters.cache_clear()" can be used to invalidate the
    cache.

    On recent Windows versions 'diskperf -y' command may need to be
    executed first otherwise this function won't find any disk.
    )�perdiskN�psutil.disk_io_counters�sdiskiocss|]}t|�VqdSr��r{rwrlrlrp�	<genexpr>Hrrz#disk_io_counters.<locals>.<genexpr>)rrlr{re�
_wrap_numbersr�rr�r�r��values)r��nowraprU�rawdictr2Zdisk�fieldsrlrlrpres 
rer�zClears nowrap argument cachecCsnt��}|s|riSdS|r&t|d�}|rN|��D]\}}tj|�||<q2|Stjdd�t|���D��SdS)acReturn network I/O statistics as a namedtuple including
    the following fields:

     - bytes_sent:   number of bytes sent
     - bytes_recv:   number of bytes received
     - packets_sent: number of packets sent
     - packets_recv: number of packets received
     - errin:        total number of errors while receiving
     - errout:       total number of errors while sending
     - dropin:       total number of incoming packets which were dropped
     - dropout:      total number of outgoing packets which were dropped
                     (always 0 on macOS and BSD)

    If *pernic* is True return the same information for every
    network interface installed on the system as a dictionary
    with network interface names as the keys and the namedtuple
    described above as the values.

    If *nowrap* is True it detects and adjust the numbers which overflow
    and wrap (restart from 0) and add "old value" to "new value" so that
    the returned numbers will always be increasing or remain the same,
    but never decrease.
    "net_io_counters.cache_clear()" can be used to invalidate the
    cache.
    N�psutil.net_io_counterscSsg|]}t|��qSrlr�rwrlrlrprqzrrz#net_io_counters.<locals>.<listcomp>)r{rar�r�rZsnetior�r�)Zpernicr�r�Znicr�rlrlrpraVs
rar�r6cCs
t�|�S)a�Return system-wide socket connections as a list of
    (fd, family, type, laddr, raddr, status, pid) namedtuples.
    In case of limited privileges 'fd' and 'pid' may be set to -1
    and None respectively.
    The *kind* parameter filters for connections that fit the
    following criteria:

    +------------+----------------------------------------------------+
    | Kind Value | Connections using                                  |
    +------------+----------------------------------------------------+
    | inet       | IPv4 and IPv6                                      |
    | inet4      | IPv4                                               |
    | inet6      | IPv6                                               |
    | tcp        | TCP                                                |
    | tcp4       | TCP over IPv4                                      |
    | tcp6       | TCP over IPv6                                      |
    | udp        | UDP                                                |
    | udp4       | UDP over IPv4                                      |
    | udp6       | UDP over IPv6                                      |
    | unix       | UNIX socket (both UDP and TCP protocols)           |
    | all        | the sum of all the possible families and protocols |
    +------------+----------------------------------------------------+

    On macOS this function requires root privileges.
    )r{rbr9rlrlrprb�srbc
Cs�t}|rddl}t��}|jdd�d�t�t�}|D]�\}}}}}}	|r�z|�|�}Wn@t	y�t
rz|dkrztj}nttd�r�|tjkr�tj}Yn0|tjkr�t
r�dnd	}
|�|
�d
kr�|d|
7}q�||�t�|||||	��q6t|�S)a*Return the addresses associated to each NIC (network interface
    card) installed on the system as a dictionary whose keys are the
    NIC names and value is a list of namedtuples for each address
    assigned to the NIC. Each namedtuple includes 5 fields:

     - family: can be either socket.AF_INET, socket.AF_INET6 or
               psutil.AF_LINK, which refers to a MAC address.
     - address: is the primary address and it is always set.
     - netmask: and 'broadcast' and 'ptp' may be None.
     - ptp: stands for "point to point" and references the
            destination address on a point to point interface
            (typically a VPN).
     - broadcast: and *ptp* are mutually exclusive.

    Note: you can have more than one address of the same family
    associated with each interface.
    rNcSs|dS)Nrrl)rxrlrlrpr/�rrznet_if_addrs.<locals>.<lambda>)�key���rS�:�-�z%s00)r��socketr{rc�sortr�r
r��
AddressFamilyr�r,rSr�r�countr�rZsnicaddrrl)Z	has_enumsr�Zrawlistr}r��fam�addr�mask�	broadcastZptp�	separatorrlrlrprc�s0
��
rccCst��S)aReturn information about each NIC (network interface card)
    installed on the system as a dictionary whose keys are the
    NIC names and value is a namedtuple with the following fields:

     - isup: whether the interface is up (bool)
     - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or
               NIC_DUPLEX_UNKNOWN
     - speed: the NIC speed expressed in mega bits (MB); if it can't
              be determined (e.g. 'localhost') it will be set to 0.
     - mtu: the maximum transmission unit expressed in bytes.
    )r{rdrlrlrlrprd�srd�sensors_temperaturesc
	s��fdd�}t�t�}t��}|��D]l\}}|r&|�d�\}}}}	||�}||�}||	�}	|rj|	sj|}	n|	rv|sv|	}||�t�	||||	��q.q&t
|�S)a<Return hardware temperatures. Each entry is a namedtuple
        representing a certain hardware sensor (it may be a CPU, an
        hard disk or something else, depending on the OS and its
        configuration).
        All temperatures are expressed in celsius unless *fahrenheit*
        is set to True.
        cs(|dur$�r t|�dddS|SdS)N�	r�� )r))�n��
fahrenheitrlrp�convert�sz%sensors_temperatures.<locals>.convertr)r�r
r�r{r�r�rr�rZshwtemprl)
r�r�r}r�r�r��labelr��high�criticalrlr�rpr��s"	
��sensors_fanscCst��S)z�Return fans speed. Each entry is a namedtuple
        representing a certain hardware sensor.
        All speed are expressed in RPM (rounds per minute).
        )r{r�rlrlrlrpr�	s�sensors_batterycCst��S)a�Return battery information. If no battery is installed
        returns None.

         - percent: battery power left as a percentage.
         - secsleft: a rough approximation of how many seconds are left
                     before the battery runs out of power. May be
                     POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED.
         - power_plugged: True if the AC power cable is connected.
        )r{r�rlrlrlrpr�	s
cCst��S)zAReturn the system boot time expressed in seconds since the epoch.)r{rirlrlrlrpri2	sricCst��S)a�Return users currently connected on the system as a list of
    namedtuples including the following fields.

     - user: the name of the user
     - terminal: the tty or pseudo-tty associated with the user, if any.
     - host: the host name associated with the entry, if any.
     - started: the creation time as a floating point number expressed in
       seconds since the epoch.
    )r{rhrlrlrlrprh9	s
rhcCst��S)zjReturn a generator yielding a WindowsService instance for all
        Windows services installed.
        )r{�win_service_iterrlrlrlrpr�M	sr�cCs
t�|�S)zjGet a Windows service by *name*.
        Raise NoSuchProcess if no service with such name exists.
        )r{�win_service_get)r�rlrlrpr�S	sr�cCs(ddl}t|�|j_tj�t|��dS)zZEnable or disable PSUTIL_DEBUG option, which prints debugging
    messages to stderr.
    rN)Zpsutil._common�boolrZPSUTIL_DEBUGr{r��	set_debug)r�Zpsutilrlrlrp�
_set_debug]	sr�cCs@ddlm}ddlm}tj��}d}gd�}t|d�t|dd�D�]�}|j	dr�tj�
|j	d�}|��|kr�|�d	�}q�|�d
�}nd}|j	dr�t�d
t�
t|j	d���}nd}|j	dp�d}|s�tr�z|��d}Wnty�Yn0|�rt�rd|v�r|�d�d}|dd�}|j	ddu�rF||j	dj�nd}	|j	ddu�rj||j	dj�nd}
|j	ddu�r�t|j	dd�nd}|j	d�r�t|j	d�nd}|j	d�r�d�|j	d�}
n
|j	d}
|j	d�r�|j	ddd�nd}||dd�|j	d||	|
|||||
f
}t|d|�d��qFdS)Nr)�bytes2human)�get_terminal_sizez)%-10s %5s %5s %7s %7s %5s %6s %6s %6s  %s)
r~r*r�r�r\r�r�r�r�r�)
�USERZPIDz%MEMZVSZZRSSZNICEZSTATUS�STARTZTIMEZCMDLINE)r�r�z%H:%Mz%b%drur\z%M:%Sr�r�\r�r�r*r�r�� r�r�r��
r~)rr��_compatr�r��date�today�printrXr�r�r�r��	localtimer{rr�r.r,�split�vmsr%rrmr�)r�r�Z	today_dayZtemplr��pr�Zcputimerr�r%Zmempr�r�r��linerlrlrp�testg	sr


�������
"
�r�r-�__main__)NN)NN)T)F)NF)NF)F)F)FT)FT)r6)F)�rK�
__future__rr�rNr��	functoolsr�r?rQ�sysr�r�r�r�rurrrrrr	r
rrr
rrrrrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r�r�r5r�r6r7r8rqr9ZPROCFS_PATHr:r{r;r<r=r>r?Z_psutil_windowsr@rArBrCrDrErFrGrHrIrJrKrLrMrNrOrPr��platform�__all__�extendZ__extra__all__r�rTrk�globalsZ_globalsr�rVr��isupperr�r�rS�
__author__rRr�r�rQrr'r�r^r�rm�replacer�ryr�r�r�rvrzrr�r�r�rUrWrVrir�rX�cache_clearrYr_r\r�r�r��	Exceptionr�r}r�r�r]rjr�r�r^r`r�r�rZr[rgrfre�partialrarbrcrdr�r�r�rirhr�r�r�r�rorxr�rlrlrlrp�<module>s�
1��
��

7�
W
6

b


�

N
;
(

;

/�
'�
2
"




J
PKok\E��55(psutil/__pycache__/_psosx.cpython-39.pycnu�[���a

��?h?�@s�dZddlZddlZddlZddlmZddlmZddlmZddlm	Z
ddlmZdd	lm
Z
dd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZgZe��ZejZe
jeje
jej e
j!ej"e
j#ej$e
j%ej&e
j'ej(e
j)ej*e
j+ej,e
j-ej.e
j/ej0e
j1ej2e
j3ej4iZ5e
j6ej7e
j8ej9e
j:ej;e
j<ej=e
j>ej?iZ@eAdddddddddddd�ZBeAddddddddd�ZCedgd ��ZDed!gd"��ZEed#gd$��ZFed%eFjGd&�ZHd'd(�ZId)d*�ZJd+d,�ZKd-d.�ZLd/d0�ZMd1d2�ZNd3d4�ZOd5d6�ZPejQZQe
jRZRdMd8d9�ZSd:d;�ZTe
jUZUejVZVdNd=d>�ZWd?d@�ZXdAdB�ZYdCdD�ZZdEdF�Z[ej\Z\dGdH�Z]dIdJ�Z^GdKdL�dL�Z_dS)OzmacOS platform implementation.�N)�
namedtuple�)�_common)�_psposix)�_psutil_osx)�
_psutil_posix)�AccessDenied)�
NoSuchProcess)�
ZombieProcess)�	conn_tmap)�conn_to_ntuple)�
isfile_strict)�memoize_when_activated)�parse_environ_block)�
usage_percent)�PermissionError)�ProcessLookupError��������	�
)�ppid�ruid�euid�suid�rgid�egid�sgid�ttynr�ctime�status�name)�cpuutime�cpustime�rss�vms�pfaults�pageins�
numthreads�volctxsw�	scputimes��user�nice�system�idle�svmem)�total�	available�percent�used�free�active�inactive�wired�pmem)r)r*r+r,�pfullmem)�ussc		CsTt��\}}}}}}||}||}||8}t|||dd�}t||||||||�S)z&System virtual memory as a namedtuple.r�Zround_)�cextZvirtual_memrr5)	r6r;r<r=r:ZspeculativeZavailr9r8�rC�9/usr/local/lib64/python3.9/site-packages/psutil/_psosx.py�virtual_memoryqsrEcCs4t��\}}}}}t||dd�}t�||||||�S)z=Swap system memory as a (total, used, free, sin, sout) tuple.rrA)rBZswap_memrrZsswap)r6r9r:�sinZsoutr8rCrCrD�swap_memory�srGcCst��\}}}}t||||�S)z(Return system CPU times as a namedtuple.)rB�	cpu_timesr/r0rCrCrDrH�srHcCs:g}t��D](}|\}}}}t||||�}|�|�q|S)z)Return system CPU times as a named tuple.)rB�
per_cpu_timesr/�append)�retZcpu_tr1r2r3r4�itemrCrCrDrI�srIcCst��S)z0Return the number of logical CPUs in the system.)rB�cpu_count_logicalrCrCrCrDrM�srMcCst��S)z-Return the number of CPU cores in the system.)rB�cpu_count_coresrCrCrCrDrN�srNcCs"t��\}}}}}t�||||�S�N)rB�	cpu_statsrZ	scpustats)Zctx_switchesZ
interruptsZsoft_interruptsZsyscallsZ_trapsrCrCrDrP�s
��rPcCst��\}}}t�|||�gS)z�Return CPU frequency.
    On macOS per-cpu frequency is not supported.
    Also, the returned frequency never changes, see:
    https://arstechnica.com/civis/viewtopic.php?f=19&t=465002.
    )rB�cpu_freqrZscpufreq)�currZmin_Zmax_rCrCrDrQ�srQFc	Csjg}t��}|D]T}|\}}}}|dkr,d}|sJtj�|�rtj�|�sJqt�||||�}|�|�q|S)z8Return mounted disk partitions as a list of namedtuples.�none�)	rB�disk_partitions�os�path�isabs�existsrZ	sdiskpartrJ)	�all�retlistZ
partitions�	partitionZdeviceZ
mountpointZfstype�opts�ntuplerCrCrDrU�srUcCsbzt��\}}}Wnty&YdS0|dk}|r<tj}n|dkrLtj}n|d}t�|||�S)zReturn battery information.Nr����<)rB�sensors_battery�NotImplementedErrorrZPOWER_TIME_UNLIMITEDZPOWER_TIME_UNKNOWNZsbattery)r8ZminsleftZ
power_pluggedZsecsleftrCrCrDra�sra�inetc	Csjg}t�D]Z}zt|��|�}Wnty6Yq
Yq
0|r
|D]"}t|�|g}|�tj|��q@q
|S)z System-wide network connections.)�pids�Process�net_connectionsr	�listrJrZsconn)�kindrK�pidZcons�crCrCrDrf�s

rfc
Cs�t���}i}|D]�}z&t�|�}t�|�}t�|�\}}Wn2tyn}z|jtjkrZ�WYd}~qd}~00t	t
d�r�t
�|�}d�|�}d|v}	t
�
|	||||�||<q|S)z)Get NIC stats (isup, duplex, speed, mtu).N�	NicDuplex�,�running)�net_io_counters�keys�
cext_posixZ
net_if_mtuZnet_if_flagsZnet_if_duplex_speed�OSError�errnoZENODEV�hasattrrrk�joinZ	snicstats)
�namesrKr&Zmtu�flagsZduplex�speed�errZoutput_flagsZisuprCrCrD�net_if_statss$






�
rycCst��S)z:The system boot time expressed in seconds since the epoch.)rB�	boot_timerCrCrCrDrz!srzc	Cs\g}t��}|D]F}|\}}}}}|dkr,q|s2qt�||p>d|pDd||�}|�|�q|S)z:Return currently connected users as a list of namedtuples.�~N)rB�usersrZsuserrJ)	r[�rawlistrLr1�tty�hostnameZtstampri�ntrCrCrDr|&sr|cCs`t��}d|vr\ztd���|�dd�Wn.ty>YntyZ|�dd�Yn0|S�Nr)rBrdre�create_time�insertr	r)ZlsrCrCrDrd:srdcCs8zt�|�td}|tjkWSty2YdS0dS)Nr%F)rB�proc_kinfo_oneshot�kinfo_proc_map�SZOMBrq)ri�strCrCrD�	is_zombieMs
r�cst����fdd��}|S)z`Decorator which translates bare OSError exceptions into
    NoSuchProcess and AccessDenied.
    cszz�|g|�Ri|��WStyVt|j�rDt|j|j|j��nt|j|j��Yn tytt|j|j��Yn0dSrO)	rr�rir
�_name�_ppidr	rr)�self�args�kwargs��funrCrD�wrapperZs
z wrap_exceptions.<locals>.wrapper)�	functools�wraps)r�r�rCr�rD�wrap_exceptionsUsr�c@sheZdZdZgd�Zdd�Zeedd���Zeedd���Z	d	d
�Z
dd�Zed
d��Zedd��Z
edd��Zedd��Zedd��Zedd��Zedd��Zedd��Zedd��Zedd ��Zed!d"��Zed#d$��Zed%d&��Zed'd(��Zed)d*��Zed+d,��Zed=d.d/��Zed0d1��Zed>d3d4��Zed5d6��Zed7d8��Z ed9d:��Z!ed;d<��Z"d2S)?rez1Wrapper class around underlying C implementation.)�_cacher�r�ricCs||_d|_d|_dSrO)rir�r�)r�rirCrCrD�__init__nszProcess.__init__cCs$t�|j�}t|�tt�ks J�|SrO)rBr�ri�lenr��r�rKrCrCrD�_get_kinfo_procsszProcess._get_kinfo_proccCs$t�|j�}t|�tt�ks J�|SrO)rBZproc_pidtaskinfo_oneshotrir��pidtaskinfo_mapr�rCrCrD�_get_pidtaskinfo{szProcess._get_pidtaskinfocCs|j�|�|j�|�dSrO)r�Zcache_activater��r�rCrCrD�
oneshot_enter�szProcess.oneshot_entercCs|j�|�|j�|�dSrO)r�Zcache_deactivater�r�rCrCrD�oneshot_exit�szProcess.oneshot_exitcCs(|��td}|dur|St�|j�S)Nr&)r�r�rBZ	proc_nameri)r�r&rCrCrDr&�szProcess.namecCst�|j�SrO)rBZproc_exerir�rCrCrD�exe�szProcess.execCst�|j�SrO)rBZproc_cmdlinerir�rCrCrD�cmdline�szProcess.cmdlinecCstt�|j��SrO)rrBZproc_environrir�rCrCrD�environ�szProcess.environcCs|��td|_|jS)Nr)r�r�r�r�rCrCrDr�szProcess.ppidcCst�|j�SrO)rBZproc_cwdrir�rCrCrD�cwd�szProcess.cwdcCs.|��}t�|td|td|td�S)Nrrr�r�rZpuidsr��r�ZrawtuplerCrCrD�uids�s


�zProcess.uidscCs.|��}t�|td|td|td�S)Nr r!r"r�r�rCrCrD�gids�s


�zProcess.gidscCs<|��td}t��}z
||WSty6YdS0dS)Nr#)r�r�rZget_terminal_map�KeyError)r�Ztty_nrZtmaprCrCrD�terminal�s
zProcess.terminalcCs6|��}t|td|td|td|td�S)Nr)r*r+r,)r�r>r�r�rCrCrD�memory_info�s



�zProcess.memory_infocCs"|��}t�|j�}t||f�SrO)r�rBZproc_memory_ussrir?)r�Z	basic_memr@rCrCrD�memory_full_info�szProcess.memory_full_infocCs(|��}t�|td|tddd�S)Nr'r(g)r�rZ	pcputimesr�r�rCrCrDrH�s

�zProcess.cpu_timescCs|��tdS)Nr$)r�r�r�rCrCrDr��szProcess.create_timecCs|��td}t�|d�S)Nr.r)r�r�rZpctxsw)r�ZvolrCrCrD�num_ctx_switches�szProcess.num_ctx_switchescCs|��tdS)Nr-)r�r�r�rCrCrD�num_threads�szProcess.num_threadscCsN|jdkrgSg}t�|j�}|D]&\}}t|�r"t�||�}|�|�q"|Sr�)rirBZproc_open_filesr
rZ	popenfilerJ)r��filesr}rW�fdr^rCrCrD�
open_files�s
zProcess.open_filesrcc	Cs�|tvr(td|d�dd�tD��f��t|\}}t�|j||�}g}|D]2}|\}}}	}
}}t|||	|
||t�}
|�|
�qL|S)Nz+invalid %r kind argument; choose between %sz, cSsg|]}t|��qSrC)�repr)�.0�xrCrCrD�
<listcomp>��z+Process.net_connections.<locals>.<listcomp>)	r�
ValueErrorrtrBZproc_net_connectionsrir�TCP_STATUSESrJ)r�rhZfamilies�typesr}rKrLr��fam�type�laddr�raddrr%r�rCrCrDrf�s ���zProcess.net_connectionscCs|jdkrdSt�|j�Sr�)rirBZproc_num_fdsr�rCrCrD�num_fds	s
zProcess.num_fdsNcCst�|j||j�SrO)rZwait_pidrir�)r��timeoutrCrCrD�waitszProcess.waitcCst�|j�SrO)rp�getpriorityrir�rCrCrD�nice_getszProcess.nice_getcCst�|j|�SrO)rp�setpriorityri)r��valuerCrCrD�nice_setszProcess.nice_setcCs|��td}t�|d�S)Nr%�?)r�r��
PROC_STATUSES�get)r��coderCrCrDr%szProcess.statuscCs<t�|j�}g}|D]"\}}}t�|||�}|�|�q|SrO)rBZproc_threadsrirZpthreadrJ)r�r}r[�	thread_id�utimeZstimer^rCrCrD�threads!szProcess.threads)rc)N)#�__name__�
__module__�__qualname__�__doc__�	__slots__r�r�rr�r�r�r�r&r�r�r�rr�r�r�r�r�r�rHr�r�r�r�rfr�r�r�r�r%r�rCrCrCrDreisr









	










re)F)rc)`r�rrr�rV�collectionsrrTrrrrBrrprr	r
rrr
rrrZ_compatrrZ__extra__all__ZgetpagesizeZPAGESIZEZAF_LINKZTCPS_ESTABLISHEDZCONN_ESTABLISHEDZ
TCPS_SYN_SENTZ
CONN_SYN_SENTZTCPS_SYN_RECEIVEDZ
CONN_SYN_RECVZTCPS_FIN_WAIT_1ZCONN_FIN_WAIT1ZTCPS_FIN_WAIT_2ZCONN_FIN_WAIT2ZTCPS_TIME_WAITZCONN_TIME_WAITZTCPS_CLOSEDZ
CONN_CLOSEZTCPS_CLOSE_WAITZCONN_CLOSE_WAITZ
TCPS_LAST_ACKZ
CONN_LAST_ACKZTCPS_LISTENZCONN_LISTENZTCPS_CLOSINGZCONN_CLOSINGZPSUTIL_CONN_NONEZ	CONN_NONEr�ZSIDLZSTATUS_IDLEZSRUNZSTATUS_RUNNINGZSSLEEPZSTATUS_SLEEPINGZSSTOPZSTATUS_STOPPEDr�Z
STATUS_ZOMBIEr��dictr�r�r/r5r>�_fieldsr?rErGrHrIrMrNrPrQ�
disk_usageZdisk_io_countersrUrarnZnet_if_addrsrfryrzr|rdZ
pid_existsr�r�rerCrCrCrD�<module>s������	
	

PKok\�DB�g[g[)psutil/__pycache__/_common.cpython-39.pycnu�[���a

��?h+t�
@shdZddlmZddlmZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlmZddl	mZddl	mZddl	mZzdd	l	mZWney�dZYn0zdd
l	mZWney�dZYn0ejddkZe�r
ddlZndZee�d��Ze�Zgd
�ZejdkZejdkZ ej!�"d�Z#ej!�"d�Z$e$Z%ej!�"d�Z&ej!�"d�Z'ej!�"d�Z(e&�p�e'�p�e(Z)ej!�"d�Z*ej!�"d�Z+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4d Z5d!Z6d"Z7d#Z8d$Z9d%Z:d&Z;d'Z<d(Z=d)Z>d*Z?d+Z@d,ZAd-ZBd.ZCd/ZDd0ZEedu�r&d1ZFd2ZGdZHn Gd3d4�d4ejI�ZJeK��LeJjM�edu�rZd5ZNd6ZOn Gd7d8�d8ejI�ZPeK��LePjM�e�Q�ZRe�s�d9ZSn0ze�T�ZSWn"eU�y�e�r�d:nd9ZSYn0ed;gd<��ZVed=gd>��ZWed?gd@��ZXedAgdB��ZYedCgdD��ZZedEgdF��Z[edGgdH��Z\edIgdJ��Z]edKgdL��Z^edMgdN��Z_edOgdP��Z`edQgdR��ZaedSgdT��ZbedUdVdWg�ZcedXgdY��ZdedZd[d\g�Zeed]gd^��Zfed_gd`��Zgedagd`��Zhedbgdc��Ziedddedfg�Zjedgdhdig�Zkedjgdk��Zledldmdng�Zmeeegeegfeegegfegegfeegegfegegfeegeegfegeegfegeegfdo�Znedu�r�en�Legegfegegfdp��edu�r�en�Ldqegeegfi�Gdrds�dseo�ZpGdtdu�duep�ZqGdvdw�dweq�ZrGdxdy�dyep�ZsGdzd{�d{ep�Zte�rBeuevew��r.evd|Zxn
eyevd|�Zxexd}�nd~d�Zzd�d�d��Z{d�d��Z|d�d��Z}d�d��Z~d�d��Ze|d�d���Z�d�d��Z�d�d��Z�d�d��Z�d�d�d��Z�d�d��Z�Gd�d��d��Z�d�d��Z�e��Z�e�j�e�_�e�j�e�_�d�Z�d�d��Z�d�d��Z�ee�fd�d��Z�efd�d��Z�d�d�d��Z�d�d��Z�e�r&d�d��Z�nd�d��Z�e|ej�fd�d���Z�d�d�d��Z�dd�ej�fd�d��Z�d�d��Z�dS)�z9Common objects shared by __init__.py and _ps*.py modules.�)�division)�print_functionN)�
namedtuple)�AF_INET)�
SOCK_DGRAM)�SOCK_STREAM)�AF_INET6)�AF_UNIX��PSUTIL_DEBUG)R�FREEBSD�BSD�LINUX�NETBSD�OPENBSD�MACOS�OSX�POSIX�SUNOS�WINDOWS�
CONN_CLOSE�CONN_CLOSE_WAIT�CONN_CLOSING�CONN_ESTABLISHED�CONN_FIN_WAIT1�CONN_FIN_WAIT2�
CONN_LAST_ACK�CONN_LISTEN�	CONN_NONE�
CONN_SYN_RECV�
CONN_SYN_SENT�CONN_TIME_WAIT�NIC_DUPLEX_FULL�NIC_DUPLEX_HALF�NIC_DUPLEX_UNKNOWN�STATUS_DEAD�STATUS_DISK_SLEEP�STATUS_IDLE�
STATUS_LOCKED�STATUS_RUNNING�STATUS_SLEEPING�STATUS_STOPPED�STATUS_SUSPENDED�STATUS_TRACING_STOP�STATUS_WAITING�STATUS_WAKE_KILL�
STATUS_WAKING�
STATUS_ZOMBIE�
STATUS_PARKED�ENCODING�
ENCODING_ERRSr�pconn�	pcputimes�pctxsw�pgids�pio�pionice�	popenfile�pthread�puids�sconn�	scpustats�sdiskio�	sdiskpart�
sdiskusage�snetio�snicaddr�	snicstats�sswap�suser�	conn_tmap�deprecated_method�
isfile_strict�memoize�parse_environ_block�path_exists_strict�
usage_percent�
supports_ipv6�sockfam_to_enum�socktype_to_enum�wrap_numbers�	open_text�open_binary�cat�bcat�bytes2human�conn_to_ntuple�debug�hilite�term_supports_colors�print_color�posix�nt�linux�darwin)ZfreebsdZmidnightbsdZopenbsdZnetbsd)�sunos�solaris�aix�runningZsleepingz
disk-sleep�stoppedztracing-stopZzombieZdeadz	wake-killZwaking�idle�lockedZwaitingZ	suspendedZparkedZESTABLISHEDZSYN_SENTZSYN_RECVZ	FIN_WAIT1Z	FIN_WAIT2Z	TIME_WAITZCLOSEZ
CLOSE_WAITZLAST_ACKZLISTENZCLOSING�NONE��c@seZdZdZdZdZdS)�	NicDuplexrirjrN)�__name__�
__module__�__qualname__r"r#r$�roro�:/usr/local/lib64/python3.9/site-packages/psutil/_common.pyrk�srk������c@seZdZdZdZdS)�BatteryTimerqrrN)rlrmrn�POWER_TIME_UNKNOWN�POWER_TIME_UNLIMITEDrorororprs�srs�replace�surrogateescaperF)�total�used�free�percent�sinZsoutrB)rxryrzr{r@)�
read_count�write_count�
read_bytes�write_bytesZ	read_timeZ
write_timerA)ZdeviceZ
mountpointZfstype�optsrC)Z
bytes_sentZ
bytes_recvZpackets_sentZpackets_recvZerrinZerroutZdropinZdropoutrG)�nameZterminal�host�started�pidr>)�fd�family�type�laddr�raddr�statusr�rD)r��address�netmask�	broadcastZptprE)ZisupZduplex�speedZmtu�flagsr?)Zctx_switchesZ
interruptsZsoft_interruptsZsyscalls�scpufreq)�current�min�max�shwtemp)�labelr��high�critical�sbattery)r{ZsecsleftZ
power_plugged�sfanr�r�r6)�user�system�
children_user�children_systemr;�pathr�r<)�idZ	user_timeZsystem_timer=)�realZ	effectiveZsavedr8r9)r}r~rr�r:Zioclass�valuer7Z	voluntaryZinvoluntaryr5)r�r�r�r�r�r��addr�ip�port)�allZtcpZtcp4ZudpZudp4ZinetZinet4Zinet6)Ztcp6Zudp6�unixc@s,eZdZdZdZdd�Zdd�Zdd�Zd	S)
�ErrorzQBase exception class. All other psutil exceptions inherit
    from this one.
    �psutilcCsHt��}|D]6}t||d�}|r*|||<q|dkr|dkr|||<q|S)Nr�r)�collections�OrderedDict�getattr)�self�attrs�infor�r�rororp�	_infodict$s

zError._infodictcCsP|�d�}|r,dd�dd�|��D��}nd}d�dd�t|dd	�|fD��S)
N)r��ppidr�z(%s)�, cSsg|]\}}d||f�qS�z%s=%rro��.0�k�vrororp�
<listcomp>3�z!Error.__str__.<locals>.<listcomp>� cSsg|]}|r|�qSroro)r��xrororpr�7r��msg�)r��join�itemsr��r�r��detailsrororp�__str__.s
�z
Error.__str__cCs2|�d�}d�dd�|��D��}d|jj|fS)N)r�r�r��secondsr�r�cSsg|]\}}d||f�qSr�ror�rororpr�<r�z"Error.__repr__.<locals>.<listcomp>z
psutil.%s(%s))r�r�r��	__class__rlr�rororp�__repr__9s
zError.__repr__N)rlrmrn�__doc__r�r�r�rorororpr�s

r�c@s&eZdZdZdZddd�Zdd�ZdS)	�
NoSuchProcesszXException raised when a process with a certain PID doesn't
    or no longer exists.
    r�NcCs$t�|�||_||_|pd|_dS)Nzprocess no longer exists�r��__init__r�r�r��r�r�r�r�rororpr�Gs
zNoSuchProcess.__init__cCs|j|j|j|jffS�N�r�r�r�r��r�rororp�
__reduce__MszNoSuchProcess.__reduce__)NN�rlrmrnr�r�r�rorororpr�@s
r�c@s&eZdZdZdZddd�Zdd�ZdS)	�
ZombieProcessa1Exception raised when querying a zombie process. This is
    raised on macOS, BSD and Solaris only, and not always: depending
    on the query the OS may be able to succeed anyway.
    On Linux all zombie processes are querable (hence this is never
    raised). Windows doesn't have zombie processes.
    r�NcCs$t�||||�||_|pd|_dS)Nz"PID still exists but it's a zombie)r�r�r�r�)r�r�r�r�r�rororpr�[szZombieProcess.__init__cCs|j|j|j|j|jffSr�)r�r�r�r�r�r�rororpr�`szZombieProcess.__reduce__)NNNr�rorororpr�Qs
r�c@s&eZdZdZdZddd�Zdd�ZdS)	�AccessDeniedz@Exception raised when permission to perform an action is denied.r�NcCs$t�|�||_||_|pd|_dS)Nr�r�r�rororpr�is
zAccessDenied.__init__cCs|j|j|j|jffSr�r�r�rororpr�oszAccessDenied.__reduce__)NNNr�rorororpr�ds
r�c@s&eZdZdZdZddd�Zdd�ZdS)	�TimeoutExpiredzWRaised on Process.wait(timeout) if timeout expires and process
    is still alive.
    r�NcCs*t�|�||_||_||_d||_dS)Nztimeout after %s seconds)r�r�r�r�r�r�)r�r�r�r�rororpr�zs

zTimeoutExpired.__init__cCs|j|j|j|jffSr�)r�r�r�r�r�rororpr��szTimeoutExpired.__reduce__)NNr�rorororpr�ss
r��execzvdef raise_from(value, from_value):
    try:
        raise value from from_value
    finally:
        value = None
    cCs|�dSr�ro)r��
from_valuerororp�
raise_from�sr�cCsDzt|�|d}Wnty(YdS0|dur<t||�}|SdS)z5Calculate percentage usage of 'used' against 'total'.�dgN)�float�ZeroDivisionError�round)ryrxZround_�retrororprN�s
rNcs2t�����fdd��}�fdd�}i�||_|S)a�A simple memoize decorator for functions supporting (hashable)
    positional arguments.
    It also provides a cache_clear() function for clearing the cache:

    >>> @memoize
    ... def foo()
    ...     return 1
        ...
    >>> foo()
    1
    >>> foo.cache_clear()
    >>>

    It supports:
     - functions
     - classes (acts as a @singleton)
     - staticmethods
     - classmethods

    It does NOT support:
     - methods
    c
s�|tt|����f}z
�|WSty~z�|i|��}�|<Wn.tyt}zt|d��WYd}~n
d}~00|YS0dSr�)�	frozenset�sortedr��KeyError�	Exceptionr�)�args�kwargs�keyr��err��cache�funrorp�wrapper�s
 zmemoize.<locals>.wrappercs���dS)zClear cache.N)�clearro)r�rorp�cache_clear�szmemoize.<locals>.cache_clear)�	functools�wrapsr�)r�r�r�ror�rprK�srKcs6t����fdd��}dd�}dd�}||_||_|S)a�A memoize decorator which is disabled by default. It can be
    activated and deactivated on request.
    For efficiency reasons it can be used only against class methods
    accepting no arguments.

    >>> class Foo:
    ...     @memoize
    ...     def foo()
    ...         print(1)
    ...
    >>> f = Foo()
    >>> # deactivated (default)
    >>> foo()
    1
    >>> foo()
    1
    >>>
    >>> # activated
    >>> foo.cache_activate(self)
    >>> foo()
    1
    >>> foo()
    >>> foo()
    >>>
    c
s�z|j�}Wn�ty^z�|�WYStyX}zt|d��WYd}~n
d}~00Ynpty�z�|�}Wn.ty�}zt|d��WYd}~n
d}~00z||j�<Wnty�Yn0Yn0|Sr�)�_cache�AttributeErrorr�r�r�)r�r�r��r�rorpr��s"$ z'memoize_when_activated.<locals>.wrappercSs
i|_dS)zsActivate cache. Expects a Process instance. Cache will be
        stored as a "_cache" instance attribute.
        N)r���procrororp�cache_activatesz.memoize_when_activated.<locals>.cache_activatecSs z|`WntyYn0dS)zDeactivate and clear cache.N)r�r�r�rororp�cache_deactivatesz0memoize_when_activated.<locals>.cache_deactivate)r�r�r�r�)r�r�r�r�ror�rp�memoize_when_activated�sr�c
CsZzt�|�}Wn:tyH}z"|jtjtjfvr2�WYd}~dSd}~00t�|j�SdS)z�Same as os.path.isfile() but does not swallow EACCES / EPERM
    exceptions, see:
    http://mail.python.org/pipermail/python-dev/2012-June/120787.html.
    NF)�os�stat�OSError�errno�EPERM�EACCES�S_ISREG�st_mode)r��str�rororprJsrJc
CsRzt�|�Wn:tyH}z"|jtjtjfvr2�WYd}~dSd}~00dSdS)z�Same as os.path.exists() but does not swallow EACCES / EPERM
    exceptions. See:
    http://mail.python.org/pipermail/python-dev/2012-June/120787.html.
    NFT)r�r�r�r�r�r�)r�r�rororprM-srMcCsvtjrtdurdSzHt�ttj�}t�|��|�d�Wd�n1sL0YWdStjypYdS0dS)z2Return True if IPv6 is supported on this platform.NF)z::1rT)�socket�has_ipv6rr�
contextlib�closing�bind�error)�sockrororprO<s(rOcCsvi}d}t}|�d|�}||kr"qr|�d||�}||krh|||�}||d|�}|r`|��}|||<|d}q|S)zCParse a C environ block of environment variables into a dictionary.r��=rj)r�find�upper)�datar��posZWINDOWS_Znext_posZ	equal_posr�r�rororprLJs
rLcCs4tdur|Szt�|�WSty.|YS0dS)z�Convert a numeric socket family value to an IntEnum member.
    If it's not a known member, return the numeric value itself.
    N)�enumr��
AddressFamily�
ValueError��numrororprPfsrPcCs4tdur|Szt�|�WSty.|YS0dS)zConvert a numeric socket type value to an IntEnum member.
    If it's not a known member, return the numeric value itself.
    N)r	r��
SocketKindrrrororprQssrQcCs�|tjtfvr&|rt|�}|r&t|�}|tjkrJ|ttfvrJ|�|t�}nt}t|�}t|�}|durxt	||||||�St
|||||||�SdS)z2Convert a raw connection tuple to a proper ntuple.N)r�rrr�r�getrrPrQr5r>)r��fam�type_r�r�r�Z
status_mapr�rororprX�srXcs�fdd�}|S)z�A decorator which can be used to mark a method as deprecated
    'replcement' is the method name which will be called instead.
    cs:d|j�f�|jdur�|_t�|���fdd��}|S)Nz8%s() is deprecated and will be removed; use %s() insteadcs$tj�tdd�t|��|i|��S)Nri)�category�
stacklevel)�warnings�warn�DeprecationWarningr�)r�r�r�)r��replacementrorp�inner�sz/deprecated_method.<locals>.outer.<locals>.inner)rlr�r�r�)r�r�r)r�rp�outer�s�
z deprecated_method.<locals>.outerro)rrrorrprI�srIc@sBeZdZdZdd�Zdd�Zdd�Zdd	�Zddd�Zd
d�Z	d
S)�_WrapNumberszNWatches numbers so that they don't overflow and wrap
    (reset to zero).
    cCs t��|_i|_i|_i|_dSr�)�	threading�Lock�lockr��	reminders�
reminder_keysr�rororpr��s
z_WrapNumbers.__init__cCsX||jvsJ�||jvsJ�||jvs*J�||j|<t�t�|j|<t�t�|j|<dSr�)r�rr r��defaultdict�int�set)r��
input_dictr�rororp�	_add_dict�s
z_WrapNumbers._add_dictcCs\|j|}t|���t|���}|D]0}|j||D]}|j||=q8|j||=q&dS)z�In case the number of keys changed between calls (e.g. a
        disk disappears) this removes the entry from self.reminders.
        N)r�r#�keysr r)r�r$r��old_dictZ	gone_keysZgone_key�remkeyrororp�_remove_dead_reminders�s
z#_WrapNumbers._remove_dead_remindersc
	Cs||jvr|�||�|S|�||�|j|}i}|D]�}||}z||}Wntyn|||<Yq8Yn0g}tt|��D]f}	||	}
||	}||	f}|
|kr�|j|||7<|j||�|�|�	|
|j||�q�t
|�||<q8||j|<|S)zlCache dict and sum numbers which overflow and wrap.
        Return an updated copy of `input_dict`.
        )r�r%r)r��range�lenrr �add�append�tuple)
r�r$r�r'Znew_dictr�Zinput_tupleZ	old_tuple�bits�iZinput_value�	old_valuer(rororp�run�s2



z_WrapNumbers.runNcCs||j�b|dur0|j��|j��|j��n*|j�|d�|j�|d�|j�|d�Wd�n1sn0YdS)z>Clear the internal cache, optionally only for function 'name'.N)rr�r�rr �pop)r�r�rororpr��s

z_WrapNumbers.cache_clearcCs:|j� |j|j|jfWd�S1s,0YdS)z5Return internal cache dicts as a tuple of 3 elements.N)rr�rr r�rororp�
cache_info�sz_WrapNumbers.cache_info)N)
rlrmrnr�r�r%r)r2r�r4rorororpr�s'
rcCs6tj�t�||�Wd�S1s(0YdS)z�Given an `input_dict` and a function `name`, adjust the numbers
    which "wrap" (restart from zero) across different calls by adding
    "old value" to "new value" and return an updated dict.
    N)�_wnrr2)r$r�rororprRsrRi�cCst|dtd�S)N�rb��	buffering)�open�FILE_READ_BUFFER_SIZE)�fnamerororprTsrTcCs\tst|td�St|tttd�}z
t|_Wn,ty<YntyV|���Yn0|S)z�On Python 3 opens a file in text mode by using fs encoding and
    a proper en/decoding errors handler.
    On Python 2 this is just an alias for open(name, 'rt').
    r7)r8�encoding�errors)	�PY3r9r:r3r4�_CHUNK_SIZEr�r��close)r;�fobjrororprS"s �
rSc	Cs�|tur:||��}|��Wd�S1s.0YnRz6||��}|��Wd�WS1sd0YWnttfy�|YS0dS)z�Read entire file content and return it as a string. File is
    opened in text mode. If specified, `fallback` is the value
    returned in case of error, either if the file does not exist or
    it can't be read().
    N)�_DEFAULT�read�IOErrorr�)r;�fallback�_open�frororprU@s
(
,rUcCst||td�S)z,Same as above but opens file in binary mode.)rErF)rUrT)r;rErororprVQsrV�%(value).1f%(symbol)scCs�d}i}t|dd��D]\}}d|dd>||<qt|dd��D]2}t|�||krFt|�||}|t�SqF|t|d|d�S)z�Used by various scripts. See: http://goo.gl/zeJZl.

    >>> bytes2human(10000)
    '9.8K'
    >>> bytes2human(100001221)
    '95.4M'
    )	�B�K�M�G�T�P�E�Z�YrjN�
r)�symbolr�)�	enumerate�reversed�absr��locals�dict)�n�format�symbols�prefixr0�srSr�rororprWVsrWcCstjdjS)z+Return updated psutil.PROCFS_PATH constant.r�)�sys�modulesZPROCFS_PATHrorororp�get_procfs_pathisr`cCs|jttd�S)N)r<r=)�decoder3r4�r]rororprapsracCs|Sr�rorbrororprauscCs^tjdkrdSz2ddl}|��s$J�|��|�d�dks>J�WntyTYdS0dSdS)Nr^Tr�colorsF)r�r��curses�isattyZ	setuptermZtigetnumr�)�filerdrororpr[~s
r[FcCs�t�s
|Sg}tddddddddd	d
�	}d|d<z||}Wn&tybtd
t|�����Yn0|�|�|r||�d�dd�|�|fS)z*Return an highlighted version of 'string'.Z34Z33Z30Z32Z37Z36Z91Z35Z93)	�blue�brownZdarkgrey�greenZgreyZ	lightblue�redZviolet�yellowZ29Nz#invalid color %r; choose between %s�1z[%sm%s�;)r[rXr�r�listr&r-r�)r]�color�bold�attrrcrororprZ�s2��


rZc	Cs
t�st||d�n�tr.tt|||�|d�n�ddl}d}|jjj}|jjj}t	ddddd�}||d<z||}Wn*t
y�td	|t|�
��f��Yn0|r�|dkr�|d
7}|tjur�dnd}	|j|_||	�}
||
|�zt||d�W||
|�n||
|�0dS)
z$Print a colorized version of string.�rfrN�ri��)rirjrhrkz#invalid color %r; choose between %r�i�i����)r[�printrrZ�ctypes�windllZKernel32�GetStdHandle�SetConsoleTextAttributerXr�rrnr&r^�stderr�c_ulong�restype)r]rorprfrxZ
DEFAULT_COLORrzr{rcZ	handle_id�handlerororpr\�s8
���

r\cCsntrjddl}|�|��j�\}}}}}t|t�rRt|ttt	f�rJd|}nd|}t
d|||ftjd�dS)z@If PSUTIL_DEBUG env var is set, print a debug message to stderr.rNzignoring %szignoring %rzpsutil-debug [%s:%s]> %srr)
r�inspect�getframeinfo�currentframe�f_back�
isinstancer�r�rD�EnvironmentErrorrwr^r|)r�r�r;�lineno�_�_lines�_indexrororprY�s�

�rY)N)N)rH)NF)�r��
__future__rrr�r�r�r�r�r�r�r^rrrrrrr�ImportErrorr	�version_infor>r	�bool�getenvr�objectrB�__all__r�rr�platform�
startswithrrrrrrr
rZAIXr)r*r&r+r-r1r%r/r0r'r(r.r,r2rr rrrr!rrrrrrr"r#r$�IntEnumrk�globals�update�__members__rtrurs�getfilesystemencodingr3r4�getfilesystemencodeerrorsr�rFrBr@rArCrGr>rDrEr?r�r�r�r�r6r;r<r=r8r9r:r7r5r�rHr�r�r�r�r�r�r��__builtins__rX�exec_r�r�rNrKr�rJrMrOrLrPrQrXrIrrRr5r�r4r:rTrSrUrVrWr`ra�stdoutr[rZr\rYrorororp�<module>sp


&

	

�������	

�


�
#



-G



W	

	
�
'PKok\]2�مG�G*psutil/__pycache__/_pssunos.cpython-39.pycnu�[���a

��?h�c�@s6dZddlZddlZddlZddlZddlZddlZddlmZddlm	Z	ddl
mZddl
mZddl
m
Zdd	l
mZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!gd�Z"e�#�Z$ej%Z%ej&dkZ'dZ(dZ)ej*ej+ej,ej-ej.ej/ej0ej1ej2ej3ej4ej-ej5ej6iZ7ej8ej9ej:ej;ej<ej=ej>ej?ej@ejAejBejCejDejEejFejGejHejIejJejKejLejMejNejOejPe(ejQe)iZReSddddd d!d"d#d$d%d&d'd(�ZTed)gd*��ZUed+gd,��ZVed-gd.��ZWed/d0d1g�ZXeXZYed2gd3��ZZed4d5d6�[eZj\��Z]d7d8�Z^d9d:�Z_d;d<�Z`d=d>�Zad?d@�ZbdAdB�ZcdCdD�ZdejeZeejfZfdYdFdG�ZgejhZhejiZidZdIdJ�ZjdKdL�ZkdMdN�ZldOdP�ZmdQdR�ZndSdT�ZodUdV�ZpGdWdX�dX�ZqdS)[z'Sun OS Solaris platform implementation.�N)�
namedtuple)�AF_INET�)�_common)�_psposix)�
_psutil_posix)�
_psutil_sunos)�AF_INET6)�AccessDenied)�
NoSuchProcess)�
ZombieProcess)�debug)�get_procfs_path)�
isfile_strict)�memoize_when_activated)�sockfam_to_enum)�socktype_to_enum)�
usage_percent)�PY3)�FileNotFoundError)�PermissionError)�ProcessLookupError)�b)�	CONN_IDLE�
CONN_BOUNDZPROCFS_PATHlZIDLEZBOUND��������	�
�)�ppid�rss�vms�create_time�nice�num_threads�status�ttynr�uid�euid�gid�egid�	scputimes)�user�system�idleZiowait�	pcputimes)r2r3�
children_user�children_system�svmem)�total�	available�percent�used�free�pmemr&r'�
pmmap_grouped)�pathr&Z	anonymous�locked�	pmmap_extzaddr perms � cCsFt�d�t}t�d�t}}||}t||dd�}t|||||�S)zReport virtual memory metrics.�
SC_PHYS_PAGES�SC_AVPHYS_PAGESr�Zround_)�os�sysconf�	PAGE_SIZErr8)r9r=Zavailr<r;�rJ�;/usr/local/lib64/python3.9/site-packages/psutil/_pssunos.py�virtual_memorys
rLc	Cst��\}}tjddtjdddgtjd�}|��\}}trL|�	t
jj�}|j
dkrdtd|j
��|���d	�d
d�}|s�d}t|��d}}|D]D}	|	��}	|	d
d�\}
}|tt|
�d�7}|tt|�d�7}q�||}t||d
d�}
t�||||
|t|t�S)zReport swap memory metrics.z/usr/bin/envzPATH=/usr/sbin:/sbin:%s�PATHZswapz-l)�stdoutrz'swap -l' failed (retcode=%s)�
rNzno swap device(s) configuredrrirF)�cextZswap_mem�
subprocess�PopenrG�environ�PIPE�communicater�decode�sysrN�encoding�
returncode�RuntimeError�strip�split�intrrZsswaprI)�sinZsout�prN�_�lines�msgr9r=�line�t�fr<r;rJrJrK�swap_memory�s:��	
�rfcCst��}tdd�t|�D��S)z.Return system-wide CPU times as a named tuple.cSsg|]}t|��qSrJ)�sum��.0�xrJrJrK�
<listcomp>��zcpu_times.<locals>.<listcomp>)rP�
per_cpu_timesr1�zip��retrJrJrK�	cpu_times�srqcCst��}dd�|D�S)z6Return system per-CPU times as a list of named tuples.cSsg|]}t|��qSrJ)r1rhrJrJrKrk�rlz!per_cpu_times.<locals>.<listcomp>)rPrmrorJrJrKrm�srmcCs&zt�d�WSty YdS0dS)z0Return the number of logical CPUs in the system.�SC_NPROCESSORS_ONLNN)rGrH�
ValueErrorrJrJrJrK�cpu_count_logical�srtcCst��S)z-Return the number of CPU cores in the system.)rP�cpu_count_coresrJrJrJrKru�srucCs$t��\}}}}d}t�||||�S)z*Return various CPU stats as a named tuple.r)rP�	cpu_statsrZ	scpustats)Zctx_switchesZ
interruptsZsyscallsZ_trapsZsoft_interruptsrJrJrKrv�s
�rvFc
Cs�g}t��}|D]�}|\}}}}|dkr,d}|s�zt|�js@WqWn@ty�}z(td||f�WYd}~qWYd}~n
d}~00t�||||�}	|�|	�q|S)zReturn system disk partitions.�none�zskipping %r: %sN)	rP�disk_partitions�
disk_usager9�OSErrorr
rZ	sdiskpart�append)
�all�retlistZ
partitions�	partitionZdeviceZ
mountpointZfstype�opts�errZntuplerJrJrKry�s 
"ry���c
Cstj��}|dkr|�dd�||vrFtd|d�dd�|D��f��tj|\}}t�|�}t�}|D]�}|\}}	}
}}}
}|	|vr�qh|
|vr�qh|	t	t
fvr�|r�tj|�}|r�tj|�}t|
}
t
|	�}	t|
�}
|dkr�t�||	|
|||
|�}nt�||	|
|||
�}|�|�qht|�S)z�Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    Only INET sockets are returned (UNIX are not).
    r��unixrz+invalid %r kind argument; choose between %sz, cSsg|]}t|��qSrJ)�reprrhrJrJrKrkrlz#net_connections.<locals>.<listcomp>)rZ	conn_tmap�copy�poprs�joinrP�net_connections�setrr	�addr�TCP_STATUSESrrZsconn�pconn�add�list)�kind�_pidZcmapZfamilies�types�rawlistrp�item�fd�fam�type_�laddr�raddrr+�pid�ntrJrJrKr�s>
��


r�cCsTt��}|��D]>\}}|\}}}}ttd�r8t�|�}t�||||d�||<q|S)z)Get NIC stats (isup, duplex, speed, mtu).�	NicDuplexrx)rP�net_if_stats�items�hasattrrr�Z	snicstats)rp�namer�ZisupZduplex�speedZmturJrJrKr�.s

r�cCst��S)z:The system boot time expressed in seconds since the epoch.)rP�	boot_timerJrJrJrKr�>sr�cCs\g}t��}d}|D]B}|\}}}}}}	|s.q||vr:d}t�|||||	�}
|�|
�q|S)z:Return currently connected users as a list of namedtuples.)z:0.0z:0�	localhost)rP�usersrZsuserr|)r~r�r�r�r2�tty�hostnameZtstampZuser_processr�r�rJrJrKr�Csr�cCsdd�t�tt���D�S)z7Returns a list of PIDs currently running on the system.cSsg|]}|��rt|��qSrJ)�isdigitr]rhrJrJrKrk]rlzpids.<locals>.<listcomp>)rG�listdirrrrJrJrJrK�pids[sr�cCs
t�|�S)z&Check for the existence of a unix pid.)r�
pid_exists)r�rJrJrKr�`sr�cst����fdd��}|S)z�Call callable into a try/except clause and translate ENOENT,
    EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
    c	s�z�|g|�Ri|��WSttfyZt|j�sDt|j|j��nt|j|j|j��YnXtyxt	|j|j��Yn:t
y�|jdkr�dt�vr�t	|j|j��n��Yn0dS�Nr)rrr�r�r�_namer�_ppidrr
r{r�)�self�args�kwargs��funrJrK�wrapperjs


z wrap_exceptions.<locals>.wrapper)�	functools�wraps)r�r�rJr�rK�wrap_exceptionsesr�c@s�eZdZdZgd�Zdd�Zdd�Zdd�Zd	d
�Ze	e
dd���Ze	e
d
d���Ze	e
dd���Z
e	dd��Ze	dd��Ze	dd��Ze	dd��Ze	dd��Ze	dd��Ze	dd��Ze	dd ��Ze	d!d"��Ze	d#d$��Ze	d%d&��Ze	d'd(��Ze	d)d*��Ze	d+d,��Ze	d-d.��Ze	d/d0��ZeZe	d1d2��Ze	d3d4��Z e	d5d6��Z!d7d8�Z"e	dHd:d;��Z#e$d<d=�Z%e$d<d>�Z&e	d?d@��Z'e	dAdB��Z(e	dCdD��Z)e	dIdFdG��Z*dES)J�Processz1Wrapper class around underlying C implementation.)�_cacher�r��_procfs_pathr�cCs||_d|_d|_t�|_dS�N)r�r�r�rr�)r�r�rJrJrK�__init__�szProcess.__init__cCst�d|j|jf�dS)z+Raise NSP if the process disappeared on us.�%s/%sN)rG�statr�r��r�rJrJrK�
_assert_alive�szProcess._assert_alivecCs(|j�|�|j�|�|j�|�dSr�)�_proc_name_and_argsZcache_activate�_proc_basic_info�
_proc_credr�rJrJrK�
oneshot_enter�szProcess.oneshot_entercCs(|j�|�|j�|�|j�|�dSr�)r�Zcache_deactivater�r�r�rJrJrK�oneshot_exit�szProcess.oneshot_exitcCst�|j|j�Sr�)rPZproc_name_and_argsr�r�r�rJrJrKr��szProcess._proc_name_and_argscCsT|jdkr,tj�d|j|jf�s,t|j��t�|j|j�}t|�tt	�ksPJ�|S)Nrz%s/%s/psinfo)
r�rGr@�existsr�r
rPZproc_basic_info�len�
proc_info_map)r�rprJrJrKr��s�
zProcess._proc_basic_infocCst�|j|j�Sr�)rPZ	proc_credr�r�r�rJrJrKr��szProcess._proc_credcCs|��dSr�)r�r�rJrJrKr��szProcess.namecCs8zt�d|j|jf�WSty*Yn0|��dS)Nz%s/%s/path/a.outrx)rG�readlinkr�r�r{�cmdliner�rJrJrK�exe�s�zProcess.execCs|��d�d�S)NrrC)r�r\r�rJrJrKr��szProcess.cmdlinecCst�|j|j�Sr�)rPZproc_environr�r�r�rJrJrKrS�szProcess.environcCs|��tdS)Nr(�r�r�r�rJrJrKr(�szProcess.create_timecCs|��tdS)Nr*r�r�rJrJrKr*�szProcess.num_threadscCs|��tdS)Nr)r�r�rJrJrK�nice_get�szProcess.nice_getcCs&|jdvrt|j|j��t�|j|�S)N)rr)r�r
r��
cext_posix�setpriority)r��valuerJrJrK�nice_set�s
zProcess.nice_setcCs|��td|_|jS)Nr%)r�r�r�r�rJrJrKr%�szProcess.ppidcCs^z|��\}}}}}}Wn6tyN|��td}|��td}d}Yn0t�|||�S)Nr-r.�r�r
r�r�rZpuids)r��real�	effective�savedr`rJrJrK�uids�s
zProcess.uidscCs^z|��\}}}}}}Wn6tyN|��td}|��td}d}Yn0t�|||�S)Nr/r0r�)r�r`r�r�r�rJrJrK�gids�s
zProcess.gidsc
Cs\zt�|j|j�}Wn<tyP}z$|jtjkr:ts:d}n�WYd}~n
d}~00tj	|�S)N)�r�r�r�)
rPZproc_cpu_timesr�r�r{�errno�	EOVERFLOW�	IS_64_BITrr5)r��timesr�rJrJrKrqszProcess.cpu_timescCst�|j|j�Sr�)rPZproc_cpu_numr�r�r�rJrJrK�cpu_numszProcess.cpu_numc	Csz|j}d}t|��td�}|tjkrjdD]<}zt�d||j|f�WSt	yfd}Yq,Yq,0q,|rv|�
�dS)NFr,)rrr�z
%s/%d/path/%dT)r�r�r�r�rPZPRNODEVrGr�r�rr�)r��procfs_path�
hit_enoentr�rjrJrJrK�terminals
�
zProcess.terminalcCsJ|j}zt�d||jf�WStyDt�d||jf�YdS0dS)Nz%s/%s/path/cwdr�rx)r�rGr�r�rr�)r�r�rJrJrK�cwd'szProcess.cwdcCs2|��}|tdd}|tdd}t||�S)Nr&ir')r�r�r>)r�rpr&r'rJrJrK�memory_info4szProcess.memory_infocCs|��td}t�|d�S)Nr+�?)r�r��
PROC_STATUSES�get)r��coderJrJrKr+=szProcess.statusc
Cs�|j}g}t�d||jf�}d}|D]�}t|�}zt�|j||�\}}Wn^ty�}zF|jtj	krvt
svWYd}~q&|jtjkr�d}WYd}~q&�WYd}~q&d}~00t�
|||�}	|�|	�q&|r�|��|S)Nz	%s/%d/lwpFT)r�rGr�r�r]rPZquery_process_thread�EnvironmentErrorr�r�r��ENOENTrZpthreadr|r�)
r�r�rpZtidsr��tid�utimeZstimer�r�rJrJrK�threadsCs,�zProcess.threadsc	Cs�g}d}|j}d||jf}t�d||jf�D]f}tj�||�}tj�|�r0zt�|�}Wntyvd}Yq0Yq00t	|�r0|�
t�|t
|���q0|r�|��|S)NFz
%s/%d/pathz%s/%d/fdT)r�r�rGr�r@r��islinkr�rrr|rZ	popenfiler]r�)r�r~r�r�Zpathdirr�r@�filerJrJrK�
open_fileses"
zProcess.open_filesccs*dt|�g}tj|tjtjd�}|��\}}trFdd�||fD�\}}|jdkr�d|��vrjt|j	|j
��d|��vr�t|j	|j
��td||f��|�
d	�d
d�}t|�D]v\}}|��}|�d�r�|�
d
d
�d
}	||d
��}
|
dkr�tj}
n|
dk�r
tj}
nd}
dtj|
|	dtjfVq�dS)z<Get UNIX sockets used by process by parsing 'pfiles' output.Zpfiles)rN�stderrcss|]}|�tjj�VqdSr�)rVrWrNrXrhrJrJrK�	<genexpr>�sz,Process._get_unix_sockets.<locals>.<genexpr>rzpermission deniedzno such processz%r command error
%srOrNzsockname: AF_UNIXrC�SOCK_STREAM�
SOCK_DGRAMr�rx)�strrQrRrTrUrrY�lowerr
r�r�rrZr\�	enumerate�lstrip�
startswithr[�socketr�r��AF_UNIXr�	CONN_NONE)r�r��cmdr_rNr�ra�ircr@�typerJrJrK�_get_unix_socketszs6
��



zProcess._get_unix_sockets�inetcCsPt||jd�}|s(t�d|j|jf�|dvrL|�dd�|�|j�D��|S)N)r�r�)r}r�cSsg|]}tj|��qSrJ)rr�)ri�connrJrJrKrk�s�z+Process.net_connections.<locals>.<listcomp>)r�r�rGr�r��extendr�)r�r�rprJrJrKr��s

�zProcess.net_connectionsZmmapzpath rss anon lockedzaddr perms path rss anon lockedcCs0dd�}|j}g}zt�|j|�}WnFtyj}z.|jtjkrTtsTgWYd}~S�WYd}~n
d}~00d}|D]�}|\}}	}
}}}
}|||	�}|�d��szt	�
d||j|f�}WnJt�y}z0|jtjkr�d||j|f}d}n�WYd}~n
d}~00|�||
|||
|f�qt|�r,|�
�|S)NcSs0dt|�dd��d�t|�dd��d�fS)Nz%s-%sr�L)�hexr[)�start�endrJrJrK�toaddr�s�z#Process.memory_maps.<locals>.toaddrF�[z
%s/%s/path/%sT)r�rPZproc_memory_mapsr�r{r�r�r�r�rGr�r�r|r�)r�rr�r~r�r�r�r�r�Zaddrsize�permr�r&ZanonrArJrJrK�memory_maps�s6
�zProcess.memory_mapscCstt�d|j|jf��S)Nz%s/%s/fd)r�rGr�r�r�r�rJrJrK�num_fds�szProcess.num_fdscCstjt�|j|j��Sr�)rZpctxswrPZproc_num_ctx_switchesr�r�r�rJrJrK�num_ctx_switches�s�zProcess.num_ctx_switchesNcCst�|j||j�Sr�)rZwait_pidr�r�)r��timeoutrJrJrK�wait�szProcess.wait)r�)N)+�__name__�
__module__�__qualname__�__doc__�	__slots__r�r�r�r�r�rr�r�r�r�r�r�rSr(r*r�r�r%r�r�rqr�r�r�r�Zmemory_full_infor+r�r�r�r�rZnt_mmap_groupedZnt_mmap_extrr	r
rrJrJrJrKr��s�	








	

	
	






!
"


1

r�)F)r�)rrr�r�rGr�rQrW�collectionsrrrxrrrr�rrPr	r
rrr
rrrrrrZ_compatrrrrrZ__extra__all__ZgetpagesizerIZAF_LINK�maxsizer�rrZSSLEEPZSTATUS_SLEEPINGZSRUNZSTATUS_RUNNINGZSZOMBZ
STATUS_ZOMBIEZSSTOPZSTATUS_STOPPEDZSIDLZSTATUS_IDLEZSONPROCZSWAITZSTATUS_WAITINGr�ZTCPS_ESTABLISHEDZCONN_ESTABLISHEDZ
TCPS_SYN_SENTZ
CONN_SYN_SENTZ
TCPS_SYN_RCVDZ
CONN_SYN_RECVZTCPS_FIN_WAIT_1ZCONN_FIN_WAIT1ZTCPS_FIN_WAIT_2ZCONN_FIN_WAIT2ZTCPS_TIME_WAITZCONN_TIME_WAITZTCPS_CLOSEDZ
CONN_CLOSEZTCPS_CLOSE_WAITZCONN_CLOSE_WAITZ
TCPS_LAST_ACKZ
CONN_LAST_ACKZTCPS_LISTENZCONN_LISTENZTCPS_CLOSINGZCONN_CLOSINGZPSUTIL_CONN_NONEr�Z	TCPS_IDLEZ
TCPS_BOUNDr��dictr�r1r5r8r>Zpfullmemr?r��_fieldsrBrLrfrqrmrtrurvZdisk_io_countersrzryZnet_io_countersZnet_if_addrsr�r�r�r�r�r�r�r�rJrJrJrK�<module>s�
������
.	

'PKok\1}:p�;�;(psutil/__pycache__/_psaix.cpython-39.pycnu�[���a

��?h�H�@s�dZddlZddlZddlZddlZddlZddlZddlmZddl	m
Z
ddl	mZddl	mZ
ddl	mZdd	l
mZdd
l
mZddl
mZddl
mZdd
l
mZddl
mZddl
mZddl
mZddl
mZddl
mZddlmZddlmZddlmZddlmZdgZe e
d�Z!e e
d�Z"e e
d�Z#e�$�Z%ej&Z&e
j'e
j(e
j)e
j*e
j+e
j,e
j-e
j,e
j.e
j/iZ0e
j1e
j2e
j3e
j4e
j5e
j6e
j7e
j8e
j9e
j:e
j;e
j<e
j=e
j>e
j?e
j@e
jAe
jBe
jCe
jDe
jEe
jFe
jGe
jHiZIeJdddddddd d!�ZKed"d#d$g�ZLeLZMed%gd&��ZNed'gd(��ZOd)d*�ZPd+d,�ZQd-d.�ZRd/d0�ZSd1d2�ZTd3d4�ZUd5d6�ZVe
jWZWejXZXdKd8d9�ZYejZZZe"�r�e
j[Z[dLd;d<�Z\d=d>�Z]d?d@�Z^dAdB�Z_dCdD�Z`dEdF�ZadGdH�ZbGdIdJ�dJ�ZcdS)MzAIX platform implementation.�N)�
namedtuple�)�_common)�_psposix)�_psutil_aix)�
_psutil_posix)�NIC_DUPLEX_FULL)�NIC_DUPLEX_HALF)�NIC_DUPLEX_UNKNOWN)�AccessDenied)�
NoSuchProcess)�
ZombieProcess)�conn_to_ntuple)�get_procfs_path)�memoize_when_activated)�
usage_percent)�PY3)�FileNotFoundError)�PermissionError)�ProcessLookupErrorZPROCFS_PATH�proc_threads�net_io_counters�proc_io_counters������)�ppid�rss�vms�create_time�nice�num_threads�status�ttynr�pmemr r!�	scputimes)�user�system�idleZiowait�svmem)�total�	available�percent�used�freecCs4t��\}}}}}t|||dd�}t|||||�S)Nr�Zround_)�cextZvirtual_memrr,)r-Zavailr1Z_pinnedZinuser/�r4�9/usr/local/lib64/python3.9/site-packages/psutil/_psaix.py�virtual_memoryksr6cCs:t��\}}}}||}t||dd�}t�||||||�S)z=Swap system memory as a (total, used, free, sin, sout) tuple.rr2)r3Zswap_memrrZsswap)r-r1�sinZsoutr0r/r4r4r5�swap_memoryqsr8cCst��}tdd�t|�D��S)z.Return system-wide CPU times as a named tuple.cSsg|]}t|��qSr4)�sum��.0�xr4r4r5�
<listcomp>��zcpu_times.<locals>.<listcomp>)r3�
per_cpu_timesr(�zip��retr4r4r5�	cpu_times~srCcCst��}dd�|D�S)z6Return system per-CPU times as a list of named tuples.cSsg|]}t|��qSr4)r(r:r4r4r5r=�r>z!per_cpu_times.<locals>.<listcomp>)r3r?rAr4r4r5r?�sr?cCs&zt�d�WSty YdS0dS)z0Return the number of logical CPUs in the system.�SC_NPROCESSORS_ONLNN)�os�sysconf�
ValueErrorr4r4r4r5�cpu_count_logical�srHcCstgd�}tj|tjtjd�}|��\}}trBdd�||fD�\}}|jdkr\td||f��|����}t	|�prdS)N)Zlsdevz-Cc�	processor��stdout�stderrcss|]}|�tjj�VqdS�N��decode�sysrK�encodingr:r4r4r5�	<genexpr>�sz"cpu_count_cores.<locals>.<genexpr>rz%r command error
%s)
�
subprocess�Popen�PIPE�communicater�
returncode�RuntimeError�strip�
splitlines�len)�cmd�prKrLZ
processorsr4r4r5�cpu_count_cores�s�

r^cCs t��\}}}}t�||||�S)z*Return various CPU stats as a named tuple.)r3�	cpu_statsrZ	scpustats)Zctx_switchesZ
interruptsZsoft_interruptsZsyscallsr4r4r5r_�s�r_Fc	Cs\g}t��}|D]F}|\}}}}|dkr,d}|s<t|�js<qt�||||�}|�|�q|S)zReturn system disk partitions.�none�)r3�disk_partitions�
disk_usager-rZ	sdiskpart�append)	�all�retlistZ
partitions�	partitionZdeviceZ
mountpointZfstype�opts�ntupler4r4r5rb�s
rb���cCs�tj}||vr.td|d�dd�|D��f��tj|\}}t�|�}g}|D]X}|\}}	}
}}}
}|	|vrnqN|
|vrxqNt||	|
|||
t|dkr�|ndd�}|�|�qN|S)z�Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    z+invalid %r kind argument; choose between %sz, cSsg|]}t|��qSr4)�reprr:r4r4r5r=�r>z#net_connections.<locals>.<listcomp>rjN��pid)	rZ	conn_tmaprG�joinr3�net_connectionsr�TCP_STATUSESrd)�kind�_pidZcmapZfamilies�types�rawlistrB�item�fd�fam�type_�laddr�raddrr%rm�ntr4r4r5ro�s8��
�
rocCs�ttd�}tdd�t�D��}i}|D]�}t�|�}t�|�}d}d}tjdd|gtj	tj	d�}|�
�\}	}
tr�d	d
�|	|
fD�\}	}
|jdkr�t
�d|	�}|dur�t|�d
��}|�d�}d�|�}d|v}
|�|t�}t�|
||||�||<q&|S)z)Get NIC stats (isup, duplex, speed, mtu).)�FullZHalfcSsg|]}|d�qS)rr4r:r4r4r5r=�r>z net_if_stats.<locals>.<listcomp>rarz/usr/bin/entstatz-drJcss|]}|�tjj�VqdSrMrNr:r4r4r5rRsznet_if_stats.<locals>.<genexpr>z"Running: (\d+) Mbps.*?(\w+) DuplexNrr�,�running)rr	�set�net_if_addrs�
cext_posixZ
net_if_mtuZnet_if_flagsrSrTrUrVrrW�re�search�int�grouprn�getr
rZ	snicstats)Z
duplex_map�namesrB�nameZmtu�flagsZduplex�speedr]rKrLZ	re_resultZoutput_flagsZisupr4r4r5�net_if_stats�s<


��

�

r�cCst��S)z:The system boot time expressed in seconds since the epoch.)r3�	boot_timer4r4r4r5r�sr�cCs\g}t��}d}|D]B}|\}}}}}}	|s.q||vr:d}t�|||||	�}
|�|
�q|S)z:Return currently connected users as a list of namedtuples.)z:0.0z:0�	localhost)r3�usersrZsuserrd)rfrtr�rur)�tty�hostnameZtstampZuser_processrmr{r4r4r5r�$sr�cCsdd�t�t��D�S)z7Returns a list of PIDs currently running on the system.cSsg|]}|��rt|��qSr4)�isdigitr�r:r4r4r5r=>r>zpids.<locals>.<listcomp>)rE�listdirrr4r4r4r5�pids<sr�cCstj�tj�t�t|�d��S)z&Check for the existence of a unix pid.Zpsinfo)rE�path�existsrnr�strrlr4r4r5�
pid_existsAsr�cst����fdd��}|S)z�Call callable into a try/except clause and translate ENOENT,
    EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
    c	s~z�|g|�Ri|��WSttfyZt|j�sDt|j|j��nt|j|j|j��Yn tyxt	|j|j��Yn0dSrM)
rrr�rmr�_namer
�_ppidrr)�self�args�kwargs��funr4r5�wrapperKs
z wrap_exceptions.<locals>.wrapper)�	functools�wraps)r�r�r4r�r5�wrap_exceptionsFsr�c@sreZdZdZgd�Zdd�Zdd�Zdd�Zee	d	d
���Z
ee	dd���Zed
d��Zedd��Z
edd��Zedd��Zedd��Zedd��Zer�edd��Zed=dd��Zedd��Zed d!��Zed"d#��Zed$d%��Zed&d'��Zed(d)��Zed*d+��Zed,d-��Zed.d/��ZeZed0d1��Zd2d3�Z ed4d5��Z!ed6d7��Z"ed>d9d:��Z#e$�rned;d<��Z%d8S)?�Processz1Wrapper class around underlying C implementation.)�_cacher�r��_procfs_pathrmcCs||_d|_d|_t�|_dSrM)rmr�r�rr�)r�rmr4r4r5�__init__bszProcess.__init__cCs|j�|�|j�|�dSrM)�_proc_basic_infoZcache_activate�
_proc_cred�r�r4r4r5�
oneshot_enterhszProcess.oneshot_entercCs|j�|�|j�|�dSrM)r�Zcache_deactivater�r�r4r4r5�oneshot_exitlszProcess.oneshot_exitcCst�|j|j�SrM)r3Zproc_basic_informr�r�r4r4r5r�pszProcess._proc_basic_infocCst�|j|j�SrM)r3Z	proc_credrmr�r�r4r4r5r�uszProcess._proc_credcCs$|jdkrdSt�|j|j��d�S)NrZswapper�)rmr3Z	proc_namer��rstripr�r4r4r5r�zs
zProcess.namecCs�|��}|sdS|d}tjj|vr�tj�|�sJtj�tj�|��|��}tj�|�rttj�|�rtt�	|tj
�rt|Stj�|�}tjd�
d�D]<}tj�tj�||��}tj�|�r�t�	|tj
�r�|Sq�dS)Nrar�PATH�:)�cmdlinerEr��sep�isabs�abspathrn�cwd�isfile�access�X_OK�basename�environ�split)r�r��exer�Zpossible_exer4r4r5r��s,
�
���
zProcess.execCst�|j�SrM)r3Z	proc_argsrmr�r4r4r5r��szProcess.cmdlinecCst�|j�SrM)r3Zproc_environrmr�r4r4r5r��szProcess.environcCs|��tdS)Nr"�r��
proc_info_mapr�r4r4r5r"�szProcess.create_timecCs|��tdS)Nr$r�r�r4r4r5r$�szProcess.num_threadscCsVt�|j�}g}|D]"\}}}t�|||�}|�|�q|sRt�d|j|jf�|S)N�%s/%s)	r3rrmrZpthreadrdrE�statr�)r�rtrf�	thread_id�utimeZstimerir4r4r5�threads�szProcess.threads�inetcCs,t||jd�}|s(t�d|j|jf�|S)N)rrr�)rormrEr�r�)r�rqrBr4r4r5ro�szProcess.net_connectionscCst�|j�SrM)r��getpriorityrmr�r4r4r5�nice_get�szProcess.nice_getcCst�|j|�SrM)r��setpriorityrm)r��valuer4r4r5�nice_set�szProcess.nice_setcCs|��td|_|jS)Nr)r�r�r�r�r4r4r5r�szProcess.ppidcCs"|��\}}}}}}t�|||�SrM�r�rZpuids)r��real�	effective�saved�_r4r4r5�uids�szProcess.uidscCs"|��\}}}}}}t�|||�SrMr�)r�r�r�r�r�r4r4r5�gids�szProcess.gidscCst�|j|j�}tj|�SrM)r3Zproc_cpu_timesrmr�rZ	pcputimes)r��tr4r4r5rC�szProcess.cpu_timescCsP|��td}|d@d?|d@B}t�d�D]}t�|�j|kr.|Sq.dS)Nr&l��i��z	/dev/**/*)r�r��globrEr��st_rdev)r�Zttydev�devr4r4r5�terminal�s
zProcess.terminalcCsT|j}z t�d||jf�}|�d�WStyNt�d||jf�YdS0dS)Nz	%s/%s/cwd�/r�ra)r�rE�readlinkrmr�rr�)r�Zprocfs_path�resultr4r4r5r��szProcess.cwdcCs2|��}|tdd}|tdd}t||�S)Nr ir!)r�r�r')r�rBr r!r4r4r5�memory_infoszProcess.memory_infocCs|��td}t�|d�S)Nr%�?)r�r��
PROC_STATUSESr�)r��coder4r4r5r%	szProcess.statuscCs�tjddt|j�gtjtjd�}|��\}}trFdd�||fD�\}}d|��vr`t|j|j	��t
�d|�}g}|D]J\}}|��}|�
d�r�|d	d�}|��d
kr�qt|�t�|t|���qt|S)Nz/usr/bin/procfilesz-nrJcss|]}|�tjj�VqdSrMrNr:r4r4r5rRsz%Process.open_files.<locals>.<genexpr>zno such processz(\d+): S_IFREG.*name:(.*)\nz//rzcannot be retrieved)rSrTr�rmrUrVr�lowerrr�r��findallrY�
startswithrdrZ	popenfiler�)r�r]rKrLZ	procfilesrfrvr�r4r4r5�
open_filess,��

zProcess.open_filescCs(|jdkrdStt�d|j|jf��S)Nrz%s/%s/fd)rmr[rEr�r�r�r4r4r5�num_fds)s
zProcess.num_fdscCstjt�|j��SrM)rZpctxswr3Zproc_num_ctx_switchesrmr�r4r4r5�num_ctx_switches/szProcess.num_ctx_switchesNcCst�|j||j�SrM)rZwait_pidrmr�)r��timeoutr4r4r5�wait3szProcess.waitcCsVzt�|j�\}}}}Wn,tyDt|j�s>t|j|j���Yn0t�||||�SrM)	r3rrm�OSErrorr�rr�rZpio)r��rcZwc�rb�wbr4r4r5�io_counters9s
zProcess.io_counters)r�)N)&�__name__�
__module__�__qualname__�__doc__�	__slots__r�r�r�r�rr�r�r�r�r�r�r"r$�HAS_THREADSr�ror�r�rr�r�rCr�r�r�Zmemory_full_infor%r�r�r�r��HAS_PROC_IO_COUNTERSr�r4r4r4r5r�]sv















	



r�)F)rj)dr�r�r�rEr�rSrP�collectionsrrarrrr3rr�rr	r
rrr
rrrrZ_compatrrrrZ__extra__all__�hasattrr�ZHAS_NET_IO_COUNTERSr�ZgetpagesizeZ	PAGE_SIZEZAF_LINKZSIDLZSTATUS_IDLEZSZOMBZ
STATUS_ZOMBIEZSACTIVEZSTATUS_RUNNINGZSSWAPZSSTOPZSTATUS_STOPPEDr�ZTCPS_ESTABLISHEDZCONN_ESTABLISHEDZ
TCPS_SYN_SENTZ
CONN_SYN_SENTZ
TCPS_SYN_RCVDZ
CONN_SYN_RECVZTCPS_FIN_WAIT_1ZCONN_FIN_WAIT1ZTCPS_FIN_WAIT_2ZCONN_FIN_WAIT2ZTCPS_TIME_WAITZCONN_TIME_WAITZTCPS_CLOSEDZ
CONN_CLOSEZTCPS_CLOSE_WAITZCONN_CLOSE_WAITZ
TCPS_LAST_ACKZ
CONN_LAST_ACKZTCPS_LISTENZCONN_LISTENZTCPS_CLOSINGZCONN_CLOSINGZPSUTIL_CONN_NONEZ	CONN_NONErp�dictr�r'Zpfullmemr(r,r6r8rCr?rHr^r_Zdisk_io_countersrcrbr�rror�r�r�r�r�r�r�r4r4r4r5�<module>s�


�	��
	


!,PKok\+�������*psutil/__pycache__/_pslinux.cpython-39.pycnu�[���a

��?hZ�
@s�dZddlmZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlmZddlmZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&ddlm'Z'ddlm(Z(ddlm)Z)ddlm*Z*ddl+m,Z,dd l+m-Z-dd!l+m.Z.dd"l+m/Z/dd#l+m0Z0dd$l+m1Z1e,�r�ddl2Z2ndZ2gd%�Z3d&Z4ej5�6d'e�7��Z8ej5�6d(e�7��Z9e:ed)�Z;e:ed*�Z<e�=d+�Z>e�?�Z@daAejBd,kZCd-ZDe2du�rze
jEZFne2�Gd.d/eHe
jE�i�ZIeIjFZFe2du�r�dZJdZKd0ZLd1ZMn Gd2d3�d3e2jG�ZNeO��PeNjQ�ejRejSejTejUejVejWejXejXejYejZej[ej\d4�Z]ej^ej_ej`ejaejbejcejdejeejfejgejhd5�Zied6gd7��Zjed8gd9��Zked:gd;��Zled<d=�Zmed>emjnd?�Zoed@gdA��ZpedBdCdD�qepjn��ZredEgdF��ZsedGgdH��ZtdIdJ�ZudKdL�ZvdMdN�Zwe#dOdP��ZxzexdQ�WnDey�y2Zzz*edRez�edSdT�dUdUdU�a{WYdZz[zn
dZz[z00dZ|zddVl}m|Z|Wn@e~�y�ddlZej�ddWdX�Z�e:e�dY��r�d�dZdY�Z|Yn0e|du�r�e3��d[d\�e�e�D��d]d^�Z�d_d`�Z�dadb�Z�dcdd�Z�dedf�Z�dgdh�Z�didj�Z�dkdl�Z�dmdn�Z�ej5�6do��sej5�6dp��rdqdr�Z�ndsdr�Z�ej�Z�Gdtdu�duey�Z�Gdvdw�dw�Z�e��Z�d�dydz�Z�d{d|�Z�d}d~�Z�ej�Z�d�d�d��Z�Gd�d��d��Z�d�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�d�d��Z�Gd�d��d��Z�dS)�zLinux platform implementation.�)�divisionN)�defaultdict)�
namedtuple�)�_common)�_psposix)�
_psutil_linux)�
_psutil_posix)�NIC_DUPLEX_FULL)�NIC_DUPLEX_HALF)�NIC_DUPLEX_UNKNOWN)�AccessDenied)�
NoSuchProcess)�
ZombieProcess)�bcat)�cat)�debug)�decode)�get_procfs_path)�
isfile_strict)�memoize)�memoize_when_activated)�open_binary)�	open_text)�parse_environ_block)�path_exists_strict)�
supports_ipv6)�
usage_percent)�PY3)�FileNotFoundError)�PermissionError)�ProcessLookupError)�b)�
basestring)ZPROCFS_PATH�IOPRIO_CLASS_NONE�IOPRIO_CLASS_RT�IOPRIO_CLASS_BE�IOPRIO_CLASS_IDLE�CONN_ESTABLISHED�
CONN_SYN_SENT�
CONN_SYN_RECV�CONN_FIN_WAIT1�CONN_FIN_WAIT2�CONN_TIME_WAIT�
CONN_CLOSE�CONN_CLOSE_WAIT�
CONN_LAST_ACK�CONN_LISTEN�CONN_CLOSINGz/sys/class/power_supplyz/proc/%s/smapsz/proc/%s/smaps_rollup�proc_ioprio_get�proc_cpu_affinity_get�
SC_CLK_TCK�littlei�
AddressFamily�AF_LINK��c@seZdZdZdZdZdZdS)�
IOPriorityrrr9r:N)�__name__�
__module__�__qualname__r$r%r&r'�r?r?�;/usr/local/lib64/python3.9/site-packages/psutil/_pslinux.pyr;ysr;)�R�S�D�T�t�Z�X�x�K�W�I�P)Z01�02Z03Z04Z05Z06Z07Z08Z09Z0AZ0B�svmem)�total�	available�percent�used�free�active�inactive�buffers�cached�shared�slab�sdiskio)	�
read_count�write_count�
read_bytes�write_bytesZ	read_timeZ
write_timeZread_merged_countZwrite_merged_count�	busy_time�	popenfile)�path�fd�position�mode�flags�pmemz"rss vms shared text lib data dirty�pfullmem)�uss�pss�swap�
pmmap_grouped)ra�rss�sizeriZshared_cleanZshared_dirtyZ
private_cleanZ
private_dirtyZ
referencedZ	anonymousrj�	pmmap_extzaddr perms � �pio)r[r\r]r^Z
read_charsZwrite_chars�	pcputimes)�user�system�
children_user�children_system�iowaitcCsLt|t�sJ|��t�|�}|�d�d}|�d�rHt|�sH|dd�}|S)zWrapper around os.readlink().�r�
 (deleted)N���)�
isinstancer#�os�readlink�split�endswithr)rar?r?r@r|�s
r|cCsXtjdtjdtjdi}||tjtjBtjB@}|tj@rH|�ddd�}|�dd�}|S)zZConvert file's open() flags into a readable string.
    Used by Process.open_files().
    �r�wzw+�arzr+)r{�O_RDONLY�O_WRONLY�O_RDWR�O_APPEND�replace)reZ	modes_maprdr?r?r@�file_flags_to_mode�s
r�cCs4|�dd�}d}|rd|}nd|}t�|tj�S)z�Return True if the given name refers to a root device (e.g.
    "sda", "nvme0n1") as opposed to a logical partition (e.g.  "sda1",
    "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram")
    return True.
    �/�!Tz
/sys/block/%sz/sys/block/%s/device)r�r{�access�F_OK)�nameZincluding_virtualrar?r?r@�is_storage_device�s

r�cCs�td|��$}|����dd�}Wd�n1s60Ygd�}t|�}|dkrb|�d�|dkrt|�d�|d	kr�|�d
�td|�adS)z�Set a namedtuple of variable fields depending on the CPU times
    available on this Linux kernel version which may be:
    (user, nice, system, idle, iowait, irq, softirq, [steal, [guest,
     [guest_nice]]])
    Used by cpu_times() function.
    �%s/statrN)rr�nicers�idlervZirqZsoftirq�Zsteal�	Zguest�
Z
guest_nice�	scputimes)r�readliner}�len�appendrr�)�procfs_path�f�values�fieldsZvlenr?r?r@�set_scputimes_ntuples	2


r��/procz ignoring exception on import: %rr�zuser system idle�)�prlimitT)�	use_errnor�cCs�Gdd�dtj�}|�}|dur8t�||dt�|��}n6|�}|d|_|d|_t�||t�|�t�|��}|dkr�t��}t|t	�
|���|j|jfS)Nc@s eZdZdejfdejfgZdS)zprlimit.<locals>.StructRlimit�rlim_cur�rlim_maxN)r<r=r>�ctypes�
c_longlong�_fields_r?r?r?r@�StructRlimit>s�r�rr)r��	Structure�libcr��byrefr�r��	get_errno�OSErrorr{�strerror)�pid�	resource_�limitsr��current�ret�newZerrno_r?r?r@r�=s

�cCs"g|]}|�d�r|��r|�qS)ZRLIM)�
startswith�isupper��.0rHr?r?r@�
<listcomp>Y�r�c
CsB|d}||�dd�}z|d}|d}|d}Wn:tyn}z"td|jd�|WYd}~Sd}~00ztd	t��}Wnty�|YS0d}|�@|D]*}	|	��}	|	�d
�r�|t	|	�
�d�7}q�Wd�n1s�0Y|t9}||}
||}|t|d|�8}|
|7}
|
|t|d
|�7}
t	|
�S)ayFallback for kernels < 3.14 where /proc/meminfo does not provide
    "MemAvailable", see:
    https://blog.famzah.net/2014/09/24/.

    This code reimplements the algorithm outlined here:
    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
        commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773

    We use this function also when "MemAvailable" returns 0 (possibly a
    kernel bug, see: https://github.com/giampaolo/psutil/issues/1915).
    In that case this routine matches "free" CLI tool result ("available"
    column).

    XXX: on recent kernels this calculation may differ by ~1.5% compared
    to "MemAvailable:", as it's calculated slightly differently.
    It is still way more realistic than doing (free + cached) though.
    See:
    * https://gitlab.com/procps-ng/procps/issues/42
    * https://github.com/famzah/linux-memavailable-procfs/issues/2
    �MemFree:�Cached:rs
Active(file):sInactive(file):�
SReclaimable:zY%s is missing from /proc/meminfo; using an approximation for calculating available memoryNz%s/zoneinfoslowrr9g@)
�get�KeyErrorr�argsrr�IOError�stripr��intr}�PAGESIZE�min)�memsrS�fallbackZlru_active_fileZlru_inactive_fileZslab_reclaimable�errr�Z
watermark_low�line�availZ	pagecacher?r?r@�calculate_avail_vmembs<��

4r�cCs�g}i}tdt���:}|D]$}|��}t|d�d||d<qWd�n1sV0Y|d}|d}z|d}Wn ty�d}|�d	�Yn0z|d
}Wn ty�d}|�d�Yn0||�dd�7}z|d
}	WnDt�y,z|d}	Wn"t�y&d}	|�d�Yn0Yn0z|d}
Wn"t�y\d}
|�d�Yn0z|d}WnTt�y�z|d|d|d}Wn"t�y�d}|�d�Yn0Yn0z|d}Wnt�y�d}Yn0||||}
|
dk�r||}
z|d}Wnt�y0t|�}Yn0|dk�rDt|�}|dk�r^d}|�d�n||k�rl|}t|||dd�}|�r�dd�	|�t
|�dk�r�dndf}tj|t
dd �t||||
||
||||	|�S)!a7Report virtual memory stats.
    This implementation mimics procps-ng-3.3.12, aka "free" CLI tool:
    https://gitlab.com/procps-ng/procps/blob/
        24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L778-791
    The returned values are supposed to match both "free" and "vmstat -s"
    CLI tools.
    �
%s/meminfor�rNs	MemTotal:r�sBuffers:rVr�rWr�sShmem:s
MemShared:rXsActive:rTs	Inactive:sInact_dirty:sInact_clean:sInact_laundry:rUsSlab:s
MemAvailable:rP�Zround_z6%s memory stats couldn't be determined and %s set to 0�, �was�werer9��
stacklevel)rrr}r�r�r�r�r�r�joinr��warnings�warn�RuntimeWarningrN)Zmissing_fieldsr�r�r�r�rOrSrVrWrXrTrUrYrRr�rQ�msgr?r?r@�virtual_memory�s�8���

	


��r�c
Cs�i}tdt���:}|D]$}|��}t|d�d||d<qWd�n1sR0Yz|d}|d}Wn8ty�t��\}}}}}}}||9}||9}Yn0||}t||dd�}	ztd	t��}WnNt�y }
z4d
dt	|
�}t
j|tdd
�d}}
WYd}
~
n�d}
~
00|��d}}
|D]n}|�
d��r`t|�d�d�dd}n&|�
d��r�t|�d�d�dd}
|du�r4|
du�r4�qȐq4d
}|d7}t
j|tdd
�d}}
Wd�n1�s�0Yt�||||	||
�S)zReturn swap memory metrics.r�rr�rNs
SwapTotal:s	SwapFree:r�z	%s/vmstatz,'sin' and 'sout' swap memory stats couldn't z$be determined and were set to 0 (%s)r9r�spswpin� �spswpoutzbe determined and were set to 0)rrr}r�r��cextZ
linux_sysinforr��strr�r�r�r�rZsswap)r�r�r�r�rOrS�_Zunit_multiplierrRrQr�r��sinZsoutr?r?r@�swap_memory'sJ8
��
(r�cCsrt�}t|�td|��}|����}Wd�n1s<0Y|dttj�d�}dd�|D�}t|�S)z�Return a named tuple representing the following system-wide
    CPU times:
    (user, nice, system, idle, iowait, irq, softirq [steal, [guest,
     [guest_nice]]])
    Last 3 fields may not be available on all Linux kernel versions.
    r�NrcSsg|]}t|�t�qSr?��float�CLOCK_TICKSr�r?r?r@r�or�zcpu_times.<locals>.<listcomp>)rr�rr�r}r�r��_fields)r�r�r�r�r?r?r@�	cpu_timescs*r�cCs�t�}t|�g}td|��n}|��|D]L}|�d�r,|��}|dttj�d�}dd�|D�}t|�}|�	|�q,|Wd�S1s�0YdS)zfReturn a list of namedtuple representing the CPU times
    for every CPU available on the system.
    r�scpurcSsg|]}t|�t�qSr?r�r�r?r?r@r��r�z!per_cpu_times.<locals>.<listcomp>N)
rr�rr�r�r}r�r�r�r�)r��cpusr�r�r�r��entryr?r?r@�
per_cpu_timesss
r�cCs�zt�d�WSty�d}tdt���0}|D]}|���d�r2|d7}q2Wd�n1sb0Y|dkr�t�d�}t	dt���:}|D]$}|�
d	�d}|�|�r�|d7}q�Wd�n1s�0Y|dkr�YdS|YS0dS)
z0Return the number of logical CPUs in the system.�SC_NPROCESSORS_ONLNr�
%s/cpuinfos	processorrNzcpu\dr�ro)r{�sysconf�
ValueErrorrr�lowerr��re�compilerr}�match)�numr�r��searchr?r?r@�cpu_count_logical�s$(

(r�c
Cs2t�}d}d}t�|�p t�|�D]>}t|��"}|�|�����Wd�q"1sV0Yq"t|�}|dkrv|Si}i}tdt���~}|D]h}|����}|s�z|d||d<Wnt	y�Yn0i}q�|�
d�r�|�d	d
�\}	}
t|
�||	<q�Wd�n1�s0Yt
|���}|�p0dS)z-Return the number of CPU cores in the system.z9/sys/devices/system/cpu/cpu[0-9]*/topology/core_cpus_listz?/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_listNrr��	cpu cores�physical id)r�r�s	:r)�set�globr�add�readr�r�rr�r�r�r}r��sumr�)�ls�p1�p2rar��result�mappingZcurrent_infor��key�valuer?r?r@�cpu_count_cores�s6
2�
.rcCs�tdt����}d}d}d}|D]r}|�d�r@t|��d�}n6|�d�r\t|��d�}n|�d�rvt|��d�}|dur |dur |dur q�q Wd�n1s�0Yd}t�||||�S)z*Return various CPU stats as a named tuple.r�Nsctxtrsintrssoftirqr)rrr�r�r}rZ	scpustats)r�Zctx_switchesZ
interruptsZsoft_interruptsr�Zsyscallsr?r?r@�	cpu_stats�s,


���$�rc	Cshg}tdt���B}|D],}|���d�r|�t|�dd�d��qWd�n1sZ0Y|S)z7Return current CPU frequency from cpuinfo if available.r�scpu mhz�:rN)rrr�r�r�r�r})r�r�r�r?r?r@�_cpu_get_cpuinfo_freq�s:rz'/sys/devices/system/cpu/cpufreq/policy0z$/sys/devices/system/cpu/cpu0/cpufreqcCs&t�}t�d�pt�d�}|jdd�d�g}tjj}t|�D]�\}}t|�t|�krd||d}nt||d�dd	�}|dur�t||d
�dd	�}|dur�d�	|�}t
|dd	�dkr�|�t�
d
d
d
��q>d}t|��t|�d}tt||d���d}	tt||d���d}
|�t�
||
|	��q>|S)z�Return frequency metrics for all CPUs.
        Contrarily to other OSes, Linux updates these values in
        real-time.
        z,/sys/devices/system/cpu/cpufreq/policy[0-9]*z)/sys/devices/system/cpu/cpu[0-9]*/cpufreqcSstt�d|����S)Nz[0-9]+)r�r�r��group)rHr?r?r@�<lambda>�r�zcpu_freq.<locals>.<lambda>)r�i�Zscaling_cur_freqN�r�Zcpuinfo_cur_freqz$/sys/devices/system/cpu/cpu{}/onlinez0
r�z!can't find current frequency fileZscaling_max_freqZscaling_min_freq)rr��sortr{rar��	enumerater�r�formatrr�r�scpufreq�NotImplementedErrorr�)Z
cpuinfo_freqs�pathsr��pjoin�ira�currZonline_pathr�Zmax_Zmin_r?r?r@�cpu_freq�s8���rcCsdd�t�D�S)z}Alternate implementation using /proc/cpuinfo.
        min and max frequencies are not available and are set to None.
        cSsg|]}t�|dd��qS)r�)rr
r�r?r?r@r�#r�zcpu_freq.<locals>.<listcomp>)rr?r?r?r@rsc@seZdZdS)�_Ipv6UnsupportedErrorN)r<r=r>r?r?r?r@r.src@sZeZdZdZdd�Zdd�Zdd�Zedd	��Zeddd��Z	edd
d��Z
ddd�Zd
S)�NetConnectionsawA wrapper on top of /proc/net/* files, retrieving per-process
    and system-wide open connections (TCP, UDP, UNIX) similarly to
    "netstat -an".

    Note: in case of UNIX sockets we're only able to determine the
    local endpoint/path, not the one it's connected to.
    According to [1] it would be possible but not easily.

    [1] http://serverfault.com/a/417946
    cCs�dtjtjf}dtjtjf}dtjtjf}dtjtjf}dtjdf}|||||f||f|f|f||f|f|f|f||||f||f||fd�|_d|_dS)N�tcp�tcp6�udp�udp6�unix)�allr�tcp4rr�udp4rr�inetZinet4Zinet6)�socket�AF_INET�SOCK_STREAM�AF_INET6�
SOCK_DGRAM�AF_UNIX�tmap�_procfs_path)�selfrrrrrr?r?r@�__init__>s$
�
zNetConnections.__init__cCs�tt�}t�d|j|f�D]�}ztd|j||f�}WnvttfyRYqYqty�}zF|j	t	j
krxWYd}~q|j	t	jkr�t|�WYd}~q�WYd}~qd}~00|�
d�r|dd�dd�}||�|t|�f�q|S)N�%s/%s/fd�%s/%s/fd/%szsocket:[r����)r�listr{�listdirr#r|rr!r��errno�EINVAL�ENAMETOOLONGrr�r�r�)r$r��inodesrb�inoder�r?r?r@�get_proc_inodesUs"
zNetConnections.get_proc_inodescCsFi}t�D]6}z|�|�|��Wq
tttfy>Yq
Yq
0q
|S�N)�pids�updater0rr!r )r$r.r�r?r?r@�get_all_inodesos
zNetConnections.get_all_inodesc	Cs�|�d�\}}t|d�}|s dStr.|�d�}|tjkrntrZt�|t�	|�ddd��}q�t�|t�	|��}n~t�	|�}zRtr�t�tj
tjdgt�
d|��R��}n$t�tj
tjdgt�
d|��R��}Wn ty�t�s�t�n�Yn0t�||�S)	a�Accept an "ip:port" address as displayed in /proc/net/*
        and convert it into a human readable form, like:

        "0500000A:0016" -> ("10.0.0.5", 22)
        "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)

        The IP address portion is a little or big endian four-byte
        hexadecimal number; that is, the least significant byte is listed
        first, so we need to reverse the order of the bytes to convert it
        to an IP address.
        The port is represented as a two-byte hexadecimal number.

        Reference:
        http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html
        �:�r?�asciiNr(z>4Iz<4I)r}r�r�encoderr�
LITTLE_ENDIAN�	inet_ntop�base64�	b16decoder�struct�pack�unpackr�rrr�addr)r@�family�ip�portr?r?r@�decode_addresss4



��zNetConnections.decode_addressNccsN|�d�rtj�|�sdSt|���}|��t|d�D]�\}}z(|��dd�\
}}	}
}}}}}}}Wn$ty�t	d|||f��Yn0||vr�||d\}
}nd\}
}|dur�||
kr�q8q8|t
jkr�t|}nt
j}zt�|	|�}	t�|
|�}
Wnt�yYq8Yn0||||	|
||
fVq8Wd�n1�s@0YdS)z.Parse /proc/net/tcp* and /proc/net/udp* files.�6Nrr�z,error while parsing %s; malformed line %s %rr�Nr()r~r{ra�existsrr�rr}r��RuntimeErrorrr�TCP_STATUSESr�	CONN_NONErrDr)�filerA�type_r.�
filter_pidr��linenor�r��laddr�raddr�statusr/r�rbr?r?r@�process_inet�s8���



zNetConnections.process_inetc
cst|���}|��|D]�}|��}z|dd�\}}}}}}}	Wn.tynd|vrZYqtd||f��Yn0|	|vr�||	}
ndg}
|
D]`\}}|dur�||kr�q�q�t|�dkr�|dnd	}
t�t|��}d	}tj	}||||
|||fVq�qWd�n1�s0YdS)
zParse /proc/net/unix files.r�roz)error while parsing %s; malformed line %rrFNr�r(�)
rr�r}r�rHr�rZsocktype_to_enumr�rJ)rKrAr.rMr�r��tokensr�rLr/�pairsr�rbrarPrQr?r?r@�process_unix�s2
��

zNetConnections.process_unixcCs||jvr,td|d�dd�|jD��f��t�|_|durP|�|�}|sXgSn|��}t�}|j|D]�\}}}d|j|f}|tj	tj
fvr�|j|||||d�}	n|j||||d�}	|	D]L\}
}}}}}
}|r�t
�|
|||||
�}nt
�|
|||||
|�}|�|�q�qht|�S)Nz+invalid %r kind argument; choose between %sr�cSsg|]}t|��qSr?)�reprr�r?r?r@r�r�z+NetConnections.retrieve.<locals>.<listcomp>z	%s/net/%s)rM)r"r�r�rr#r0r4r�rrrrRrWr�pconnZsconnr�r))r$�kindr�r.r�Z
proto_namerArLrar�rbrOrPrQZ	bound_pid�connr?r?r@�retrieves<
��

���zNetConnections.retrieve)N)N)N)r<r=r>�__doc__r%r0r4�staticmethodrDrRrWr\r?r?r?r@r2s
4)#rrcCs
t�|�S)z$Return system-wide open connections.)�_net_connectionsr\)rZr?r?r@�net_connections)sr`cCs�tdt���}|��}Wd�n1s,0Yi}|dd�D]�}|�d�}|dkshJt|���|d|���}||dd�����}tt|�\}}}	}
}}}
}}}}}}}}}|||||	||
|f||<qF|S)zsReturn network I/O statistics for every network interface
    installed on the system as a dict of raw tuples.
    z
%s/net/devNr9r5rr)	rr�	readlines�rfindrXr�r}�mapr�)r��lines�retdictr��colonr�r�Z
bytes_recvZpackets_recvZerrinZdropinZ_fifoinZ_frameinZ
_compressedinZ_multicastinZ
bytes_sentZpackets_sentZerroutZdropoutZ_fifooutZ_collisionsoutZ_carrieroutZ_compressedoutr?r?r@�net_io_counters.sH&
��

rgcCs�tjttjttjti}t���}i}|D]�}z&t	�
|�}t	�|�}t�|�\}}Wn<t
y�}z$|jtjkrr�nt|�WYd}~q(d}~00d�|�}	d|v}
t�|
|||||	�||<q(|S)z)Get NIC stats (isup, duplex, speed, mtu).N�,�running)r�ZDUPLEX_FULLr
ZDUPLEX_HALFrZDUPLEX_UNKNOWNrrg�keys�
cext_posixZ
net_if_mtuZnet_if_flagsZnet_if_duplex_speedr�r+ZENODEVrr�rZ	snicstats)Z
duplex_map�namesr�r�ZmtureZduplex�speedr�Zoutput_flagsZisupr?r?r@�net_if_stats]s*�



�
rnFcCs�dd�}dd�}tj�dt��r*|�}n"tj�d�r>|�}ntdt���i}|D]T}|\
}}}}	}
}}}
}}|s~t|�s~qT|	t9}	|
t9}
|||	|
|||
||f	||<qT|S)zcReturn disk I/O statistics for every disk installed on the
    system as a dict of raw tuples.
    cssDtdt���}|��}Wd�n1s,0Y|D�]}|��}t|�}|dkr�|d}t|d�}tt|dd��\
}}}	}
}}}
}}}n�|dks�|dkr�|d}tt|dd��\}}}}	}
}}}
}}}nN|dk�r|d}tt|dd��\}}}
}d	}	}
}}}ntd
|��|||
|||	|
|||f
Vq:dS)N�%s/diskstats�r:r9r���rSrz!not sure how to interpret line %r)rrrar}r�r�rcr�)r�rdr�r�Zflenr��reads�reads_merged�rbytes�rtime�writes�
writes_merged�wbytes�wtimer�r_r?r?r@�read_procfs�s4&
�
��
�
�z%disk_io_counters.<locals>.read_procfscss�t�d�D]�}t�tj�d|��D]�\}}}d|vr6q"ttj�|d��� }|������}Wd�n1sn0Ytj�	|�}t
t|dd��\
}}}	}
}}}
}}}||||	|
|
||||f
Vq"q
dS)N�
/sys/block�statr�)r{r*�walkrar�rr�r�r}�basenamercr�)�block�rootr��filesr�r�r�rsrtrurvrwrxryrzr_r?r?r@�
read_sysfs�s.��z$disk_io_counters.<locals>.read_sysfsror|zC%s/diskstats nor /sys/block filesystem are available on this system)r{rarGrrr��DISK_SECTOR_SIZE)Zperdiskr{r��genrer�r�rsrwruryrvrzrtrxr_r?r?r@�disk_io_counters�s0-����
r�c@s@eZdZdZddgZdd�Zdd�Zdd	�Zd
d�Zdd
�Z	dS)�RootFsDeviceFinderaFdisk_partitions() may return partitions with device == "/dev/root"
    or "rootfs". This container class uses different strategies to try to
    obtain the real device path. Resources:
    https://bootlin.com/blog/find-root-device/
    https://www.systutorials.com/how-to-find-the-disk-where-root-is-on-in-bash-on-linux/.
    �major�minorcCs(t�d�j}t�|�|_t�|�|_dS)Nr�)r{r}�st_devr�r�)r$�devr?r?r@r%�szRootFsDeviceFinder.__init__cCs�tdt����}|��dd�D]�}|��}t|�dkr:q |d��rRt|d�nd}|d��rnt|d�nd}|d}||jkr ||jkr |r d|Wd�Sq Wd�n1s�0YdS)Nz
%s/partitionsr9r�rrr:�/dev/%s)	rrrar}r��isdigitr�r�r�)r$r�r�r�r�r�r�r?r?r@�ask_proc_partitions�sz&RootFsDeviceFinder.ask_proc_partitionscCs�d|j|jf}t|��T}|D]>}|�d�r|���d�d}|rd|Wd�SqWd�n1sr0YdS)Nz/sys/dev/block/%s:%s/ueventzDEVNAME=r9r�)r�r�rr�r��
rpartition)r$rar�r�r�r?r?r@�ask_sys_dev_blocks

z$RootFsDeviceFinder.ask_sys_dev_blockc	Cs�d|j|jf}t�d�}|D]�}zt|�}WntyDYqYq0|�R|����}||kr�tj	�
tj	�|��}d|Wd�SWd�q1s�0YqdS)Nz%s:%sz/sys/class/block/*/devr�)r�r�r��iglobrrr�r�r{rar�dirname)r$�needler�rKr��datar�r?r?r@�ask_sys_class_blocks

z&RootFsDeviceFinder.ask_sys_class_blockc
Cs�d}|durJz|��}Wn0ttfyH}zt|�WYd}~n
d}~00|dur�z|��}Wn0ttfy�}zt|�WYd}~n
d}~00|dur�z|��}Wn0ttfy�}zt|�WYd}~n
d}~00|dur�tj�|�r�|SdSr1)	r�r�r�rr�r�r{rarG)r$rar�r?r?r@�finds$zRootFsDeviceFinder.findN)
r<r=r>r]�	__slots__r%r�r�r�r�r?r?r?r@r��s
	r�cCs4t�}t�}|s�td|��\}|D]F}|��}|�d�sH|�|���q"|�d�d}|dkr"|�d�q"Wd�n1s~0Y|dkr�tj�	d�r�tj�
d�}ntj�
d	|�}g}t�|�}|D]b}	|	\}
}}}|
d
kr�d}
|
dvr�t
���p�|
}
|�s|
r�||v�rq�t�|
|||�}
|�|
�q�|S)
z8Return mounted disk partitions as a list of namedtuples.z%s/filesystemsZnodev�	rZzfsNr�z	/etc/mtabz%s/self/mounts�nonerT)z	/dev/rootZrootfs)r�rrr�r�r�r}r{ra�isfile�realpathr��disk_partitionsr�r�rZ	sdiskpartr�)rZfstypesr�r�r�ZfstypeZmounts_path�retlistZ
partitions�	partitionZdeviceZ
mountpoint�opts�ntupler?r?r@r�5s8
*
r�cCs`t�t�}t�d�}|�t�d��ttdd�|D���}t�d�}t�d�}|D]"}|�	d|�}||vrR|�
|�qR|D�]}z>|d}tt|��d	}t
j�t
j�|�d
�}t|���}	Wntttfy�YqzYn0t|ddd
�}
t|ddd
�}t|ddd
���}|
du�rDzt|
�d	}
Wnt�yBd}
Yn0|du�rxzt|�d	}Wnt�yvd}Yn0||	�
|||
|f�qz|�sXt�d�}tt|��}|D�]�}z<t
j�|d�}tt|��d	}t
j�|d�}t|���}	WnBtttf�y4}
z"t|
�WYd}
~
�q�WYd}
~
n
d}
~
00t�|d�}tdd�|D��}d}d}
|D]�}t
j�||d�}t|dd
���}|dk�r�tt
j�||d�dd
�}n$|dk�r�tt
j�||d�dd
�}
|
du�rzt|
�d	}
Wnt�yd}
Yn0|du�rbzt|�d	}Wnt�y8d}Yn0�qb||	�
d||
|f��q�t|�S)a�Return hardware (CPU and others) temperatures as a dict
    including hardware name, label, current, max and critical
    temperatures.

    Implementation notes:
    - /sys/class/hwmon looks like the most recent interface to
      retrieve this info, and this implementation relies on it
      only (old distros will probably use something else)
    - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon
    - /sys/class/thermal/thermal_zone* is another one but it's more
      difficult to parse
    z/sys/class/hwmon/hwmon*/temp*_*z&/sys/class/hwmon/hwmon*/device/temp*_*cSsg|]}|�d�d�qS�r�r�r}r�r?r?r@r�tr�z(sensors_temperatures.<locals>.<listcomp>z5/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*z'/sys/devices/platform/coretemp.*/hwmon/z/sys/class/hwmon/�_inputg@�@r�Z_maxNrZ_crit�_labelrTz /sys/class/thermal/thermal_zone*�temp�typez/trip_point*cSs,g|]$}d�tj�|��d�dd���qS)r�rr:)r�r{rarr})r��pr?r?r@r��s��_type�critical�_temp�high)�collectionsrr)r��extend�sortedr�r�r��subr�r�rr{rar�r�rr�r�r�r�r�dict)r��	basenamesZ
basenames2�replr�Zaltname�baserar��	unit_namer�r��labelr�Z
trip_pathsZtrip_pointsZ
trip_pointZ	trip_typer?r?r@�sensors_temperaturesas�

�

	






$�
�
�


r�cCs�t�t�}t�d�}|s"t�d�}ttdd�|D���}|D]�}ztt|d��}Wn<tt	fy�}z t
|�WYd}~q<WYd}~n
d}~00ttj
�tj
�|�d����}t|dd	d
���}||�t�||��q<t|�S)a�Return hardware fans info (for CPU and other peripherals) as a
    dict including hardware label and current speed.

    Implementation notes:
    - /sys/class/hwmon looks like the most recent interface to
      retrieve this info, and this implementation relies on it
      only (old distros will probably use something else)
    - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon
    z/sys/class/hwmon/hwmon*/fan*_*z%/sys/class/hwmon/hwmon*/device/fan*_*cSsg|]}|�d�d�qSr�r�r�r?r?r@r��r�z sensors_fans.<locals>.<listcomp>r�Nr�r�rTr)r�rr)r�r�r�r�rr�r�rrr{rar�r�r�r�rZsfanr�)r�r�r�r�r�r�r�r?r?r@�sensors_fans�s



"r�cs�t���fdd�}dd�t�t�D�}|s.dStj�tt|�d�}||d|d�}||d	|d
�}||d|d�}||d
�}|dur�|dur�zd||}Wq�ty�d}Yq�0n tt	|ddd��}|dkr�dSd}|tj�td�tj�td��}	|	du�r|	dk}n6t	|ddd��
���}
|
dk�r>d}n|
dv�rLd}|�rZtj
}nt|du�r�|du�r�zt||d�}Wnt�y�tj}Yn0n.|du�r�t|d�}|dk�r�tj}ntj}t�|||�S)aReturn battery information.
    Implementation note: it appears /sys/class/power_supply/BAT0/
    directory structure may vary and provide files with the same
    meaning but under different names, see:
    https://github.com/giampaolo/psutil/issues/966.
    c	sP|D]F}t|�d�}|�krzt|�WStyH|��YS0qdS)zvAttempt to read the content of multiple files which may
        not exist. If none of them exist return None.
        rN)rr�r�r�)rrar���nullr?r@�
multi_bcat�sz#sensors_battery.<locals>.multi_bcatcSs&g|]}|�d�sd|��vr|�qS)ZBATZbattery)r�r�r�r?r?r@r�s�z#sensors_battery.<locals>.<listcomp>Nrz/energy_nowz/charge_nowz
/power_nowz/current_nowz/energy_fullz/charge_fullz/time_to_empty_nowgY@r�z	/capacityr(rz
AC0/onlinez	AC/onlinerz/statusrTZdischargingF)Zcharging�fullTi�<)�objectr{r*�POWER_SUPPLY_PATHrar�r��ZeroDivisionErrorr�rr�r�rZPOWER_TIME_UNLIMITEDZPOWER_TIME_UNKNOWNZsbattery)r�Zbatsr�Z
energy_nowZ	power_nowZenergy_fullZ
time_to_emptyrQZ
power_pluggedZonlinerQZsecsleftr?r�r@�sensors_battery�sZ
��





r�c	CsHg}t��}|D]2}|\}}}}}t�||p.d|||�}|�|�q|S)z:Return currently connected users as a list of namedtuples.N)r��usersrZsuserr�)	r�Zrawlist�itemrr�tty�hostnameZtstampr��ntr?r?r@r�Usr�cCs�dt�}t|��^}|D]<}|�d�rt|����d�}|a|Wd�Sqtd|��Wd�n1sv0YdS)zAReturn the system boot time expressed in seconds since the epoch.r�sbtimerNzline 'btime' not found in %s)rrr�r�r�r}�	BOOT_TIMErH)rar�r�r�r?r?r@�	boot_time`s


r�cCsdd�t�tt���D�S)z7Returns a list of PIDs currently running on the system.cSsg|]}|��rt|��qSr?)r�r�r�r?r?r@r�tr�zpids.<locals>.<listcomp>)r{r*r"rr?r?r?r@r2rsr2c	Cs�t�|�sdSz�dt�|f}t|��\}|D]:}|�d�r,t|��d�}||kWd�WSq,td|��Wd�n1s�0YWn ttfy�|t	�vYS0dS)zcCheck for the existence of a unix PID. Linux TIDs are not
    supported (always return False).
    F�%s/%s/statussTgid:rNz'Tgid' line not found in %s)
r�
pid_existsrrr�r�r}r��EnvironmentErrorr2)r�rar�r�Ztgidr?r?r@r�ws



.r�c
Cs�i}t�}t�D]�}z<td||f��}|��}Wd�n1sD0YWnttfyfYq0|�d�}||dd���}t|d�}|||<q|S)zsObtain a {pid: ppid, ...} dict for all running processes in
    one shot. Used to speed up Process.children().
    �
%s/%s/statN�)r9r)	rr2rr�rr!rbr}r�)r�r�r�r�r��rparZdset�ppidr?r?r@�ppid_map�s
*

r�cst����fdd��}|S)zlDecorator which translates bare OSError and IOError exceptions
    into NoSuchProcess and AccessDenied.
    cs�z�|g|�Ri|��WSty8t|j|j��Ynhty^|��t|j|j��YnBty�|��tj	�
d|j|jf�s�t|j|j���Yn0dS)N�%s/%s)r r
r��_namer!�_raise_if_zombierrr{rarGr#)r$r��kwargs��funr?r@�wrapper�sz wrap_exceptions.<locals>.wrapper)�	functools�wraps)r�r�r?r�r@�wrap_exceptions�sr�c@s�eZdZdZgd�Zdd�Zdd�Zdd�Zd	d
�Ze	e
dd���Ze	e
d
d���Ze	e
dd���Z
dd�Zdd�Ze	dd��Ze	dd��Ze	dd��Ze	dd��Ze	dd��Zej�de���r�e	d d!��Ze	d"d#��Ze	d$d%��Ze	ddd'd(��Ze	d)d*��Ze	d+d,��Ze�se �rVd-d.�Z!e	e"�#d/�e"�#d0�e"�#d1�fd2d3��Z$e	d4d5��Z%neZ%e �rle	d6d7��Z&e	d8d9��Z'e	e"�#d:�fd;d<��Z(e	e"�#d=�fd>d?��Z)e	d@dA��Z*e	dBdC��Z+e	dDdE��Z,e-�r�e	dFdG��Z.e"�#dH�fdIdJ�Z/e	dKdL��Z0e1�re	dMdN��Z2e	dOdP��Z3e4d&u�r.e	dedQdR��Z5e	dSdT��Z6e	dUdV��Z7e	dfdXdY��Z8e	dZd[��Z9e	d\d]��Z:e	e"�#d^�fd_d`��Z;e	e"�#da�fdbdc��Z<d&S)g�ProcesszLinux process implementation.)�_cacher��_ppidr#r�cCs||_d|_d|_t�|_dSr1)r�r�r�rr#)r$r�r?r?r@r%�szProcess.__init__c	Cs\ztd|j|jf�}Wnttfy0YdS0|�d�}||d|d�}|dkSdS)Nr�Fr�r9r:�Z)rr#r�r�r�rb)r$r�r�rQr?r?r@�
_is_zombie�s
zProcess._is_zombiecCs|��rt|j|j|j��dSr1)r�rr�r�r��r$r?r?r@r��szProcess._raise_if_zombiecCst�d|j|jf�dS)z+Raise NSP if the process disappeared on us.r�N)r{r}r#r�r�r?r?r@�_raise_if_not_alive�szProcess._raise_if_not_alivecCs�td|j|jf�}|�d�}||�d�d|�}||dd���}i}||d<|d|d	<|d|d
<|d|d<|d
|d<|d|d<|d|d<|d|d<|d|d<|d|d<z|d|d<Wn"ty�td�d|d<Yn0|S)aYParse /proc/{pid}/stat file and return a dict with various
        process info.
        Using "man proc" as a reference: where "man proc" refers to
        position N always subtract 3 (e.g ppid position 4 in
        'man proc' == position 1 in here).
        The return value is cached in case oneshot() ctx manager is
        in use.
        r�r��(rr9Nr�rrQr�r��ttynr��utime��stime�
�children_utimerq�children_stime��create_time�$�cpu_num�'�blkio_ticksz&can't get blkio_ticks, set iowait to 0)rr#r�rbr�r}�
IndexErrorr)r$r�r�r�r�r�r?r?r@�_parse_stat_file�s*
zProcess._parse_stat_filecCs@td|j|jf��}|��Wd�S1s20YdS)z�Read /proc/{pid}/stat file and return its content.
        The return value is cached in case oneshot() ctx manager is
        in use.
        r�N)rr#r�r��r$r�r?r?r@�_read_status_fileszProcess._read_status_filecCsDtd|j|jf��}|����Wd�S1s60YdS)Nz%s/%s/smaps)rr#r�r�r�r�r?r?r@�_read_smaps_fileszProcess._read_smaps_filecCs(|j�|�|j�|�|j�|�dSr1)r�Zcache_activater�r�r�r?r?r@�
oneshot_enter szProcess.oneshot_entercCs(|j�|�|j�|�|j�|�dSr1)r�Zcache_deactivater�r�r�r?r?r@�oneshot_exit%szProcess.oneshot_exitcCs|��d}trt|�}|S)Nr�)r�rr)r$r�r?r?r@r�*szProcess.namec	CsZztd|j|jf�WSttfyT|��tj�d|j|jf�rNYdS�Yn0dS)Nz	%s/%s/exer�rT)	r|r#r�rr!r�r{ra�lexistsr�r?r?r@�exe2szProcess.execCs�td|j|jf��}|��}Wd�n1s20Y|sL|��gS|�d�rZdnd}|�|�rt|dd�}|�|�}|dkr�t|�dkr�d|vr�|�d�}|S)Nz
%s/%s/cmdlinerwror(r)rr#r�r�r�r~r}r�)r$r�r��sep�cmdliner?r?r@r�?s&


zProcess.cmdlinecCsDtd|j|jf��}|��}Wd�n1s20Yt|�S)Nz
%s/%s/environ)rr#r�r�r)r$r�r�r?r?r@�environYs&zProcess.environcCs<t|��d�}t��}z
||WSty6YdS0dS)Nr�)r�r�rZget_terminal_mapr�)r$Ztty_nrr"r?r?r@�terminal_s
zProcess.terminalz/proc/%s/ioc
Csd|j|jf}i}t|��\}|D]F}|��}|r"z|�d�\}}WntyZYq"Yq"0t|�||<q"Wd�n1s~0Y|s�td|��z,t|d|d|d|d|d|d	�WSt	�y}z$td
|j
d||f��WYd}~n
d}~00dS)Nz%s/%s/ios: z%s file was emptyssyscrssyscws
read_bytesswrite_bytessrcharswcharz1%r field was not found in %s; found fields are %rr)r#r�rr�r}r�r�rHrpr�r�)r$�fnamer�r�r�r�r�r�r?r?r@�io_countersks8

,���zProcess.io_counterscCsh|��}t|d�t}t|d�t}t|d�t}t|d�t}t|d�t}t|||||�S)Nr�r�r�r�r�)r�r�r�rq)r$r�r�r�r�r�rvr?r?r@r��szProcess.cpu_timescCst|��d�S)zWhat CPU the process is on.r��r�r�r�r?r?r@r��szProcess.cpu_numNcCst�|j||j�Sr1)rZwait_pidr�r�)r$�timeoutr?r?r@�wait�szProcess.waitcCs&t|��d�}tpt�}|t|S)Nr�)r�r�r�r�r�)r$�ctimeZbtr?r?r@r��s
zProcess.create_timec	Csttd|j|jf��<}dd�|����dd�D�\}}}}}}}Wd�n1sV0Yt|||||||�S)Nz%s/%s/statmcss|]}t|�tVqdSr1)r�r�r�r?r?r@�	<genexpr>�sz&Process.memory_info.<locals>.<genexpr>rS)rr#r�r�r}rf)	r$r�ZvmsrlrX�text�libr�Zdirtyr?r?r@�memory_info�s

�2zProcess.memory_infocCs�d}}}td�|j|j���|}|D]f}|�d�rN|t|��d�d7}q&|�d�rnt|��d�d}q&|�d�r&t|��d�d}q&Wd�n1s�0Y|||fS)Nrz{}/{}/smaps_rollupsPrivate_rr��Pss:�Swap:)rr	r#r�r�r�r})r$rhrirjr�r�r?r?r@�_parse_smaps_rollup�s	�


4zProcess._parse_smaps_rollups\nPrivate.*:\s+(\d+)s\nPss\:\s+(\d+)s\nSwap\:\s+(\d+)cCsZ|��}ttt|�|���d}ttt|�|���d}ttt|�|���d}|||fS)Nr�)r�r�rcr��findall)r$Z_private_reZ_pss_reZ_swap_reZ
smaps_datarhrirjr?r?r@�_parse_smaps�s
zProcess._parse_smapsc	Csftr>z|��\}}}WqLttfy:|��\}}}YqL0n|��\}}}|��}t||||f�Sr1)�HAS_PROC_SMAPS_ROLLUPr	r!rrrrg)r$rhrirjZ	basic_memr?r?r@�memory_full_info�szProcess.memory_full_infocCs^dd�}|��}|s |��gS|�d�}g}|�d�}|g}|||�D�]\}}|�dd�}z|\}	}
}}}
}Wn(ty�|dg\}	}
}}}
}Yn0|s�d}n2tr�t|�}|��}|�d	�r�t	|�s�|dd
�}t|	�t|
�||�
dd�|�
dd�|�
d
d�|�
dd�|�
dd�|�
dd�|�
dd�|�
dd�|�
dd�|�
dd�f
}|�|�qH|S)aQReturn process's mapped memory regions as a list of named
            tuples. Fields are explained in 'man proc'; here is an updated
            (Apr 2012) version: http://goo.gl/fmebo.

            /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if
            CONFIG_MMU kernel configuration option is not enabled.
            c	ss�i}|D]�}|�dd�}|d�d�s@|��|fV|�|�qzt|d�d||d<Wqty�|d�d�r~Yqntd|��Yq0q|��|fVdS)N�rrrr�sVmFlags:z#don't know how to interpret line %r)r}r~�popr�r�r�r�)rd�
current_blockr�r�r�r?r?r@�
get_blockss"��z'Process.memory_maps.<locals>.get_blocks�
rNrrTz[anon]rxrysRss:sSize:rs
Shared_Clean:s
Shared_Dirty:sPrivate_Clean:sPrivate_Dirty:sReferenced:s
Anonymous:r)r�r�r}rr�rrr�r~rr�r�)r$rr�rdr��
first_liner�headerZhfieldsr@Zperms�_offset�_devZ_inoderar�r?r?r@�memory_mapssP


�









�zProcess.memory_mapscCstd|j|jf�S)Nz	%s/%s/cwd)r|r#r�r�r?r?r@�cwdRszProcess.cwdsctxt_switches:\t(\d+)cCsL|��}|�|�}|s,td|j|jf��nt�t|d�t|d��SdS)Nz�'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'lines were not found in %s/%s/status; the kernel is probably older than 2.6.23rr)r�r
rr#r�rZpctxswr�)r$Z	_ctxsw_rer�Zctxswr?r?r@�num_ctx_switchesVs

��zProcess.num_ctx_switchessThreads:\t(\d+)cCs|��}t|�|�d�S�Nr)r�r�r
)r$Z_num_threads_rer�r?r?r@�num_threadseszProcess.num_threadsc
Cst�d|j|jf�}|��g}d}|D]�}d|j|j|f}z8t|��}|����}Wd�n1sl0YWntt	fy�d}Yq*Yn0||�
d�dd�}|�d�}t|d�t
}	t|d	�t
}
t�t|�|	|
�}|�|�q*|�r|��|S)
Nz
%s/%s/taskFz%s/%s/task/%s/statTr�r9r�r�r�)r{r*r#r�rrr�r�rr!r�r}r�r�rZpthreadr�r�r�)r$Z
thread_idsr��
hit_enoent�	thread_idr�r��str�r�r�r�r?r?r@�threadsms2�
.

zProcess.threadscCst�|j�Sr1)rk�getpriorityr�r�r?r?r@�nice_get�szProcess.nice_getcCst�|j|�Sr1)rk�setpriorityr�)r$r�r?r?r@�nice_set�szProcess.nice_setcCst�|j�Sr1)r�r4r�r�r?r?r@�cpu_affinity_get�szProcess.cpu_affinity_getsCpus_allowed_list:\t(\d+)-(\d+)cCsV|��}|�|�}|r@ttt|dd�t|dd�d��Stttt����SdS)Nrr)r�r
r)�ranger�r�r�)r$�_rer�r�r?r?r@�_get_eligible_cpus�s

*zProcess._get_eligible_cpusc
Cs�zt�|j|�Wn�ttfy�}zxt|t�s<|jtjkr�|��}t	t
tt����}|D]4}||vrvtd||f��||vrZtd||f��qZ�WYd}~n
d}~00dS)Nz(invalid CPU number %r; choose between %sz0CPU number %r is not eligible; choose between %s)
r�Zproc_cpu_affinity_setr�r�r�rzr+r,r'�tupler%r�r�)r$r�r�Z
eligible_cpusZall_cpus�cpur?r?r@�cpu_affinity_set�s(����zProcess.cpu_affinity_setcCs,t�|j�\}}tdur t|�}t�||�Sr1)r�r3r��enumr;rZpionice)r$�ioclassr�r?r?r@�
ionice_get�szProcess.ionice_getcCsT|durd}|r(|ttfvr(td|��|dks8|dkrDd}t|��t�|j||�S)Nrz%r ioclass accepts no valuerSzvalue not in 0-7 range)r'r$r�r�Zproc_ioprio_setr�)r$r,r�r�r?r?r@�
ionice_set�szProcess.ionice_setc
Cs�|jdkrd}t|��zL|dur.t|j|�WSt|�dkrRddt|�}t|��t|j||�Wn:ty�}z"|jtjkr�|���WYd}~n
d}~00dS)Nrz)can't use prlimit() against PID 0 processr9z'second argument must be a (soft, hard) z
tuple, got %s)	r�r�r�r�rXr�r+ZENOSYSr�)r$r�r�r�r�r?r?r@�rlimit�s"

��zProcess.rlimitcCs$|��d}tr|��}t�|d�S)NrQ�?)r�rr�
PROC_STATUSESr�)r$�letterr?r?r@rQ�szProcess.statusc
Cs�g}t�d|j|jf�}d}|D�]b}d|j|j|f}zt|�}Wnzttfydd}Yq"Yq"ty�}zF|jtj	kr�WYd}~q"|jtj
kr�t|�WYd}~q"�WYd}~q"d}~00|�d�r"t
|�r"d|j|j|f}zXt|��:}t|����d�}	t|����dd�}
Wd�n1�s20YWnttf�yZd}Yq"0t|
�}t|t|�t|	�||
�}|�|�q"|�r�|��|S)	Nr&Fr'Tr�z%s/%s/fdinfo/%srr�)r{r*r#r�r|rr!r�r+r,r-rr�rrr�r�r}r�r`r�r�)
r$r�r�rrbrKrar�r��posrerdr�r?r?r@�
open_files�sJ
�
:
�zProcess.open_filesrcCst�||j�}|��|Sr1)r_r\r�r�)r$rZr�r?r?r@r`/	szProcess.net_connectionscCstt�d|j|jf��S)Nr&)r�r{r*r#r�r�r?r?r@�num_fds5	szProcess.num_fdscCst|��d�S)Nr�r�r�r?r?r@r�9	szProcess.ppidsUid:\t(\d+)\t(\d+)\t(\d+)cCs6|��}|�|�d\}}}t�t|�t|�t|��Sr)r�r
rZpuidsr�)r$Z_uids_rer��real�	effective�savedr?r?r@�uids=	szProcess.uidssGid:\t(\d+)\t(\d+)\t(\d+)cCs6|��}|�|�d\}}}t�t|�t|�t|��Sr)r�r
rZpgidsr�)r$Z_gids_rer�r6r7r8r?r?r@�gidsC	szProcess.gids)N)N)r)=r<r=r>r]r�r%r�r�r�r�rr�r�r�r�r�r�r�r�r�r�r{rarG�getpidr�r�r�rr�rr�HAS_PROC_SMAPSr	r�r�rr
rrrrrr!r#�HAS_CPU_AFFINITYr$r'r*�HAS_PROC_IO_PRIORITYr-r.r�r/rQr4r`r5r�r9r:r?r?r?r@r��s�%




	
 
	



�
K
�



�







3

r�)N)r)F)F)�r]�
__future__rr;r�r+r�r�r{r�rr=�sysr�rrrTrrrr�r	rkr
rrr
rrrrrrrrrrrrrrrrZ_compatrrr r!r"r#r+Z__extra__all__r�rarGr;r<r�hasattrr>r=r�r�Zgetpagesizer�r��	byteorderr9r��	AF_PACKETr8�IntEnumr�r7r$r%r&r'r;�globalsr3�__members__ZSTATUS_RUNNINGZSTATUS_SLEEPINGZSTATUS_DISK_SLEEPZSTATUS_STOPPEDZSTATUS_TRACING_STOPZ
STATUS_ZOMBIEZSTATUS_DEADZSTATUS_WAKE_KILLZ
STATUS_WAKINGZSTATUS_IDLEZ
STATUS_PARKEDr1r(r)r*r+r,r-r.r/r0r1r2rIrNrZr`rfr�rgrkr�rnrprqr|r�r�r��	Exceptionr�r�r��resource�ImportErrorr��CDLLr�r��dirr�r�r�r�r�r�rrrrZnet_if_addrsrrr_r`rgrn�
disk_usager�r�r�r�r�r�r�r�r2r�r�r�r�r?r?r?r@�<module>sb






�
�����
���

(

�
@<+
�
)u
/"
hK
,v_ PKok\�Dˤ��*psutil/__pycache__/_psposix.cpython-39.pycnu�[���a

��?h+ �@spdZddlZddlZddlZddlZddlZddlmZddlmZddlm	Z	ddlm
Z
ddlmZdd	lm
Z
dd
lmZddlmZddlmZdd
lmZddlmZddlmZer�ddlmZe
r�ddlZndZgd�Zdd�Zedu�r*eed��r*e�dedd�ejD���Zdd�Zndd�Zddeje edej�e!ej"efdd�Z#dd�Z$e	d d!��Z%dS)"z%Routines common to all posix systems.�N�)�MACOS��TimeoutExpired)�memoize)�
sdiskusage)�
usage_percent)�PY3)�ChildProcessError)�FileNotFoundError)�InterruptedError)�PermissionError)�ProcessLookupError)�unicode)�_psutil_osx)�
pid_exists�wait_pid�
disk_usage�get_terminal_mapcCsL|dkrdSzt�|d�Wn&ty0YdStyBYdS0dSdS)z6Check whether pid exists in the current process table.rTFN)�os�killrr
)�pid�r�;/usr/local/lib64/python3.9/site-packages/psutil/_psposix.pyr(sr�Signals�	NegsignalcCsg|]}|j|jf�qSr)�name�value)�.0�xrrr�
<listcomp>B�r cCs&z
t|�WSty |YS0dS)z+Convert a negative signal value to an enum.N)r�
ValueError��numrrr�negsig_to_enumEs
r%cCs|S)Nrr#rrrr%Ns�	monotoniccs��dkrd}t|��d}	d}
�dur8|
tjO}
�����������fdd�}zt��|
�\}}
Wn>ty~||	�}	YqPty�|��r�||	�}	q�YdS0|dkr�||	�}	qPt�|
�r�t�|
�St�|
�r�t	t�
|
��Std|
��qPdS)a�Wait for a process PID to terminate.

    If the process terminated normally by calling exit(3) or _exit(2),
    or by returning from main(), the return value is the positive integer
    passed to *exit().

    If it was terminated by a signal it returns the negated value of the
    signal which caused the termination (e.g. -SIGTERM).

    If PID is not a children of os.getpid() (current process) just
    wait until the process disappears and return None.

    If PID does not exist at all return None immediately.

    If *timeout* != None and process is still alive raise TimeoutExpired.
    timeout=0 is also possible (either return immediately or raise).
    rzcan't wait for PID 0g-C��6?Ncs6�dur ���kr t���d���|��|dd�S)N)rr�g{�G�z�?r)�interval��_min�_sleep�_timerr�	proc_nameZstop_at�timeoutrr�sleepws

zwait_pid.<locals>.sleepzunknown process exit status %r)r"r�WNOHANG�waitpidrr
�	WIFEXITED�WEXITSTATUS�WIFSIGNALEDr%�WTERMSIG)rr.r-�_waitpidr,r*r+Z_pid_exists�msgr(�flagsr/Zretpid�statusrr)rrRs2






rcCs�trt�|�}n`zt�|�}WnPtynt|t�rhz|�t���}WntyZYn0t�|�}n�Yn0|j	|j
}|j|j
}|j|j
}||}t
r�t�||�}||}t||dd�}t||||d�S)a.Return disk usage associated with path.
    Note: UNIX usually reserves 5% disk space which is not accessible
    by user. In this function "total" and "used" values reflect the
    total and used disk space whereas "free" and "percent" represent
    the "free" and "used percent" user disk space.
    r)Zround_)�total�used�free�percent)r	r�statvfs�UnicodeEncodeError�
isinstancer�encode�sys�getfilesystemencoding�f_blocks�f_frsize�f_bfree�f_bavailrrZdisk_usage_usedrr)�path�str:Z
avail_to_rootZ
avail_to_userr;Z
total_userZusage_percent_userrrrr�s.
�rc	Cs^i}t�d�t�d�}|D]<}||vs0J|��z||t�|�j<WqtyVYq0q|S)zNGet a map of device-id -> path as a dict.
    Used by Process.terminal().
    z	/dev/tty*z
/dev/pts/*)�globr�stat�st_rdevr)�retZlsrrrrr�sr)&�__doc__rJr�signalrB�time�_commonrrrrrZ_compatr	r
rrr
rr�r�enum�__all__r�hasattr�IntEnum�dictrrr%r1�getattr�minr/rrrrrrr�<module>sR
�
	�
_5PKok\q�-��-�-)psutil/__pycache__/_compat.cpython-39.pycnu�[���a

��?h�;�@sdZddlZddlZddlZddlZddlZddlZddlZgd�Zej	ddkZ
e�Ze
rze
ZeZeZeZeZdd�ZneZeZeZeZdd�Ze
r�eZneZeedfd	d
�Ze
r�eZeZeZeZeZeZn�ddlZefdd�Zee �d
d��Zee �dd��Zee �dd��Zee �dd��Zee �dd��Zee �dd��Ze�!�dk�r�ze"ej#d��Wn2e�ytYn e"�y�dZ$e%e$��Yn0zddlm&Z&Wn�e'�y<zddl(m)Z)Wn e'�y�ddl*m)Z)Yn0e�+dgd��Z,Gd d!�d!e-�Z.efe/e
ee0e1d�f�e2e3e1e4fd"d#�Z5d5d&d'�Z&Yn0zdd(l6m7Z7Wn*e'�yxej8ej9Bdfd)d*�Z7Yn0zdd+l6m:Z:Wne'�y�d6d-d.�Z:Yn0zdd/l;m<Z=Wn$e'�y�Gd0d1�d1e�Z=Yn0zdd2lm>Z>Wn"e'�yej?d3d4��Z>Yn0dS)7z�Module which provides compatibility with older Python versions.
This is more future-compatible rather than the opposite (prefer latest
Python 3 way of doing things).
�N)�PY3�long�range�super�unicode�
basestring�b�	lru_cache�which�get_terminal_size�redirect_stderr�FileNotFoundError�PermissionError�ProcessLookupError�InterruptedError�ChildProcessError�FileExistsError�cCs
|�d�S)Nzlatin-1)�encode��s�r�:/usr/local/lib64/python3.9/site-packages/psutil/_compat.pyr2srcCs|S�Nrrrrrr;s�cCsd|tu�rHt�|�}z|j|jjd}Wn"ttfyLd}t|��Yn0z
|j	}WnBt
tfy�z|jj	}Wnt
y�d}t|��Yn0Yn0|D]�}|j�
�D]�}zNt|tj�s�t|t�r�|j}q�z
|j}Wq�t
y�|�||�}Yq�0q�Wnt
tf�yYq�Yn0|j|jur��q4q�q��qHq�d}t|��|tu�r\t||�St|�S)zuLike Python 3 builtin super(). If called without any arguments
        it attempts to infer them at runtime.
        rz'super() used in a function with no argsz$super() used in a non-newstyle classzsuper() called outside a method)�	_SENTINEL�sys�	_getframe�f_locals�f_code�co_varnames�
IndexError�KeyError�RuntimeError�__mro__�AttributeError�	__class__�__dict__�values�
isinstance�types�FunctionType�property�fget�__func__�__get__�	TypeError�	func_code�_builtin_super)�type_Ztype_or_objZ
framedepth�f�msg�mro�methrrrrJsH







rcs�fdd�}|S)Ncs*G��fdd�d����j�_�j�_�S)Ncs2eZdZ��fdd�ZG�fdd�de�Z�ZS)zE_instance_checking_exception.<locals>.wrapped.<locals>.TemporaryClasscsht|�dkrNt|d��rN|d}t|�D] }|�d�s*t||t||��q*nt�|�j|i|��dS)Nrr�__)�lenr)�dir�
startswith�setattr�getattrr�__init__)�self�args�kwargsZ	unwrap_me�attr)�TemporaryClassr&rrr>�s

��zN_instance_checking_exception.<locals>.wrapped.<locals>.TemporaryClass.__init__cs eZdZ�fdd�Zdd�ZdS)zS_instance_checking_exception.<locals>.wrapped.<locals>.TemporaryClass.__metaclass__cs�|�Srr)�cls�inst��instance_checkerrr�__instancecheck__�sze_instance_checking_exception.<locals>.wrapped.<locals>.TemporaryClass.__metaclass__.__instancecheck__cSst��d}t||�S�Nr)r�exc_infor))rDZ	classinfo�valuerrr�__subclasscheck__�sze_instance_checking_exception.<locals>.wrapped.<locals>.TemporaryClass.__metaclass__.__subclasscheck__N)�__name__�
__module__�__qualname__rHrLrrFrr�
__metaclass__�srP)rMrNrOr>�typerP�
__classcell__r�rCrG)r&rrC�srC)rM�__doc__rF��base_exceptionrSr�wrapped�sz-_instance_checking_exception.<locals>.wrappedr)rVrWrrUr�_instance_checking_exception�srXcCst|dt�tjkS�N�errno)r=rrZ�ENOENT�rErrrr
�sr
cCst|dt�tjkSrY)r=rrZZESRCHr\rrrr�srcCst|dt�tjtjfvSrY)r=rrZ�EACCES�EPERMr\rrrr�srcCst|dt�tjkSrY)r=rrZZEINTRr\rrrr�srcCst|dt�tjkSrY)r=rrZ�ECHILDr\rrrr�srcCst|dt�tjkSrY)r=rrZ�EEXISTr\rrrr�sr�CPython�permzbbroken or incompatible Python implementation, see: https://github.com/giampaolo/psutil/issues/1659)r	)�RLock�	CacheInfo)�hits�misses�maxsize�currsizec@s$eZdZdZefdd�Zdd�ZdS)�
_HashedSeq��	hashvaluecCs||dd�<||�|_dSrrj)r?�tup�hashrrrr>�sz_HashedSeq.__init__cCs|jSrrj)r?rrr�__hash__�sz_HashedSeq.__hash__N)rMrNrO�	__slots__rmr>rnrrrrri�sric	s�|}	|r.||���}
|	|7}	|
D]}|	|7}	q |rl|	|�fdd�|D��7}	|r�|	|�fdd�|
D��7}	n$||	�dkr��|	d�|vr�|	dSt|	�S)Nc3s|]}�|�VqdSrr)�.0�v�rQrr�	<genexpr>�z_make_key.<locals>.<genexpr>c3s|]\}}�|�VqdSrr)rp�krqrrrrrsrtrr)�itemsri)r@�kwds�typed�kwd_mark�	fasttypes�sorted�tuplerQr9�key�sorted_items�itemrrrr�	_make_key�s
r��dFcs��fdd�}|S)zLeast-recently-used cache decorator, see:
        http://docs.python.org/3/library/functools.html#functools.lru_cache.
        csi�ddg�
d\��t�
�j�t�t��	g���ddg�dd�<�g�d\�����dkrl��
�fdd�}nP�dur������
��
��f	dd�}n*����������	�
���
��fdd�}����	��
fdd	�}��	��
fd
d�}�|_||_||_t�|��S)Nr)rr)rr�rcs"�|i|��}��d7<|SrIr)r@rw�result)�MISSES�stats�
user_functionrr�wrappersz7lru_cache.<locals>.decorating_function.<locals>.wrappercs\�||��}�|��}|�ur2��d7<|S�|i|��}|�|<��d7<|SrIr)r@rwr}r�)	�HITSr��cache�	cache_get�make_key�rootr�rxr�rrr�!s
cs�|s�r�
||��}n|}�	��z��|�}|dur��\}|\}}}}||�<||�<|�}||�<|�<||�<||�<�
�d7<|W�	��SW�	��n
�	��0�|i|��}�	��z��\}|�vr�n�����k�r4|}	||	�<||	�<|	�}�d<|�}
d|�<|�<�|
=|	�|<n,|�}||||g}||�<|�<�|<�
�d7<W�	��n
�	��0|S)Nrr)�acquire�release)r@rwr}�linkr�Z	link_prevZ	link_nextr��lastZoldrootZoldkey)r��KEYr��NEXT�PREV�RESULT�_lenr�r��lockr�rg�
nonlocal_rootr�rxr�rrr�.sR�
cs<���z$t�����t���W���S���0dS)zReport cache statistics.N)r��
_CacheInfor9r�r)r�r�r�r�rgr�rr�
cache_info[s��z:lru_cache.<locals>.decorating_function.<locals>.cache_infocsX���z@����d}||ddg|dd�<ddg�dd�<W���n
���0dS)z%Clear the cache and cache statistics.rN)r��clearr�)r�)r�r�r�r�rr�cache_clearesz;lru_cache.<locals>.decorating_function.<locals>.cache_clear)	r��getr9rc�__wrapped__r�r��	functools�update_wrapper)r�r�r�r��rgrx)r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�decorating_functions,
*-
z&lru_cache.<locals>.decorating_functionr)rgrxr�rr�rr	sir	)r
cs"dd�}tj���r&|�|�r"�SdS|dur>tj�dtj�}|sFdS|�tj�}tj	dkr�tj
|vrt|�dtj
�tj�dd��tj�}t�fd	d
�|D��r��g}q‡fdd�|D�}n�g}t
�}|D]P}tj�|�}||vr�|�|�|D](}	tj�||	�}
||
|�r�|
Sq�q�dS)
aJGiven a command, mode, and a PATH string, return the path which
        conforms to the given mode on the PATH, or None if there is no such
        file.

        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
        of os.environ.get("PATH"), or can be overridden with a custom search
        path.
        cSs&tj�|�o$t�||�o$tj�|�Sr)�os�path�exists�access�isdir)�fn�moderrr�
_access_check�s

��zwhich.<locals>._access_checkN�PATH�win32r�PATHEXT�c3s |]}����|���VqdSr)�lower�endswith�rp�ext��cmdrrrs�rtzwhich.<locals>.<genexpr>csg|]}�|�qSrrr�r�rr�
<listcomp>�rtzwhich.<locals>.<listcomp>)r�r��dirname�environr��defpath�split�pathsepr�platform�curdir�insert�any�set�normcase�add�join)r�r�r�r��pathext�files�seenr:�normdir�thefile�namerr�rr
}s8





r
)r��P�cCszzddl}ddl}ddl}Wnty2|YS0z*|�d|�d|jd��}|d|dfWStyt|YS0dS)Nr�hhrZ1234)�fcntl�struct�termios�ImportError�unpack�ioctl�
TIOCGWINSZ�	Exception)�fallbackr�r�r��resrrrr�s
�r)�TimeoutExpiredc@seZdZdS)�SubprocessTimeoutExpiredN)rMrNrOrrrrr��sr�)rccs*tj}z|t_|VW|t_n|t_0dSr)r�stderr)�
new_target�originalrrrr�s
r)r�F)r�)@rT�collections�
contextlibrZr�r�rr*�__all__�version_infor�objectr�intrr�xrange�strrrrrr2r
rrrrrr�r�rX�EnvironmentError�python_implementation�OSErrorr`r5r#r	r��	threadingrcZdummy_threading�
namedtupler��listrir��	frozensetrQr{r|r9r��shutilr
�F_OK�X_OKr�
subprocessr�r�r�contextmanagerrrrr�<module>s�

;





�	��
r5PKok\<�RR(psutil/__pycache__/_psbsd.cpython-39.pycnu�[���a

��?h�}�@s�dZddlZddlZddlZddlZddlmZddlmZddlm	Z	ddl
mZddl
mZdd	l
m
Zdd
l
mZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!gZ"e�r�ej#ej$ej%ej&ej'ej(ej)ej*ej+ej,ej-ej.ej/ej0iZ1n~e�r�ej#ej$ej'ej(ej)ej*ej2ej,ej+ej,ej%ej3ej4ej&iZ1n:e�r�ej#ej$ej'ej(ej)ej*ej+ej,ej%ej3ej4ej&iZ1ej5ej6ej7ej8ej9ej:ej;ej<ej=ej>ej?ej@ejAejBejCejDejEejFejGejHejIejJejKejLiZMe�N�ZOejPZPeQed�ZReQed�ZSeQed�ZTeQed�ZUeVdddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6�ZWed7gd8��ZXed9gd:��ZYed;gd<��ZZeZZ[ed=gd>��Z\ed?d@�Z]edAdB�Z^e�r8edCgdD��Z_nedCgdE��Z_dFdG�Z`dHdI�ZadJdK�ZbeR�rndLd�ZcndMd�ZcdNec_ddOdP�Zee�s�e�r�dQdR�ZfndSdR�ZfdTdU�Zge�r�dVdW�Zhne�r�dXdW�ZhdvdYdZ�ZiejjZjejkZkejlZlejmZmd[d\�Znd]d^�Zoe�rd_d`�Zpdadb�Zqdcdd�Zrdedf�Zsedgdh��Ztdidj�Zue�rDdkdl�Zvne�rTdmdl�ZvnejvZvdndo�Zwdpdq�Zxejydrds��ZzGdtdu�du�Z{dS)wz5FreeBSD, OpenBSD and NetBSD platforms implementation.�N)�defaultdict)�
namedtuple)�ElementTree�)�_common)�_psposix)�_psutil_bsd)�
_psutil_posix)�FREEBSD)�NETBSD)�OPENBSD)�AccessDenied)�
NoSuchProcess)�
ZombieProcess)�	conn_tmap)�conn_to_ntuple)�debug)�memoize)�memoize_when_activated)�
usage_percent)�FileNotFoundError)�PermissionError)�ProcessLookupError)�which�
per_cpu_times�proc_num_threads�proc_open_files�proc_num_fds��������	�
���
�����������)�ppid�status�real_uid�
effective_uid�	saved_uid�real_gid�
effective_gid�	saved_gid�ttynr�create_time�ctx_switches_vol�ctx_switches_unvol�
read_io_count�write_io_count�	user_time�sys_time�ch_user_time�ch_sys_time�rss�vms�memtext�memdata�memstack�cpunum�name�svmem)�total�	available�percent�used�free�active�inactive�buffers�cached�shared�wired�	scputimes��user�nice�system�idle�irq�pmem)rGrH�text�data�stack�	pcputimes)r\r^�
children_user�children_system�
pmmap_grouped�*path rss, private, ref_count, shadow_count�	pmmap_ext�6addr, perms path rss, private, ref_count, shadow_count�sdiskio)�
read_count�write_count�
read_bytes�write_bytesZ	read_timeZ
write_timeZ	busy_time)rmrnrorpcCs�t��}tr�|\}}}}}}tdd��X}|D]B}|�d�rPt|��d�d}	q,|�d�r,t|��d�d}
q,Wd�n1s�0Y||}||}n,|\}}}}}}}	}
|||}|||}t|||dd�}
t|||
|||||	||
|�S)Nz
/proc/meminfo�rbsBuffers:ris
MemShared:�Zround_)	�cextZvirtual_memr�open�
startswith�int�splitrrN)ZmemrOrSrTrUrYrW�f�linerVrXrRZavailrQ�rz�9/usr/local/lib64/python3.9/site-packages/psutil/_psbsd.py�virtual_memory�s8

4
�r|cCs4t��\}}}}}t||dd�}t�||||||�S)z@System swap memory as (total, used, free, sin, sout) namedtuple.rrr)rsZswap_memrrZsswap)rOrRrS�sinZsoutrQrzrzr{�swap_memory�sr~cCs"t��\}}}}}t|||||�S)z,Return system per-CPU times as a namedtuple.)rs�	cpu_timesrZr[rzrzr{r�srcCs>g}t��D],}|\}}}}}t|||||�}|�|�q|S)�(Return system CPU times as a namedtuple.)rsrrZ�append)�retZcpu_tr\r]r^r_r`�itemrzrzr{r�scCs2t�dkrt�gStjr$d}t|��dt_t�gS)r�r�&supported only starting from FreeBSD 8T)�cpu_count_logicalrr�
__called__�NotImplementedError)�msgrzrzr{r
s
FcCst��S)z0Return the number of logical CPUs in the system.)rsr�rzrzrzr{r�sr�cCst�dkrdSdS)Nr)r�rzrzrzr{�cpu_count_coressr�cCs�d}t��}|durj|�d�}|dkrj|d|d�}t�|�}zt|�d��pRd}W|��n
|��0|s|t�dkr|dS|S)z-Return the number of CPU cores in the system.Nz	</groups>���r%zgroup/children/group/cpur)	rsZcpu_topology�rfindr�
fromstring�len�findall�clearr�)r��s�index�rootrzrzr{r�$s


c	Cs�trt��\}}}}}n�tr�t��\}}}}}}}tdd��4}|D]}|�d�rBt|��d�}qBWd�q�1sv0Yntr�t��\}}}}}}}t	�
||||�S)z*Return various CPU stats as a named tuple.z
/proc/statrqsintrrN)r
rs�	cpu_statsrrtrurvrwrrZ	scpustats)	ZctxswZintrsZ
soft_intrsZsyscallsZ_trapsZ_faults�_forksrxryrzrzr{r�?s�
2�r�c
Cs�g}t�}t|�D]�}zt�|�\}}Wnty>YqYn0|r�z t|�d�d�d�d�}Wnttfy~d}Yn0z t|�d�d�d�d�}Wnttfy�d}Yn0|�	t
�|||��q|S)z�Return frequency metrics for CPUs. As of Dec 2018 only
        CPU 0 appears to be supported by FreeBSD and all other cores
        match the frequency of CPU 0.
        � r��/rN)r��rangers�cpu_freqr�rvrw�
IndexError�
ValueErrorr�r�scpufreq)r��num_cpus�cpu�currentZavailable_freqZmin_freqZmax_freqrzrzr{r�as$
 
 
r�cCstt���}t�|dd�gS)Ng)�floatrsr�rr�)�currrzrzr{r�{sc	Cs@g}t��}|D]*}|\}}}}t�||||�}|�|�q|S)z�Return mounted disk partitions as a list of namedtuples.
    'all' argument is ignored, see:
    https://github.com/giampaolo/psutil/issues/906.
    )rs�disk_partitionsrZ	sdiskpartr�)	�all�retlistZ
partitions�	partitionZdeviceZ
mountpointZfstype�opts�ntuplerzrzr{r��sr�c
Cs�t���}i}|D]�}z&t�|�}t�|�}t�|�\}}Wn2tyn}z|jtjkrZ�WYd}~qd}~00t	t
d�r�t
�|�}d�|�}d|v}	t
�
|	||||�||<q|S)z)Get NIC stats (isup, duplex, speed, mtu).N�	NicDuplex�,�running)�net_io_counters�keys�
cext_posixZ
net_if_mtuZnet_if_flagsZnet_if_duplex_speed�OSError�errnoZENODEV�hasattrrr��joinZ	snicstats)
�namesr�rMZmtu�flagsZduplex�speed�errZoutput_flagsZisuprzrzr{�net_if_stats�s$






�
r�c
Cs�|tjvr*td|d�dd�tD��f��t|\}}t�}trPt�d||�}ntrbt�d|�}nt�||�}|D]6}|\}}}}	}
}}t	||||	|
|t
|�}
|�|
�qrt|�S)z System-wide network connections.�+invalid %r kind argument; choose between %s�, cSsg|]}t|��qSrz��repr��.0�xrzrzr{�
<listcomp>��z#net_connections.<locals>.<listcomp>r�)
rrr�r��setrrs�net_connectionsrr�TCP_STATUSES�add�list)�kind�families�typesr��rawlistr��fd�fam�type�laddr�raddrr6�pid�ntrzrzr{r��s(
���r�cCsbzt��\}}}Wnty&YdS0|dk}|r<tj}n|dkrLtj}n|d}t�|||�S)zReturn battery info.Nrr��<)rs�sensors_batteryr�rZPOWER_TIME_UNLIMITEDZPOWER_TIME_UNKNOWNZsbattery)rQZminsleftZ
power_pluggedZsecsleftrzrzr{r��sr�c	Csttt�}t�}t|�D]X}z@t�|�\}}|dkr6d}d|}|d�t�||||��Wqt	ylYq0q|S)z?Return CPU cores temperatures if available, else an empty dict.rNzCore %sZcoretemp)
rr�r�r�rsZsensors_cpu_temperaturer�rZshwtempr�)r�r�r�r��highrMrzrzr{�sensors_temperatures�s�r�cCst��S)z:The system boot time expressed in seconds since the epoch.)rs�	boot_timerzrzrzr{r�sr�c	Csfg}t��}|D]P}|\}}}}}|dkr6ts2J�d}|dkr@qt�||pLd|||�}|�|�q|S)z:Return currently connected users as a list of namedtuples.r�N�~)rs�usersrrZsuserr�)	r�r�r�r\�tty�hostnameZtstampr�r�rzrzr{r�sr�cCs@ztd���Wn&ty$YdSty6YdS0dSdS)NrFT)�ProcessrMrr
rzrzrzr{�
_pid_0_existssr�cCs*t��}tr&d|vr&t�r&|�dd�|S)z7Returns a list of PIDs currently running on the system.r)rs�pidsrr��insert)r�rzrzr{r�'sr�cCs t�|�}|s|t�vSdSdS)NT�r�
pid_existsr��r��existsrzrzr{r�3s

r�cCs t�|�}|sdS|t�vSdS)NFr�r�rzrzr{r�>s
cCs>z$t�|�td}t�|�tjkWSty8YdS0dS)Nr6F)rs�proc_oneshot_info�kinfo_proc_map�
PROC_STATUSES�getr�
STATUS_ZOMBIEr�)r��strzrzr{�	is_zombieLs
r�cst����fdd��}|S)z`Decorator which translates bare OSError exceptions into
    NoSuchProcess and AccessDenied.
    cs�z�|g|�Ri|��WStyVt|j�rDt|j|j|j��nt|j|j��YnXtytt|j|j��Yn:t	y�|jdkr�dt
�vr�t|j|j��n��Yn0dS)Nr)rr�r�r�_name�_ppidrrr
r�r�)�self�args�kwargs��funrzr{�wrapperYs


z wrap_exceptions.<locals>.wrapper)�	functools�wraps)r�r�rzr�r{�wrap_exceptionsTsr�c	cspz
dVWn`ttfyLt|j�r:t|j|j|j��nt|j|j��Yn tyjt	|j|j��Yn0dS)z8Same as above, for routines relying on reading /proc fs.N)
rrr�r�rr�r�rrr
)�instrzrzr{�wrap_exceptions_procfsos

r�c@s�eZdZdZgd�Zdd�Zdd�Zeedd���Z	d	d
�Z
dd�Zed
d��Zedd��Z
edd��Zedd��Zedd��Zedd��Zedd��Zedd��Zedd��Zer�edd ��Zed!d"��ZeZed#d$��Zed%d&��Zed'd(��Zed)d*��ZedLd,d-��ZedMd/d0��Zed1d2��Zed3d4��Z ed5d6��Z!ed7d8��Z"ed9d:��Z#e$d;d<�Z%e$d;d=�Z&d>d?�Z'e(�r�ed@dA��Z)ne'Z)e*�r�edBdC��Z+ne'Z+e�r�edDdE��Z,edFdG��Z-edHdI��Z.edNdJdK��Z/d.S)Or�z1Wrapper class around underlying C implementation.)�_cacher�r�r�cCs||_d|_d|_dS�N)r�r�r�)r�r�rzrzr{�__init__�szProcess.__init__cCst�|j�dS)z+Raise NSP if the process disappeared on us.N)rs�	proc_namer��r�rzrzr{�
_assert_alive�szProcess._assert_alivecCs$t�|j�}t|�tt�ks J�|S)z;Retrieves multiple process info in one shot as a raw tuple.)rsr�r�r�r��r�r�rzrzr{�oneshot�szProcess.oneshotcCs|j�|�dSr�)r�Zcache_activater�rzrzr{�
oneshot_enter�szProcess.oneshot_entercCs|j�|�dSr�)r�Zcache_deactivater�rzrzr{�oneshot_exit�szProcess.oneshot_exitcCs(|��td}|dur|St�|j�S)NrM)r�r�rsr�r�)r�rMrzrzr{rM�szProcess.namecCs�tr|jdkrdSt�|j�Strj|jdkr0dSt|�� t�d|j�Wd�S1s^0Yn |��}|r�t	|d�p�dSdSdS)Nr�z/proc/%s/exe)
r
r�rsZproc_exerr��os�readlink�cmdliner)r�rrzrzr{�exe�s


0zProcess.exec
Cs�tr|jdkrgStr�zt�|j�WSty�}zt|jtjkr�t|j�r^t	|j|j
|j��q�t|j�s|t
|j|j
|j��q�td|�gWYd}~Sn�WYd}~q�d}~00nt�|j�SdS)Nrz'ignoring %r and returning an empty list)rr�rrsZproc_cmdliner�r��EINVALr�rr�r�r�rr)r�r�rzrzr{r�s

zProcess.cmdlinecCst�|j�Sr�)rsZproc_environr�r�rzrzr{�environ�szProcess.environcCs<|��td}t��}z
||WSty6YdS0dS)Nr=)r�r�rZget_terminal_map�KeyError)r�Ztty_nrZtmaprzrzr{�terminal�s
zProcess.terminalcCs|��td|_|jS)Nr5)r�r�r�r�rzrzr{r5�szProcess.ppidcCs.|��}t�|td|td|td�S)Nr7r8r9)r�rZpuidsr��r�Zrawtuplerzrzr{�uids�s


�zProcess.uidscCs.|��}t�|td|td|td�S)Nr:r;r<)r�rZpgidsr�rrzrzr{�gids�s


�zProcess.gidscCs8|��}t�|td|td|td|td�S)NrCrDrErF)r�rrer�rrzrzr{r�s



�zProcess.cpu_timescCs|��tdS)NrL�r�r�r�rzrzr{�cpu_numszProcess.cpu_numcCs@|��}t|td|td|td|td|td�S)NrGrHrIrJrK)r�rar�rrzrzr{�memory_info
s




�zProcess.memory_infocCs|��tdS)Nr>r
r�rzrzr{r>szProcess.create_timecCs trt�|j�St|���SdSr�)�HAS_PROC_NUM_THREADSrsrr�r��threadsr�rzrzr{�num_threadsszProcess.num_threadscCs$|��}t�|td|td�S)Nr?r@)r�rZpctxswr�rrzrzr{�num_ctx_switches#s


�zProcess.num_ctx_switchescCsHt�|j�}g}|D]"\}}}t�|||�}|�|�qtrD|��|Sr�)rsZproc_threadsr�rZpthreadr�rr�)r�r�r��	thread_id�utimeZstimer�rzrzr{r+szProcess.threads�inetc	Cs�|tvr(td|d�dd�tD��f��t|\}}g}trLt�|j|�}n&trbt�|j||�}nt�|j||�}|D]P}|dd�\}}}	}
}}t	r�||vsv|	|vr�qvt
|||	|
||t�}
|�|
�qv|�
�|S)Nr�r�cSsg|]}t|��qSrzr�r�rzrzr{r�<r�z+Process.net_connections.<locals>.<listcomp>r")rr�r�rrsr�r�rZproc_net_connectionsr
rr�r�r�)r�r�r�r�r�r�r�r�r�r�r�r�r6r�rzrzr{r�7s0���zProcess.net_connectionsNcCst�|j||j�Sr�)rZwait_pidr�r�)r��timeoutrzrzr{�waitUszProcess.waitcCst�|j�Sr�)r��getpriorityr�r�rzrzr{�nice_getYszProcess.nice_getcCst�|j|�Sr�)r��setpriorityr�)r��valuerzrzr{�nice_set]szProcess.nice_setcCs|��td}t�|d�S)Nr6�?)r�r�r�r�)r��coderzrzr{r6aszProcess.statuscCs(|��}t�|td|tddd�S)NrArBr�)r�rZpior�rrzrzr{�io_countersgs

�zProcess.io_counterscCs:tr|jdkrdStstr&t�|j�Sttr0dnd��dS)z)Return process current working directory.rr�r�N)rr�r�HAS_PROC_OPEN_FILESrsZproc_cwdr�r
r�rzrzr{�cwdqs
�zProcess.cwdZmmaprirkcCst�dSr�)r�r�rzrzr{�_not_implemented�szProcess._not_implementedcCst�|j�}dd�|D�S)z8Return files opened by process as a list of namedtuples.cSsg|]\}}t�||��qSrz)rZ	popenfile)r��pathr�rzrzr{r��r�z&Process.open_files.<locals>.<listcomp>)rsrr�)r�r�rzrzr{�
open_files�szProcess.open_filescCst�|j�}tr|��|S)z=Return the number of file descriptors opened by this process.)rsrr�rr�r�rzrzr{�num_fds�szProcess.num_fdscCst�|j�Sr�)rsZproc_cpu_affinity_getr�r�rzrzr{�cpu_affinity_get�szProcess.cpu_affinity_getc
Cs�tttt����}|D]}||vrtd||f��qzt�|j|�WnZty�}zB|j	t	j
t	jfvr�|D]}||vrltd||f��ql�WYd}~n
d}~00dS)Nz#invalid CPU #%i (choose between %s))�tupler�r�rr�rsZproc_cpu_affinity_setr�r�r�rZEDEADLK)r�ZcpusZallcpusr�r�rzrzr{�cpu_affinity_set�s$
���zProcess.cpu_affinity_setcCst�|j�Sr�)rsZproc_memory_mapsr�r�rzrzr{�memory_maps�szProcess.memory_mapscCsP|durt�|j|�St|�dkr2tdt|���|\}}t�|j|||�SdS)Nrz4second argument must be a (soft, hard) tuple, got %s)rsZproc_getrlimitr�r�r�r�Zproc_setrlimit)r��resourceZlimitsZsoft�hardrzrzr{�rlimit�s��zProcess.rlimit)r)N)N)0�__name__�
__module__�__qualname__�__doc__�	__slots__r�r�r�rr�r�r�rMrrrrr5rr	rr
rrZmemory_full_infor>rrrr�rrrr6rrrZnt_mmap_groupedZnt_mmap_extr rr"�HAS_PROC_NUM_FDSr#r$r&r'r*rzrzrzr{r��s�








	










	
��


r�)F)|r.�
contextlibr�r�r��collectionsrrZ	xml.etreerr�rrrrsr	r�r
rrr
rrrrrrrrZ_compatrrrrZ__extra__all__ZSIDLZSTATUS_IDLEZSRUNZSTATUS_RUNNINGZSSLEEPZSTATUS_SLEEPINGZSSTOPZSTATUS_STOPPEDZSZOMBr�ZSWAITZSTATUS_WAITINGZSLOCKZ
STATUS_LOCKEDr�ZSDEADZ
STATUS_WAKINGZSONPROCZTCPS_ESTABLISHEDZCONN_ESTABLISHEDZ
TCPS_SYN_SENTZ
CONN_SYN_SENTZTCPS_SYN_RECEIVEDZ
CONN_SYN_RECVZTCPS_FIN_WAIT_1ZCONN_FIN_WAIT1ZTCPS_FIN_WAIT_2ZCONN_FIN_WAIT2ZTCPS_TIME_WAITZCONN_TIME_WAITZTCPS_CLOSEDZ
CONN_CLOSEZTCPS_CLOSE_WAITZCONN_CLOSE_WAITZ
TCPS_LAST_ACKZ
CONN_LAST_ACKZTCPS_LISTENZCONN_LISTENZTCPS_CLOSINGZCONN_CLOSINGZPSUTIL_CONN_NONEZ	CONN_NONEr�ZgetpagesizeZPAGESIZEZAF_LINKr�ZHAS_PER_CPU_TIMESr
rr0�dictr�rNrZraZpfullmemrerhrjrlr|r~rrr�r�r�r�r�r��
disk_usageZdisk_io_countersr�Znet_if_addrsr�r�r�r�r�r�r�r�r�r�r��contextmanagerr�r�rzrzrzr{�<module>sB�	��
�



�$�����
/


 





	

PKok\s�L+t+tpsutil/_common.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Common objects shared by __init__.py and _ps*.py modules."""

# Note: this module is imported by setup.py so it should not import
# psutil or third-party modules.

from __future__ import division
from __future__ import print_function

import collections
import contextlib
import errno
import functools
import os
import socket
import stat
import sys
import threading
import warnings
from collections import namedtuple
from socket import AF_INET
from socket import SOCK_DGRAM
from socket import SOCK_STREAM


try:
    from socket import AF_INET6
except ImportError:
    AF_INET6 = None
try:
    from socket import AF_UNIX
except ImportError:
    AF_UNIX = None


# can't take it from _common.py as this script is imported by setup.py
PY3 = sys.version_info[0] >= 3
if PY3:
    import enum
else:
    enum = None


PSUTIL_DEBUG = bool(os.getenv('PSUTIL_DEBUG'))
_DEFAULT = object()

# fmt: off
__all__ = [
    # OS constants
    'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX',
    'SUNOS', 'WINDOWS',
    # connection constants
    'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED',
    'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN',
    'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT',
    # net constants
    'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN',
    # process status constants
    'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED',
    'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED',
    'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL',
    'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED',
    # other constants
    'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
    # named tuples
    'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile',
    'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart',
    'sdiskusage', 'snetio', 'snicaddr', 'snicstats', 'sswap', 'suser',
    # utility functions
    'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
    'parse_environ_block', 'path_exists_strict', 'usage_percent',
    'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
    'open_text', 'open_binary', 'cat', 'bcat',
    'bytes2human', 'conn_to_ntuple', 'debug',
    # shell utils
    'hilite', 'term_supports_colors', 'print_color',
]
# fmt: on


# ===================================================================
# --- OS constants
# ===================================================================


POSIX = os.name == "posix"
WINDOWS = os.name == "nt"
LINUX = sys.platform.startswith("linux")
MACOS = sys.platform.startswith("darwin")
OSX = MACOS  # deprecated alias
FREEBSD = sys.platform.startswith(("freebsd", "midnightbsd"))
OPENBSD = sys.platform.startswith("openbsd")
NETBSD = sys.platform.startswith("netbsd")
BSD = FREEBSD or OPENBSD or NETBSD
SUNOS = sys.platform.startswith(("sunos", "solaris"))
AIX = sys.platform.startswith("aix")


# ===================================================================
# --- API constants
# ===================================================================


# Process.status()
STATUS_RUNNING = "running"
STATUS_SLEEPING = "sleeping"
STATUS_DISK_SLEEP = "disk-sleep"
STATUS_STOPPED = "stopped"
STATUS_TRACING_STOP = "tracing-stop"
STATUS_ZOMBIE = "zombie"
STATUS_DEAD = "dead"
STATUS_WAKE_KILL = "wake-kill"
STATUS_WAKING = "waking"
STATUS_IDLE = "idle"  # Linux, macOS, FreeBSD
STATUS_LOCKED = "locked"  # FreeBSD
STATUS_WAITING = "waiting"  # FreeBSD
STATUS_SUSPENDED = "suspended"  # NetBSD
STATUS_PARKED = "parked"  # Linux

# Process.net_connections() and psutil.net_connections()
CONN_ESTABLISHED = "ESTABLISHED"
CONN_SYN_SENT = "SYN_SENT"
CONN_SYN_RECV = "SYN_RECV"
CONN_FIN_WAIT1 = "FIN_WAIT1"
CONN_FIN_WAIT2 = "FIN_WAIT2"
CONN_TIME_WAIT = "TIME_WAIT"
CONN_CLOSE = "CLOSE"
CONN_CLOSE_WAIT = "CLOSE_WAIT"
CONN_LAST_ACK = "LAST_ACK"
CONN_LISTEN = "LISTEN"
CONN_CLOSING = "CLOSING"
CONN_NONE = "NONE"

# net_if_stats()
if enum is None:
    NIC_DUPLEX_FULL = 2
    NIC_DUPLEX_HALF = 1
    NIC_DUPLEX_UNKNOWN = 0
else:

    class NicDuplex(enum.IntEnum):
        NIC_DUPLEX_FULL = 2
        NIC_DUPLEX_HALF = 1
        NIC_DUPLEX_UNKNOWN = 0

    globals().update(NicDuplex.__members__)

# sensors_battery()
if enum is None:
    POWER_TIME_UNKNOWN = -1
    POWER_TIME_UNLIMITED = -2
else:

    class BatteryTime(enum.IntEnum):
        POWER_TIME_UNKNOWN = -1
        POWER_TIME_UNLIMITED = -2

    globals().update(BatteryTime.__members__)

# --- others

ENCODING = sys.getfilesystemencoding()
if not PY3:
    ENCODING_ERRS = "replace"
else:
    try:
        ENCODING_ERRS = sys.getfilesystemencodeerrors()  # py 3.6
    except AttributeError:
        ENCODING_ERRS = "surrogateescape" if POSIX else "replace"


# ===================================================================
# --- namedtuples
# ===================================================================

# --- for system functions

# fmt: off
# psutil.swap_memory()
sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin',
                             'sout'])
# psutil.disk_usage()
sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent'])
# psutil.disk_io_counters()
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
                                 'read_bytes', 'write_bytes',
                                 'read_time', 'write_time'])
# psutil.disk_partitions()
sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
# psutil.net_io_counters()
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
                               'packets_sent', 'packets_recv',
                               'errin', 'errout',
                               'dropin', 'dropout'])
# psutil.users()
suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid'])
# psutil.net_connections()
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
                             'status', 'pid'])
# psutil.net_if_addrs()
snicaddr = namedtuple('snicaddr',
                      ['family', 'address', 'netmask', 'broadcast', 'ptp'])
# psutil.net_if_stats()
snicstats = namedtuple('snicstats',
                       ['isup', 'duplex', 'speed', 'mtu', 'flags'])
# psutil.cpu_stats()
scpustats = namedtuple(
    'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'])
# psutil.cpu_freq()
scpufreq = namedtuple('scpufreq', ['current', 'min', 'max'])
# psutil.sensors_temperatures()
shwtemp = namedtuple(
    'shwtemp', ['label', 'current', 'high', 'critical'])
# psutil.sensors_battery()
sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged'])
# psutil.sensors_fans()
sfan = namedtuple('sfan', ['label', 'current'])
# fmt: on

# --- for Process methods

# psutil.Process.cpu_times()
pcputimes = namedtuple(
    'pcputimes', ['user', 'system', 'children_user', 'children_system']
)
# psutil.Process.open_files()
popenfile = namedtuple('popenfile', ['path', 'fd'])
# psutil.Process.threads()
pthread = namedtuple('pthread', ['id', 'user_time', 'system_time'])
# psutil.Process.uids()
puids = namedtuple('puids', ['real', 'effective', 'saved'])
# psutil.Process.gids()
pgids = namedtuple('pgids', ['real', 'effective', 'saved'])
# psutil.Process.io_counters()
pio = namedtuple(
    'pio', ['read_count', 'write_count', 'read_bytes', 'write_bytes']
)
# psutil.Process.ionice()
pionice = namedtuple('pionice', ['ioclass', 'value'])
# psutil.Process.ctx_switches()
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
# psutil.Process.net_connections()
pconn = namedtuple(
    'pconn', ['fd', 'family', 'type', 'laddr', 'raddr', 'status']
)

# psutil.net_connections() and psutil.Process.net_connections()
addr = namedtuple('addr', ['ip', 'port'])


# ===================================================================
# --- Process.net_connections() 'kind' parameter mapping
# ===================================================================


conn_tmap = {
    "all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
    "tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]),
    "tcp4": ([AF_INET], [SOCK_STREAM]),
    "udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]),
    "udp4": ([AF_INET], [SOCK_DGRAM]),
    "inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
    "inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]),
    "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
}

if AF_INET6 is not None:
    conn_tmap.update({
        "tcp6": ([AF_INET6], [SOCK_STREAM]),
        "udp6": ([AF_INET6], [SOCK_DGRAM]),
    })

if AF_UNIX is not None:
    conn_tmap.update({"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM])})


# =====================================================================
# --- Exceptions
# =====================================================================


class Error(Exception):
    """Base exception class. All other psutil exceptions inherit
    from this one.
    """

    __module__ = 'psutil'

    def _infodict(self, attrs):
        info = collections.OrderedDict()
        for name in attrs:
            value = getattr(self, name, None)
            if value:  # noqa
                info[name] = value
            elif name == "pid" and value == 0:
                info[name] = value
        return info

    def __str__(self):
        # invoked on `raise Error`
        info = self._infodict(("pid", "ppid", "name"))
        if info:
            details = "(%s)" % ", ".join(
                ["%s=%r" % (k, v) for k, v in info.items()]
            )
        else:
            details = None
        return " ".join([x for x in (getattr(self, "msg", ""), details) if x])

    def __repr__(self):
        # invoked on `repr(Error)`
        info = self._infodict(("pid", "ppid", "name", "seconds", "msg"))
        details = ", ".join(["%s=%r" % (k, v) for k, v in info.items()])
        return "psutil.%s(%s)" % (self.__class__.__name__, details)


class NoSuchProcess(Error):
    """Exception raised when a process with a certain PID doesn't
    or no longer exists.
    """

    __module__ = 'psutil'

    def __init__(self, pid, name=None, msg=None):
        Error.__init__(self)
        self.pid = pid
        self.name = name
        self.msg = msg or "process no longer exists"

    def __reduce__(self):
        return (self.__class__, (self.pid, self.name, self.msg))


class ZombieProcess(NoSuchProcess):
    """Exception raised when querying a zombie process. This is
    raised on macOS, BSD and Solaris only, and not always: depending
    on the query the OS may be able to succeed anyway.
    On Linux all zombie processes are querable (hence this is never
    raised). Windows doesn't have zombie processes.
    """

    __module__ = 'psutil'

    def __init__(self, pid, name=None, ppid=None, msg=None):
        NoSuchProcess.__init__(self, pid, name, msg)
        self.ppid = ppid
        self.msg = msg or "PID still exists but it's a zombie"

    def __reduce__(self):
        return (self.__class__, (self.pid, self.name, self.ppid, self.msg))


class AccessDenied(Error):
    """Exception raised when permission to perform an action is denied."""

    __module__ = 'psutil'

    def __init__(self, pid=None, name=None, msg=None):
        Error.__init__(self)
        self.pid = pid
        self.name = name
        self.msg = msg or ""

    def __reduce__(self):
        return (self.__class__, (self.pid, self.name, self.msg))


class TimeoutExpired(Error):
    """Raised on Process.wait(timeout) if timeout expires and process
    is still alive.
    """

    __module__ = 'psutil'

    def __init__(self, seconds, pid=None, name=None):
        Error.__init__(self)
        self.seconds = seconds
        self.pid = pid
        self.name = name
        self.msg = "timeout after %s seconds" % seconds

    def __reduce__(self):
        return (self.__class__, (self.seconds, self.pid, self.name))


# ===================================================================
# --- utils
# ===================================================================


# This should be in _compat.py rather than here, but does not work well
# with setup.py importing this module via a sys.path trick.
if PY3:
    if isinstance(__builtins__, dict):  # cpython
        exec_ = __builtins__["exec"]
    else:  # pypy
        exec_ = getattr(__builtins__, "exec")  # noqa

    exec_("""def raise_from(value, from_value):
    try:
        raise value from from_value
    finally:
        value = None
    """)
else:

    def raise_from(value, from_value):
        raise value


def usage_percent(used, total, round_=None):
    """Calculate percentage usage of 'used' against 'total'."""
    try:
        ret = (float(used) / total) * 100
    except ZeroDivisionError:
        return 0.0
    else:
        if round_ is not None:
            ret = round(ret, round_)
        return ret


def memoize(fun):
    """A simple memoize decorator for functions supporting (hashable)
    positional arguments.
    It also provides a cache_clear() function for clearing the cache:

    >>> @memoize
    ... def foo()
    ...     return 1
        ...
    >>> foo()
    1
    >>> foo.cache_clear()
    >>>

    It supports:
     - functions
     - classes (acts as a @singleton)
     - staticmethods
     - classmethods

    It does NOT support:
     - methods
    """

    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        key = (args, frozenset(sorted(kwargs.items())))
        try:
            return cache[key]
        except KeyError:
            try:
                ret = cache[key] = fun(*args, **kwargs)
            except Exception as err:  # noqa: BLE001
                raise raise_from(err, None)
            return ret

    def cache_clear():
        """Clear cache."""
        cache.clear()

    cache = {}
    wrapper.cache_clear = cache_clear
    return wrapper


def memoize_when_activated(fun):
    """A memoize decorator which is disabled by default. It can be
    activated and deactivated on request.
    For efficiency reasons it can be used only against class methods
    accepting no arguments.

    >>> class Foo:
    ...     @memoize
    ...     def foo()
    ...         print(1)
    ...
    >>> f = Foo()
    >>> # deactivated (default)
    >>> foo()
    1
    >>> foo()
    1
    >>>
    >>> # activated
    >>> foo.cache_activate(self)
    >>> foo()
    1
    >>> foo()
    >>> foo()
    >>>
    """

    @functools.wraps(fun)
    def wrapper(self):
        try:
            # case 1: we previously entered oneshot() ctx
            ret = self._cache[fun]
        except AttributeError:
            # case 2: we never entered oneshot() ctx
            try:
                return fun(self)
            except Exception as err:  # noqa: BLE001
                raise raise_from(err, None)
        except KeyError:
            # case 3: we entered oneshot() ctx but there's no cache
            # for this entry yet
            try:
                ret = fun(self)
            except Exception as err:  # noqa: BLE001
                raise raise_from(err, None)
            try:
                self._cache[fun] = ret
            except AttributeError:
                # multi-threading race condition, see:
                # https://github.com/giampaolo/psutil/issues/1948
                pass
        return ret

    def cache_activate(proc):
        """Activate cache. Expects a Process instance. Cache will be
        stored as a "_cache" instance attribute.
        """
        proc._cache = {}

    def cache_deactivate(proc):
        """Deactivate and clear cache."""
        try:
            del proc._cache
        except AttributeError:
            pass

    wrapper.cache_activate = cache_activate
    wrapper.cache_deactivate = cache_deactivate
    return wrapper


def isfile_strict(path):
    """Same as os.path.isfile() but does not swallow EACCES / EPERM
    exceptions, see:
    http://mail.python.org/pipermail/python-dev/2012-June/120787.html.
    """
    try:
        st = os.stat(path)
    except OSError as err:
        if err.errno in (errno.EPERM, errno.EACCES):
            raise
        return False
    else:
        return stat.S_ISREG(st.st_mode)


def path_exists_strict(path):
    """Same as os.path.exists() but does not swallow EACCES / EPERM
    exceptions. See:
    http://mail.python.org/pipermail/python-dev/2012-June/120787.html.
    """
    try:
        os.stat(path)
    except OSError as err:
        if err.errno in (errno.EPERM, errno.EACCES):
            raise
        return False
    else:
        return True


@memoize
def supports_ipv6():
    """Return True if IPv6 is supported on this platform."""
    if not socket.has_ipv6 or AF_INET6 is None:
        return False
    try:
        sock = socket.socket(AF_INET6, socket.SOCK_STREAM)
        with contextlib.closing(sock):
            sock.bind(("::1", 0))
        return True
    except socket.error:
        return False


def parse_environ_block(data):
    """Parse a C environ block of environment variables into a dictionary."""
    # The block is usually raw data from the target process.  It might contain
    # trailing garbage and lines that do not look like assignments.
    ret = {}
    pos = 0

    # localize global variable to speed up access.
    WINDOWS_ = WINDOWS
    while True:
        next_pos = data.find("\0", pos)
        # nul byte at the beginning or double nul byte means finish
        if next_pos <= pos:
            break
        # there might not be an equals sign
        equal_pos = data.find("=", pos, next_pos)
        if equal_pos > pos:
            key = data[pos:equal_pos]
            value = data[equal_pos + 1 : next_pos]
            # Windows expects environment variables to be uppercase only
            if WINDOWS_:
                key = key.upper()
            ret[key] = value
        pos = next_pos + 1

    return ret


def sockfam_to_enum(num):
    """Convert a numeric socket family value to an IntEnum member.
    If it's not a known member, return the numeric value itself.
    """
    if enum is None:
        return num
    else:  # pragma: no cover
        try:
            return socket.AddressFamily(num)
        except ValueError:
            return num


def socktype_to_enum(num):
    """Convert a numeric socket type value to an IntEnum member.
    If it's not a known member, return the numeric value itself.
    """
    if enum is None:
        return num
    else:  # pragma: no cover
        try:
            return socket.SocketKind(num)
        except ValueError:
            return num


def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None):
    """Convert a raw connection tuple to a proper ntuple."""
    if fam in (socket.AF_INET, AF_INET6):
        if laddr:
            laddr = addr(*laddr)
        if raddr:
            raddr = addr(*raddr)
    if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6):
        status = status_map.get(status, CONN_NONE)
    else:
        status = CONN_NONE  # ignore whatever C returned to us
    fam = sockfam_to_enum(fam)
    type_ = socktype_to_enum(type_)
    if pid is None:
        return pconn(fd, fam, type_, laddr, raddr, status)
    else:
        return sconn(fd, fam, type_, laddr, raddr, status, pid)


def deprecated_method(replacement):
    """A decorator which can be used to mark a method as deprecated
    'replcement' is the method name which will be called instead.
    """

    def outer(fun):
        msg = "%s() is deprecated and will be removed; use %s() instead" % (
            fun.__name__,
            replacement,
        )
        if fun.__doc__ is None:
            fun.__doc__ = msg

        @functools.wraps(fun)
        def inner(self, *args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
            return getattr(self, replacement)(*args, **kwargs)

        return inner

    return outer


class _WrapNumbers:
    """Watches numbers so that they don't overflow and wrap
    (reset to zero).
    """

    def __init__(self):
        self.lock = threading.Lock()
        self.cache = {}
        self.reminders = {}
        self.reminder_keys = {}

    def _add_dict(self, input_dict, name):
        assert name not in self.cache
        assert name not in self.reminders
        assert name not in self.reminder_keys
        self.cache[name] = input_dict
        self.reminders[name] = collections.defaultdict(int)
        self.reminder_keys[name] = collections.defaultdict(set)

    def _remove_dead_reminders(self, input_dict, name):
        """In case the number of keys changed between calls (e.g. a
        disk disappears) this removes the entry from self.reminders.
        """
        old_dict = self.cache[name]
        gone_keys = set(old_dict.keys()) - set(input_dict.keys())
        for gone_key in gone_keys:
            for remkey in self.reminder_keys[name][gone_key]:
                del self.reminders[name][remkey]
            del self.reminder_keys[name][gone_key]

    def run(self, input_dict, name):
        """Cache dict and sum numbers which overflow and wrap.
        Return an updated copy of `input_dict`.
        """
        if name not in self.cache:
            # This was the first call.
            self._add_dict(input_dict, name)
            return input_dict

        self._remove_dead_reminders(input_dict, name)

        old_dict = self.cache[name]
        new_dict = {}
        for key in input_dict:
            input_tuple = input_dict[key]
            try:
                old_tuple = old_dict[key]
            except KeyError:
                # The input dict has a new key (e.g. a new disk or NIC)
                # which didn't exist in the previous call.
                new_dict[key] = input_tuple
                continue

            bits = []
            for i in range(len(input_tuple)):
                input_value = input_tuple[i]
                old_value = old_tuple[i]
                remkey = (key, i)
                if input_value < old_value:
                    # it wrapped!
                    self.reminders[name][remkey] += old_value
                    self.reminder_keys[name][key].add(remkey)
                bits.append(input_value + self.reminders[name][remkey])

            new_dict[key] = tuple(bits)

        self.cache[name] = input_dict
        return new_dict

    def cache_clear(self, name=None):
        """Clear the internal cache, optionally only for function 'name'."""
        with self.lock:
            if name is None:
                self.cache.clear()
                self.reminders.clear()
                self.reminder_keys.clear()
            else:
                self.cache.pop(name, None)
                self.reminders.pop(name, None)
                self.reminder_keys.pop(name, None)

    def cache_info(self):
        """Return internal cache dicts as a tuple of 3 elements."""
        with self.lock:
            return (self.cache, self.reminders, self.reminder_keys)


def wrap_numbers(input_dict, name):
    """Given an `input_dict` and a function `name`, adjust the numbers
    which "wrap" (restart from zero) across different calls by adding
    "old value" to "new value" and return an updated dict.
    """
    with _wn.lock:
        return _wn.run(input_dict, name)


_wn = _WrapNumbers()
wrap_numbers.cache_clear = _wn.cache_clear
wrap_numbers.cache_info = _wn.cache_info


# The read buffer size for open() builtin. This (also) dictates how
# much data we read(2) when iterating over file lines as in:
#   >>> with open(file) as f:
#   ...    for line in f:
#   ...        ...
# Default per-line buffer size for binary files is 1K. For text files
# is 8K. We use a bigger buffer (32K) in order to have more consistent
# results when reading /proc pseudo files on Linux, see:
# https://github.com/giampaolo/psutil/issues/2050
# On Python 2 this also speeds up the reading of big files:
# (namely /proc/{pid}/smaps and /proc/net/*):
# https://github.com/giampaolo/psutil/issues/708
FILE_READ_BUFFER_SIZE = 32 * 1024


def open_binary(fname):
    return open(fname, "rb", buffering=FILE_READ_BUFFER_SIZE)


def open_text(fname):
    """On Python 3 opens a file in text mode by using fs encoding and
    a proper en/decoding errors handler.
    On Python 2 this is just an alias for open(name, 'rt').
    """
    if not PY3:
        return open(fname, buffering=FILE_READ_BUFFER_SIZE)

    # See:
    # https://github.com/giampaolo/psutil/issues/675
    # https://github.com/giampaolo/psutil/pull/733
    fobj = open(
        fname,
        buffering=FILE_READ_BUFFER_SIZE,
        encoding=ENCODING,
        errors=ENCODING_ERRS,
    )
    try:
        # Dictates per-line read(2) buffer size. Defaults is 8k. See:
        # https://github.com/giampaolo/psutil/issues/2050#issuecomment-1013387546
        fobj._CHUNK_SIZE = FILE_READ_BUFFER_SIZE
    except AttributeError:
        pass
    except Exception:
        fobj.close()
        raise

    return fobj


def cat(fname, fallback=_DEFAULT, _open=open_text):
    """Read entire file content and return it as a string. File is
    opened in text mode. If specified, `fallback` is the value
    returned in case of error, either if the file does not exist or
    it can't be read().
    """
    if fallback is _DEFAULT:
        with _open(fname) as f:
            return f.read()
    else:
        try:
            with _open(fname) as f:
                return f.read()
        except (IOError, OSError):
            return fallback


def bcat(fname, fallback=_DEFAULT):
    """Same as above but opens file in binary mode."""
    return cat(fname, fallback=fallback, _open=open_binary)


def bytes2human(n, format="%(value).1f%(symbol)s"):
    """Used by various scripts. See: http://goo.gl/zeJZl.

    >>> bytes2human(10000)
    '9.8K'
    >>> bytes2human(100001221)
    '95.4M'
    """
    symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
    prefix = {}
    for i, s in enumerate(symbols[1:]):
        prefix[s] = 1 << (i + 1) * 10
    for symbol in reversed(symbols[1:]):
        if abs(n) >= prefix[symbol]:
            value = float(n) / prefix[symbol]
            return format % locals()
    return format % dict(symbol=symbols[0], value=n)


def get_procfs_path():
    """Return updated psutil.PROCFS_PATH constant."""
    return sys.modules['psutil'].PROCFS_PATH


if PY3:

    def decode(s):
        return s.decode(encoding=ENCODING, errors=ENCODING_ERRS)

else:

    def decode(s):
        return s


# =====================================================================
# --- shell utils
# =====================================================================


@memoize
def term_supports_colors(file=sys.stdout):  # pragma: no cover
    if os.name == 'nt':
        return True
    try:
        import curses

        assert file.isatty()
        curses.setupterm()
        assert curses.tigetnum("colors") > 0
    except Exception:  # noqa: BLE001
        return False
    else:
        return True


def hilite(s, color=None, bold=False):  # pragma: no cover
    """Return an highlighted version of 'string'."""
    if not term_supports_colors():
        return s
    attr = []
    colors = dict(
        blue='34',
        brown='33',
        darkgrey='30',
        green='32',
        grey='37',
        lightblue='36',
        red='91',
        violet='35',
        yellow='93',
    )
    colors[None] = '29'
    try:
        color = colors[color]
    except KeyError:
        raise ValueError(
            "invalid color %r; choose between %s" % (list(colors.keys()))
        )
    attr.append(color)
    if bold:
        attr.append('1')
    return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s)


def print_color(
    s, color=None, bold=False, file=sys.stdout
):  # pragma: no cover
    """Print a colorized version of string."""
    if not term_supports_colors():
        print(s, file=file)  # NOQA
    elif POSIX:
        print(hilite(s, color, bold), file=file)  # NOQA
    else:
        import ctypes

        DEFAULT_COLOR = 7
        GetStdHandle = ctypes.windll.Kernel32.GetStdHandle
        SetConsoleTextAttribute = (
            ctypes.windll.Kernel32.SetConsoleTextAttribute
        )

        colors = dict(green=2, red=4, brown=6, yellow=6)
        colors[None] = DEFAULT_COLOR
        try:
            color = colors[color]
        except KeyError:
            raise ValueError(
                "invalid color %r; choose between %r"
                % (color, list(colors.keys()))
            )
        if bold and color <= 7:
            color += 8

        handle_id = -12 if file is sys.stderr else -11
        GetStdHandle.restype = ctypes.c_ulong
        handle = GetStdHandle(handle_id)
        SetConsoleTextAttribute(handle, color)
        try:
            print(s, file=file)  # NOQA
        finally:
            SetConsoleTextAttribute(handle, DEFAULT_COLOR)


def debug(msg):
    """If PSUTIL_DEBUG env var is set, print a debug message to stderr."""
    if PSUTIL_DEBUG:
        import inspect

        fname, lineno, _, _lines, _index = inspect.getframeinfo(
            inspect.currentframe().f_back
        )
        if isinstance(msg, Exception):
            if isinstance(msg, (OSError, IOError, EnvironmentError)):
                # ...because str(exc) may contain info about the file name
                msg = "ignoring %s" % msg
            else:
                msg = "ignoring %r" % msg
        print(  # noqa
            "psutil-debug [%s:%s]> %s" % (fname, lineno, msg), file=sys.stderr
        )
PKok\�*Ǘ�H�Hpsutil/_psaix.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'
# Copyright (c) 2017, Arnon Yaari
# All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""AIX platform implementation."""

import functools
import glob
import os
import re
import subprocess
import sys
from collections import namedtuple

from . import _common
from . import _psposix
from . import _psutil_aix as cext
from . import _psutil_posix as cext_posix
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import ZombieProcess
from ._common import conn_to_ntuple
from ._common import get_procfs_path
from ._common import memoize_when_activated
from ._common import usage_percent
from ._compat import PY3
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError


__extra__all__ = ["PROCFS_PATH"]


# =====================================================================
# --- globals
# =====================================================================


HAS_THREADS = hasattr(cext, "proc_threads")
HAS_NET_IO_COUNTERS = hasattr(cext, "net_io_counters")
HAS_PROC_IO_COUNTERS = hasattr(cext, "proc_io_counters")

PAGE_SIZE = cext_posix.getpagesize()
AF_LINK = cext_posix.AF_LINK

PROC_STATUSES = {
    cext.SIDL: _common.STATUS_IDLE,
    cext.SZOMB: _common.STATUS_ZOMBIE,
    cext.SACTIVE: _common.STATUS_RUNNING,
    cext.SSWAP: _common.STATUS_RUNNING,  # TODO what status is this?
    cext.SSTOP: _common.STATUS_STOPPED,
}

TCP_STATUSES = {
    cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
    cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
    cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
    cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
    cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
    cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
    cext.TCPS_CLOSED: _common.CONN_CLOSE,
    cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
    cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
    cext.TCPS_LISTEN: _common.CONN_LISTEN,
    cext.TCPS_CLOSING: _common.CONN_CLOSING,
    cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}

proc_info_map = dict(
    ppid=0,
    rss=1,
    vms=2,
    create_time=3,
    nice=4,
    num_threads=5,
    status=6,
    ttynr=7,
)


# =====================================================================
# --- named tuples
# =====================================================================


# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
# psutil.Process.memory_full_info()
pfullmem = pmem
# psutil.Process.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])


# =====================================================================
# --- memory
# =====================================================================


def virtual_memory():
    total, avail, free, _pinned, inuse = cext.virtual_mem()
    percent = usage_percent((total - avail), total, round_=1)
    return svmem(total, avail, percent, inuse, free)


def swap_memory():
    """Swap system memory as a (total, used, free, sin, sout) tuple."""
    total, free, sin, sout = cext.swap_mem()
    used = total - free
    percent = usage_percent(used, total, round_=1)
    return _common.sswap(total, used, free, percent, sin, sout)


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return system-wide CPU times as a named tuple."""
    ret = cext.per_cpu_times()
    return scputimes(*[sum(x) for x in zip(*ret)])


def per_cpu_times():
    """Return system per-CPU times as a list of named tuples."""
    ret = cext.per_cpu_times()
    return [scputimes(*x) for x in ret]


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    try:
        return os.sysconf("SC_NPROCESSORS_ONLN")
    except ValueError:
        # mimic os.cpu_count() behavior
        return None


def cpu_count_cores():
    cmd = ["lsdev", "-Cc", "processor"]
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    if PY3:
        stdout, stderr = (
            x.decode(sys.stdout.encoding) for x in (stdout, stderr)
        )
    if p.returncode != 0:
        raise RuntimeError("%r command error\n%s" % (cmd, stderr))
    processors = stdout.strip().splitlines()
    return len(processors) or None


def cpu_stats():
    """Return various CPU stats as a named tuple."""
    ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats()
    return _common.scpustats(
        ctx_switches, interrupts, soft_interrupts, syscalls
    )


# =====================================================================
# --- disks
# =====================================================================


disk_io_counters = cext.disk_io_counters
disk_usage = _psposix.disk_usage


def disk_partitions(all=False):
    """Return system disk partitions."""
    # TODO - the filtering logic should be better checked so that
    # it tries to reflect 'df' as much as possible
    retlist = []
    partitions = cext.disk_partitions()
    for partition in partitions:
        device, mountpoint, fstype, opts = partition
        if device == 'none':
            device = ''
        if not all:
            # Differently from, say, Linux, we don't have a list of
            # common fs types so the best we can do, AFAIK, is to
            # filter by filesystem having a total size > 0.
            if not disk_usage(mountpoint).total:
                continue
        ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
        retlist.append(ntuple)
    return retlist


# =====================================================================
# --- network
# =====================================================================


net_if_addrs = cext_posix.net_if_addrs

if HAS_NET_IO_COUNTERS:
    net_io_counters = cext.net_io_counters


def net_connections(kind, _pid=-1):
    """Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    """
    cmap = _common.conn_tmap
    if kind not in cmap:
        raise ValueError(
            "invalid %r kind argument; choose between %s"
            % (kind, ', '.join([repr(x) for x in cmap]))
        )
    families, types = _common.conn_tmap[kind]
    rawlist = cext.net_connections(_pid)
    ret = []
    for item in rawlist:
        fd, fam, type_, laddr, raddr, status, pid = item
        if fam not in families:
            continue
        if type_ not in types:
            continue
        nt = conn_to_ntuple(
            fd,
            fam,
            type_,
            laddr,
            raddr,
            status,
            TCP_STATUSES,
            pid=pid if _pid == -1 else None,
        )
        ret.append(nt)
    return ret


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    duplex_map = {"Full": NIC_DUPLEX_FULL, "Half": NIC_DUPLEX_HALF}
    names = set([x[0] for x in net_if_addrs()])
    ret = {}
    for name in names:
        mtu = cext_posix.net_if_mtu(name)
        flags = cext_posix.net_if_flags(name)

        # try to get speed and duplex
        # TODO: rewrite this in C (entstat forks, so use truss -f to follow.
        # looks like it is using an undocumented ioctl?)
        duplex = ""
        speed = 0
        p = subprocess.Popen(
            ["/usr/bin/entstat", "-d", name],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        stdout, stderr = p.communicate()
        if PY3:
            stdout, stderr = (
                x.decode(sys.stdout.encoding) for x in (stdout, stderr)
            )
        if p.returncode == 0:
            re_result = re.search(
                r"Running: (\d+) Mbps.*?(\w+) Duplex", stdout
            )
            if re_result is not None:
                speed = int(re_result.group(1))
                duplex = re_result.group(2)

        output_flags = ','.join(flags)
        isup = 'running' in flags
        duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
        ret[name] = _common.snicstats(isup, duplex, speed, mtu, output_flags)
    return ret


# =====================================================================
# --- other system functions
# =====================================================================


def boot_time():
    """The system boot time expressed in seconds since the epoch."""
    return cext.boot_time()


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    localhost = (':0.0', ':0')
    for item in rawlist:
        user, tty, hostname, tstamp, user_process, pid = item
        # note: the underlying C function includes entries about
        # system boot, run level and others.  We might want
        # to use them in the future.
        if not user_process:
            continue
        if hostname in localhost:
            hostname = 'localhost'
        nt = _common.suser(user, tty, hostname, tstamp, pid)
        retlist.append(nt)
    return retlist


# =====================================================================
# --- processes
# =====================================================================


def pids():
    """Returns a list of PIDs currently running on the system."""
    return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()]


def pid_exists(pid):
    """Check for the existence of a unix pid."""
    return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo"))


def wrap_exceptions(fun):
    """Call callable into a try/except clause and translate ENOENT,
    EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except (FileNotFoundError, ProcessLookupError):
            # ENOENT (no such file or directory) gets raised on open().
            # ESRCH (no such process) can get raised on read() if
            # process is gone in meantime.
            if not pid_exists(self.pid):
                raise NoSuchProcess(self.pid, self._name)
            else:
                raise ZombieProcess(self.pid, self._name, self._ppid)
        except PermissionError:
            raise AccessDenied(self.pid, self._name)

    return wrapper


class Process:
    """Wrapper class around underlying C implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "_procfs_path", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None
        self._procfs_path = get_procfs_path()

    def oneshot_enter(self):
        self._proc_basic_info.cache_activate(self)
        self._proc_cred.cache_activate(self)

    def oneshot_exit(self):
        self._proc_basic_info.cache_deactivate(self)
        self._proc_cred.cache_deactivate(self)

    @wrap_exceptions
    @memoize_when_activated
    def _proc_basic_info(self):
        return cext.proc_basic_info(self.pid, self._procfs_path)

    @wrap_exceptions
    @memoize_when_activated
    def _proc_cred(self):
        return cext.proc_cred(self.pid, self._procfs_path)

    @wrap_exceptions
    def name(self):
        if self.pid == 0:
            return "swapper"
        # note: max 16 characters
        return cext.proc_name(self.pid, self._procfs_path).rstrip("\x00")

    @wrap_exceptions
    def exe(self):
        # there is no way to get executable path in AIX other than to guess,
        # and guessing is more complex than what's in the wrapping class
        cmdline = self.cmdline()
        if not cmdline:
            return ''
        exe = cmdline[0]
        if os.path.sep in exe:
            # relative or absolute path
            if not os.path.isabs(exe):
                # if cwd has changed, we're out of luck - this may be wrong!
                exe = os.path.abspath(os.path.join(self.cwd(), exe))
            if (
                os.path.isabs(exe)
                and os.path.isfile(exe)
                and os.access(exe, os.X_OK)
            ):
                return exe
            # not found, move to search in PATH using basename only
            exe = os.path.basename(exe)
        # search for exe name PATH
        for path in os.environ["PATH"].split(":"):
            possible_exe = os.path.abspath(os.path.join(path, exe))
            if os.path.isfile(possible_exe) and os.access(
                possible_exe, os.X_OK
            ):
                return possible_exe
        return ''

    @wrap_exceptions
    def cmdline(self):
        return cext.proc_args(self.pid)

    @wrap_exceptions
    def environ(self):
        return cext.proc_environ(self.pid)

    @wrap_exceptions
    def create_time(self):
        return self._proc_basic_info()[proc_info_map['create_time']]

    @wrap_exceptions
    def num_threads(self):
        return self._proc_basic_info()[proc_info_map['num_threads']]

    if HAS_THREADS:

        @wrap_exceptions
        def threads(self):
            rawlist = cext.proc_threads(self.pid)
            retlist = []
            for thread_id, utime, stime in rawlist:
                ntuple = _common.pthread(thread_id, utime, stime)
                retlist.append(ntuple)
            # The underlying C implementation retrieves all OS threads
            # and filters them by PID.  At this point we can't tell whether
            # an empty list means there were no connections for process or
            # process is no longer active so we force NSP in case the PID
            # is no longer there.
            if not retlist:
                # will raise NSP if process is gone
                os.stat('%s/%s' % (self._procfs_path, self.pid))
            return retlist

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        ret = net_connections(kind, _pid=self.pid)
        # The underlying C implementation retrieves all OS connections
        # and filters them by PID.  At this point we can't tell whether
        # an empty list means there were no connections for process or
        # process is no longer active so we force NSP in case the PID
        # is no longer there.
        if not ret:
            # will raise NSP if process is gone
            os.stat('%s/%s' % (self._procfs_path, self.pid))
        return ret

    @wrap_exceptions
    def nice_get(self):
        return cext_posix.getpriority(self.pid)

    @wrap_exceptions
    def nice_set(self, value):
        return cext_posix.setpriority(self.pid, value)

    @wrap_exceptions
    def ppid(self):
        self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
        return self._ppid

    @wrap_exceptions
    def uids(self):
        real, effective, saved, _, _, _ = self._proc_cred()
        return _common.puids(real, effective, saved)

    @wrap_exceptions
    def gids(self):
        _, _, _, real, effective, saved = self._proc_cred()
        return _common.puids(real, effective, saved)

    @wrap_exceptions
    def cpu_times(self):
        t = cext.proc_cpu_times(self.pid, self._procfs_path)
        return _common.pcputimes(*t)

    @wrap_exceptions
    def terminal(self):
        ttydev = self._proc_basic_info()[proc_info_map['ttynr']]
        # convert from 64-bit dev_t to 32-bit dev_t and then map the device
        ttydev = ((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF)
        # try to match rdev of /dev/pts/* files ttydev
        for dev in glob.glob("/dev/**/*"):
            if os.stat(dev).st_rdev == ttydev:
                return dev
        return None

    @wrap_exceptions
    def cwd(self):
        procfs_path = self._procfs_path
        try:
            result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid))
            return result.rstrip('/')
        except FileNotFoundError:
            os.stat("%s/%s" % (procfs_path, self.pid))  # raise NSP or AD
            return ""

    @wrap_exceptions
    def memory_info(self):
        ret = self._proc_basic_info()
        rss = ret[proc_info_map['rss']] * 1024
        vms = ret[proc_info_map['vms']] * 1024
        return pmem(rss, vms)

    memory_full_info = memory_info

    @wrap_exceptions
    def status(self):
        code = self._proc_basic_info()[proc_info_map['status']]
        # XXX is '?' legit? (we're not supposed to return it anyway)
        return PROC_STATUSES.get(code, '?')

    def open_files(self):
        # TODO rewrite without using procfiles (stat /proc/pid/fd/* and then
        # find matching name of the inode)
        p = subprocess.Popen(
            ["/usr/bin/procfiles", "-n", str(self.pid)],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        stdout, stderr = p.communicate()
        if PY3:
            stdout, stderr = (
                x.decode(sys.stdout.encoding) for x in (stdout, stderr)
            )
        if "no such process" in stderr.lower():
            raise NoSuchProcess(self.pid, self._name)
        procfiles = re.findall(r"(\d+): S_IFREG.*name:(.*)\n", stdout)
        retlist = []
        for fd, path in procfiles:
            path = path.strip()
            if path.startswith("//"):
                path = path[1:]
            if path.lower() == "cannot be retrieved":
                continue
            retlist.append(_common.popenfile(path, int(fd)))
        return retlist

    @wrap_exceptions
    def num_fds(self):
        if self.pid == 0:  # no /proc/0/fd
            return 0
        return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))

    @wrap_exceptions
    def num_ctx_switches(self):
        return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))

    @wrap_exceptions
    def wait(self, timeout=None):
        return _psposix.wait_pid(self.pid, timeout, self._name)

    if HAS_PROC_IO_COUNTERS:

        @wrap_exceptions
        def io_counters(self):
            try:
                rc, wc, rb, wb = cext.proc_io_counters(self.pid)
            except OSError:
                # if process is terminated, proc_io_counters returns OSError
                # instead of NSP
                if not pid_exists(self.pid):
                    raise NoSuchProcess(self.pid, self._name)
                raise
            return _common.pio(rc, wc, rb, wb)
PKok\,��S??psutil/_psosx.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""macOS platform implementation."""

import errno
import functools
import os
from collections import namedtuple

from . import _common
from . import _psposix
from . import _psutil_osx as cext
from . import _psutil_posix as cext_posix
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import ZombieProcess
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import parse_environ_block
from ._common import usage_percent
from ._compat import PermissionError
from ._compat import ProcessLookupError


__extra__all__ = []


# =====================================================================
# --- globals
# =====================================================================


PAGESIZE = cext_posix.getpagesize()
AF_LINK = cext_posix.AF_LINK

TCP_STATUSES = {
    cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
    cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
    cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
    cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
    cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
    cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
    cext.TCPS_CLOSED: _common.CONN_CLOSE,
    cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
    cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
    cext.TCPS_LISTEN: _common.CONN_LISTEN,
    cext.TCPS_CLOSING: _common.CONN_CLOSING,
    cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}

PROC_STATUSES = {
    cext.SIDL: _common.STATUS_IDLE,
    cext.SRUN: _common.STATUS_RUNNING,
    cext.SSLEEP: _common.STATUS_SLEEPING,
    cext.SSTOP: _common.STATUS_STOPPED,
    cext.SZOMB: _common.STATUS_ZOMBIE,
}

kinfo_proc_map = dict(
    ppid=0,
    ruid=1,
    euid=2,
    suid=3,
    rgid=4,
    egid=5,
    sgid=6,
    ttynr=7,
    ctime=8,
    status=9,
    name=10,
)

pidtaskinfo_map = dict(
    cpuutime=0,
    cpustime=1,
    rss=2,
    vms=3,
    pfaults=4,
    pageins=5,
    numthreads=6,
    volctxsw=7,
)


# =====================================================================
# --- named tuples
# =====================================================================


# fmt: off
# psutil.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle'])
# psutil.virtual_memory()
svmem = namedtuple(
    'svmem', ['total', 'available', 'percent', 'used', 'free',
              'active', 'inactive', 'wired'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
# fmt: on


# =====================================================================
# --- memory
# =====================================================================


def virtual_memory():
    """System virtual memory as a namedtuple."""
    total, active, inactive, wired, free, speculative = cext.virtual_mem()
    # This is how Zabbix calculate avail and used mem:
    # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/
    #     osx/memory.c
    # Also see: https://github.com/giampaolo/psutil/issues/1277
    avail = inactive + free
    used = active + wired
    # This is NOT how Zabbix calculates free mem but it matches "free"
    # cmdline utility.
    free -= speculative
    percent = usage_percent((total - avail), total, round_=1)
    return svmem(total, avail, percent, used, free, active, inactive, wired)


def swap_memory():
    """Swap system memory as a (total, used, free, sin, sout) tuple."""
    total, used, free, sin, sout = cext.swap_mem()
    percent = usage_percent(used, total, round_=1)
    return _common.sswap(total, used, free, percent, sin, sout)


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return system CPU times as a namedtuple."""
    user, nice, system, idle = cext.cpu_times()
    return scputimes(user, nice, system, idle)


def per_cpu_times():
    """Return system CPU times as a named tuple."""
    ret = []
    for cpu_t in cext.per_cpu_times():
        user, nice, system, idle = cpu_t
        item = scputimes(user, nice, system, idle)
        ret.append(item)
    return ret


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    return cext.cpu_count_logical()


def cpu_count_cores():
    """Return the number of CPU cores in the system."""
    return cext.cpu_count_cores()


def cpu_stats():
    ctx_switches, interrupts, soft_interrupts, syscalls, _traps = (
        cext.cpu_stats()
    )
    return _common.scpustats(
        ctx_switches, interrupts, soft_interrupts, syscalls
    )


def cpu_freq():
    """Return CPU frequency.
    On macOS per-cpu frequency is not supported.
    Also, the returned frequency never changes, see:
    https://arstechnica.com/civis/viewtopic.php?f=19&t=465002.
    """
    curr, min_, max_ = cext.cpu_freq()
    return [_common.scpufreq(curr, min_, max_)]


# =====================================================================
# --- disks
# =====================================================================


disk_usage = _psposix.disk_usage
disk_io_counters = cext.disk_io_counters


def disk_partitions(all=False):
    """Return mounted disk partitions as a list of namedtuples."""
    retlist = []
    partitions = cext.disk_partitions()
    for partition in partitions:
        device, mountpoint, fstype, opts = partition
        if device == 'none':
            device = ''
        if not all:
            if not os.path.isabs(device) or not os.path.exists(device):
                continue
        ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
        retlist.append(ntuple)
    return retlist


# =====================================================================
# --- sensors
# =====================================================================


def sensors_battery():
    """Return battery information."""
    try:
        percent, minsleft, power_plugged = cext.sensors_battery()
    except NotImplementedError:
        # no power source - return None according to interface
        return None
    power_plugged = power_plugged == 1
    if power_plugged:
        secsleft = _common.POWER_TIME_UNLIMITED
    elif minsleft == -1:
        secsleft = _common.POWER_TIME_UNKNOWN
    else:
        secsleft = minsleft * 60
    return _common.sbattery(percent, secsleft, power_plugged)


# =====================================================================
# --- network
# =====================================================================


net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs


def net_connections(kind='inet'):
    """System-wide network connections."""
    # Note: on macOS this will fail with AccessDenied unless
    # the process is owned by root.
    ret = []
    for pid in pids():
        try:
            cons = Process(pid).net_connections(kind)
        except NoSuchProcess:
            continue
        else:
            if cons:
                for c in cons:
                    c = list(c) + [pid]
                    ret.append(_common.sconn(*c))
    return ret


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    names = net_io_counters().keys()
    ret = {}
    for name in names:
        try:
            mtu = cext_posix.net_if_mtu(name)
            flags = cext_posix.net_if_flags(name)
            duplex, speed = cext_posix.net_if_duplex_speed(name)
        except OSError as err:
            # https://github.com/giampaolo/psutil/issues/1279
            if err.errno != errno.ENODEV:
                raise
        else:
            if hasattr(_common, 'NicDuplex'):
                duplex = _common.NicDuplex(duplex)
            output_flags = ','.join(flags)
            isup = 'running' in flags
            ret[name] = _common.snicstats(
                isup, duplex, speed, mtu, output_flags
            )
    return ret


# =====================================================================
# --- other system functions
# =====================================================================


def boot_time():
    """The system boot time expressed in seconds since the epoch."""
    return cext.boot_time()


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    for item in rawlist:
        user, tty, hostname, tstamp, pid = item
        if tty == '~':
            continue  # reboot or shutdown
        if not tstamp:
            continue
        nt = _common.suser(user, tty or None, hostname or None, tstamp, pid)
        retlist.append(nt)
    return retlist


# =====================================================================
# --- processes
# =====================================================================


def pids():
    ls = cext.pids()
    if 0 not in ls:
        # On certain macOS versions pids() C doesn't return PID 0 but
        # "ps" does and the process is querable via sysctl():
        # https://travis-ci.org/giampaolo/psutil/jobs/309619941
        try:
            Process(0).create_time()
            ls.insert(0, 0)
        except NoSuchProcess:
            pass
        except AccessDenied:
            ls.insert(0, 0)
    return ls


pid_exists = _psposix.pid_exists


def is_zombie(pid):
    try:
        st = cext.proc_kinfo_oneshot(pid)[kinfo_proc_map['status']]
        return st == cext.SZOMB
    except OSError:
        return False


def wrap_exceptions(fun):
    """Decorator which translates bare OSError exceptions into
    NoSuchProcess and AccessDenied.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except ProcessLookupError:
            if is_zombie(self.pid):
                raise ZombieProcess(self.pid, self._name, self._ppid)
            else:
                raise NoSuchProcess(self.pid, self._name)
        except PermissionError:
            raise AccessDenied(self.pid, self._name)

    return wrapper


class Process:
    """Wrapper class around underlying C implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None

    @wrap_exceptions
    @memoize_when_activated
    def _get_kinfo_proc(self):
        # Note: should work with all PIDs without permission issues.
        ret = cext.proc_kinfo_oneshot(self.pid)
        assert len(ret) == len(kinfo_proc_map)
        return ret

    @wrap_exceptions
    @memoize_when_activated
    def _get_pidtaskinfo(self):
        # Note: should work for PIDs owned by user only.
        ret = cext.proc_pidtaskinfo_oneshot(self.pid)
        assert len(ret) == len(pidtaskinfo_map)
        return ret

    def oneshot_enter(self):
        self._get_kinfo_proc.cache_activate(self)
        self._get_pidtaskinfo.cache_activate(self)

    def oneshot_exit(self):
        self._get_kinfo_proc.cache_deactivate(self)
        self._get_pidtaskinfo.cache_deactivate(self)

    @wrap_exceptions
    def name(self):
        name = self._get_kinfo_proc()[kinfo_proc_map['name']]
        return name if name is not None else cext.proc_name(self.pid)

    @wrap_exceptions
    def exe(self):
        return cext.proc_exe(self.pid)

    @wrap_exceptions
    def cmdline(self):
        return cext.proc_cmdline(self.pid)

    @wrap_exceptions
    def environ(self):
        return parse_environ_block(cext.proc_environ(self.pid))

    @wrap_exceptions
    def ppid(self):
        self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']]
        return self._ppid

    @wrap_exceptions
    def cwd(self):
        return cext.proc_cwd(self.pid)

    @wrap_exceptions
    def uids(self):
        rawtuple = self._get_kinfo_proc()
        return _common.puids(
            rawtuple[kinfo_proc_map['ruid']],
            rawtuple[kinfo_proc_map['euid']],
            rawtuple[kinfo_proc_map['suid']],
        )

    @wrap_exceptions
    def gids(self):
        rawtuple = self._get_kinfo_proc()
        return _common.puids(
            rawtuple[kinfo_proc_map['rgid']],
            rawtuple[kinfo_proc_map['egid']],
            rawtuple[kinfo_proc_map['sgid']],
        )

    @wrap_exceptions
    def terminal(self):
        tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']]
        tmap = _psposix.get_terminal_map()
        try:
            return tmap[tty_nr]
        except KeyError:
            return None

    @wrap_exceptions
    def memory_info(self):
        rawtuple = self._get_pidtaskinfo()
        return pmem(
            rawtuple[pidtaskinfo_map['rss']],
            rawtuple[pidtaskinfo_map['vms']],
            rawtuple[pidtaskinfo_map['pfaults']],
            rawtuple[pidtaskinfo_map['pageins']],
        )

    @wrap_exceptions
    def memory_full_info(self):
        basic_mem = self.memory_info()
        uss = cext.proc_memory_uss(self.pid)
        return pfullmem(*basic_mem + (uss,))

    @wrap_exceptions
    def cpu_times(self):
        rawtuple = self._get_pidtaskinfo()
        return _common.pcputimes(
            rawtuple[pidtaskinfo_map['cpuutime']],
            rawtuple[pidtaskinfo_map['cpustime']],
            # children user / system times are not retrievable (set to 0)
            0.0,
            0.0,
        )

    @wrap_exceptions
    def create_time(self):
        return self._get_kinfo_proc()[kinfo_proc_map['ctime']]

    @wrap_exceptions
    def num_ctx_switches(self):
        # Unvoluntary value seems not to be available;
        # getrusage() numbers seems to confirm this theory.
        # We set it to 0.
        vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']]
        return _common.pctxsw(vol, 0)

    @wrap_exceptions
    def num_threads(self):
        return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']]

    @wrap_exceptions
    def open_files(self):
        if self.pid == 0:
            return []
        files = []
        rawlist = cext.proc_open_files(self.pid)
        for path, fd in rawlist:
            if isfile_strict(path):
                ntuple = _common.popenfile(path, fd)
                files.append(ntuple)
        return files

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        if kind not in conn_tmap:
            raise ValueError(
                "invalid %r kind argument; choose between %s"
                % (kind, ', '.join([repr(x) for x in conn_tmap]))
            )
        families, types = conn_tmap[kind]
        rawlist = cext.proc_net_connections(self.pid, families, types)
        ret = []
        for item in rawlist:
            fd, fam, type, laddr, raddr, status = item
            nt = conn_to_ntuple(
                fd, fam, type, laddr, raddr, status, TCP_STATUSES
            )
            ret.append(nt)
        return ret

    @wrap_exceptions
    def num_fds(self):
        if self.pid == 0:
            return 0
        return cext.proc_num_fds(self.pid)

    @wrap_exceptions
    def wait(self, timeout=None):
        return _psposix.wait_pid(self.pid, timeout, self._name)

    @wrap_exceptions
    def nice_get(self):
        return cext_posix.getpriority(self.pid)

    @wrap_exceptions
    def nice_set(self, value):
        return cext_posix.setpriority(self.pid, value)

    @wrap_exceptions
    def status(self):
        code = self._get_kinfo_proc()[kinfo_proc_map['status']]
        # XXX is '?' legit? (we're not supposed to return it anyway)
        return PROC_STATUSES.get(code, '?')

    @wrap_exceptions
    def threads(self):
        rawlist = cext.proc_threads(self.pid)
        retlist = []
        for thread_id, utime, stime in rawlist:
            ntuple = _common.pthread(thread_id, utime, stime)
            retlist.append(ntuple)
        return retlist
PKok\݄��psutil/_psutil_posix.abi3.sonuȯ��ELF>�"@@8	@#"PP   ]]@@@�M�]�]�M�]�]��888$$P�td�B�B�B��Q�tdR�td�M�]�]@@GNU�/���Ъ�+���O.����Y*!�8���*.4�ȷԸf���W�~����:hde���l�H�����������$���r:����B ����M<���(�� ����-n�6Nv��8 �R"�~�4W��#�]p%W��%)cP4
��4ia@#�~�b%j	 T7�P5�p$�__gmon_start___init_fini_ITM_deregisterTMCloneTable_ITM_registerTMCloneTable__cxa_finalizepsutil_PyErr_SetFromOSErrnoWithSyscall__errno_locationstrerrorsprintfPyExc_OSErrorPyObject_CallFunctionPyErr_SetObject_Py_DeallocNoSuchProcessAccessDeniedpsutil_check_pid_rangePyArg_ParseTuple_Py_NoneStructPyExc_ValueErrorPyErr_SetStringpsutil_set_debugPyObject_IsTruePSUTIL_DEBUGpsutil_setupgetenvsocketstrncpyioctlclosePy_BuildValuePyErr_SetFromErrno_Py_TrueStruct_Py_FalseStructsetprioritygetnameinfoPyList_NewgetifaddrsPyList_AppendfreeifaddrsgetpriorityPyUnicode_FromStringpsutil_getpagesizesysconfpsutil_pid_existskillpsutil_raise_for_pidPyExc_RuntimeErrorPyErr_FormatPyInit__psutil_posixPyModule_Create2PyModule_AddIntConstantPyLong_FromLongPyModule_AddObjectlibpthread.so.0libc.so.6GLIBC_2.2.5GLIBC_2.3+ ui	E;ii
Qui	E�]0#�]�"�]�]haVB�a�a�adB�a`4�apB�a�,b|Bb) b�B(bP-@b�BHb�&`b�Bhb&�b�B�b�'�_�_�_
�_�_�_�_�_�_1�_&�_(` `(`0`8`@`H`P`	X`
``h`p`.x`�`�`�`�`�`�`�`�`�`�`0�`�`�`�`*�`+�` a!a"a#a$ a%(a'0a(8a)H��H��?H��t�+H����5�?�%�?@�%�?h����%�?h�����%�?h����%�?h����%�?h����%�?h����%�?h����%�?h�p����%�?h�`����%�?h	�P����%�?h
�@����%�?h�0����%�?h� ����%z?h
�����%r?h�����%j?h���%b?h����%Z?h�����%R?h����%J?h����%B?h����%:?h����%2?h����%*?h�p����%"?h�`����%?h�P����%?h�@����%
?h�0����%?h� ����%�>h�����%�>h�����%�>h���%�>h ����%�>h!�����%�>h"����%�>h#����%�>h$���H�=9@H�2@H9�tH�=H��t	�����H�=	@H�5@H)�H��H��?H��H�H�tH�=H��t��fD���=�?u/UH�=�<H��tH�=�:�M����h�����?]�����{���f.��AUATI��UH������I��8H�����L��H�5�L��H��1������U1�L��L�%9<H�5�I�<$���I�<$H��H���
���H��tH�mtH��1�]A\A]��H������H��1�]A\A]ÐATH��H�5D1�USH��I��L���>���1�L��H��;H�5�H�;�.���H�;H��H�����H��tH�mtH��1�[]A\�fDH���H���H��1�[]A\�f.�ATH��H�5�1�USH��I��L�����1�L��
H�;H�5nH�;���H�;H��H����H��tH�mtH��1�[]A\�fDH�����H��1�[]A\�f.�H��H��H�5�1�H�T$�����t"�D$��x*H��:H�H���f.�1�H���f�H�a:H�52H�8�Z���1���fDH��H��H�5�1�H�T$�6�����t2H�|$������x$H�E:���҉H�&:H�H���D1�H���f�H��H�=B�P���H��t
H��9�1�H����UH��1�H�5�H��@H�T$���A��1�E��tc1Ҿ��:����Ń��tXL�D$H�t$�L��������!��D$H��1�������t����t$ H�=/1�����H��@]�f��k���H�$9H�8���H��@]�fDUH��1�H�5�H��@H�T$���A��1�E��tm1Ҿ�����Ń��thL�D$H�t$�L���l�������D$H��1��������t/�����D$ @tCH�5�8H�=�1�����H��@]�����H�d8H�8�,���H��@]�fDH�5Q8H�=�1�����H��@]�DH��H��H�51�H�L$H�T$����A��1�E��t�T$�t$1��������tH�8H�H���H��7H�8�����ff.�@H����AW��AV��AUATUSH����u\����H��E�H��E1�E1�j�H�����H����H�v7H�H��[]A\A]A^A_����u�D�wM��t�I��H��N�,7L��L�%D�SH��L��1�H��H������I9�u�K�vL��H�=��D�1�����fDH��H�=�1��g����h���f�H��6H��@AW1�AVAUATUSH��(����H�D$H����H�|$�c�������fH�l$H�����,���0H�i6H�I��I��H��H�uD��M��AUI��L��H�="1�����I��XZM����H�|$L��L�$�t���L�$����I�*�NI�,$�VH�+�^I�/�fI�m�nH�mH���wH�}H��t�D�7D�����H;�5I��t�H���=H�} D�����H��H���E�E��
���H�}(D�����I��H�l5H�I��M�������E1�H�|$H��t
L�$�^���L�$H�T$H�H�$H��H��M��t
I�*�BM��tI�,$�RH��t
H�+�cM��t
I�/�tM��tI�m��H�D$H�D$H��([]A\A]A^A_��L���x���I�,$�����L���e���H�+�����H���S���I�/�����L���A���I�m�����L���.���H�mH��������H�l$H���c����s���fDH�}(D���\���I��H�*4H�I��M����������DH��L�$���L�$M����������f.�L�������L����M����������f.�L���x�H����������f.�H���X�M����������f.�L���8�����H�|$E1�E1�1�E1�H����������f�H�|$E1�E1�E1�H��������H�
3E1�E1�1�E1�H�8���E1����f�UH��SH����H�T$H�5�H���H��1����A��1�E��t!�t$1��n�Ƌ��uH�=�1��8�H��[]ÐH��2H�8�Q�H��[]�f.�AU1�ATUH��H��@���H��t(I��H�T$1�H��H�5�?��uI�,$�`E1�H��@L��]A\A]�1Ҿ���Ń���TH�t$L�D$�L��������D$H��1������6�����l$ @����@���>@����@���:@����@�� ��@��@�@�ŀ�Rf����f����f���!f����f����f�� � f��@�Ef�����H�=��P�H��H������H��L���i��H�E�WH��H�E�����H�������f�L�������H�=����I��H���m���H��L���
��I�E��H��I�E����L���[����fDH�=���I��H������H��L�����I�EuuH��I�E�����L�����|���f.�H�=N�T�I��H������H��L���m��I�Eu%H��I�E�C���L�����6���f.�H��I�E�����L�����z���DH�=��t��d����H�=��\�I�,$���E1���H��@L��]A\A]�f.�H�=���I��H���
���H��L�����I�E�a���H��I�E�����L�����|���fDH�=M�D�I��H�������H��L���]��I�E����H��I�E�C���L�����6���fDH�=2���I��H���m���H��L���
��I�E�����H��I�E�=���L���[��0���L���N����f�H�=���I��H���
���H��L������I�E�a���H��I�E���L��������fDH�=��D�I��H�������H��L���]���I�E����H��I�E�����L�������fDH�=	���I��H���m���H��L���
���I�E�����H��I�E�����L���[���fDH�=I��I��H������H��L������I�E�q���H��I�E�����L�������fDH�=t�T�I��H������H��L���m���I�E�!���H��I�E�q���L�����d���fDH�=*��I��H���}���H��L������I�E����H��I�E�,���L���k�����fDH�=�
��I��H���-���H��L�������I�E�����H��I�E���L��������fDH�=�
�d�I��H������H��L���}���I�E�1���H��I�E�����L��������fDH�=j
��I��H�������H��L���-���I�E���H��I�E�~���L���{��q���H��H�E�M���H���`��@���ff.�����fDH���w�H�=�H��H��1����f���1��f�H��1����A���E��t*�����t��tH�+H�8����������1�H���f�UH��SH��H���o����tH��H��[]��������uH��H��[]���H��*H��H�5*H�8H��1�[]����AT�H�=�+��H�����	H�5�H��I����������H�5�L��������1�H�5�L���������H�5�L���|����l�H�5�L���`����P�H�5�L���D����4�H�5�L���(�����H�5�L���������H�5�L����������H�5pL����������
H�5aL���������H�5RL���������
H�5FL������ut�H�5:L���h���u\�H�50L���P���uD�H�5&L���8���u,H�������H��H��tH�5L������
�E1�L��A\�H��H���%s (originated from %s)(is)PSUTIL_DEBUGassume no such process (originated from %s)assume access denied (originated from %s)pid must be a positive integerii%02x:(siOOOO)socket(SOCK_DGRAM)ioctl(SIOCGIFFLAGS)upbroadcastdebugloopbackpointopointnotrailersnoarppromiscallmultimasterslavemulticastportselautomediadynamic%s syscall failedRLIMIT_ASRLIMIT_CORERLIMIT_CPURLIMIT_DATARLIMIT_FSIZERLIMIT_MEMLOCKRLIMIT_NOFILERLIMIT_NPROCRLIMIT_RSSRLIMIT_STACKRLIMIT_LOCKSRLIMIT_MSGQUEUERLIMIT_NICERLIMIT_RTPRIORLIMIT_RTTIMERLIMIT_SIGPENDINGRLIM_INFINITY_psutil_posixgetpagesizegetprioritynet_if_addrsnet_if_flagsnet_if_is_runningnet_if_mtusetpriority;�`������ �(��h@�������@���,��`@�|P���<��p�������� ���8zRx�$���`FJw�?;*3$"<D����B�B�D �G�j
 CBBHO CBB<�����B�M�A �G�L
 CABGO CAB<�@��B�M�A �G�L
 CABGO CAB��jD q
KF
J$��WD F
FFD �)Dd(\8��A�PP{
ACXA0����A�PP�
AIX
AGYA�h�aD H
D`���K�D�E �B(�A0�A8�G�\�H�P�Z
8A0A(B BBBI�������X<h��B�D�B �B(�A0�A8�D`]hLpXhA`l
8A0A(B BBBH0���vA�D�D0S
AABSAA@���B�D�A �G`y
 DBBA�
 DBBK��
$��DP<��WTB<T �iA�D�G O
DAHO
DALXCA�P�B��0#�"�]+; 
T7�]�]���o`��
[`x��	���o����o�oD���o�]6 F V f v � � � � � � � � !!&!6!F!V!f!v!�!�!�!�!�!�!�!�!""&"6"F"V"f"v"VB���������adB`4pB�,|B)�BP-�B�&�B&�B�'GCC: (GNU) 10.2.1 20210130 (Red Hat 10.2.1-11),@#�,p&Ql�] @#������XintW�x�W��c�����fvW�zbj}\T�gG�8+:	W;	W�	5j;=l�um@
);�nF��F��R;�R�	
W
g	^�}	�b�
3����,W�R�R�R�*W	R�LR�N3RR:vRPR��lWm���
���W�2
��W�%)���%�U	@��Rp%W�t}�Rb�,RC=��R�hx�	W���%�fU�TT	&BQ�h�%���R%j�}�"R��b�2R��pid���l%��U�TT	�@Q�lf%�T	�@P�Rp$��(��GCexc�R��msg�
(��w ��!m�R��"�!��R
	�$	Uv�$P�U��wT	`@Q�U�$3T	@Q=R��w�$Tv#�9$-�NsR�#��Ls�GCexctR��msgu
(��w `�!mzR��"�!�zR
	X$	Uv$PU��wT	0@Q�U"$37T	@Q3R��w0$Tv%\R@#��\4�IC�]
(��wexcdR�� �!mhR��"0!�hR"�#	UvT#�a#mx#P4U��wT	@R|�#3ZT	@R��w�#Tv8A�F &Qo��9�����Xintc�x�cE
�N��o�������R�N��f�c�zbvG
h�}	T�
NI/�;�h�Y�	R
��	�
�
��
4�	�q�� �
��_
�
 �!L
"�#1$�%�&O'�(�)*,+�,}-�
.�/v0�1�2�3�405|6$7H89L:p;�<,<�=�	>?�@�A�BC3D�E�F�G�H]I�J�K�L/Mk
N�O�PQR#S�T
UFVMW�X�Y7Z�[�\�]�^�_�`�ab�cdCeq	f�g�h%i�
j^k�lm�n�o�p>q	rs�t�uv�wx3yyz�{$|k}~	~K����E������
�����q�<�U	��
�6
�&�����~��	�`����=�K�{�q�����
���:�]
� �����f�����8��
��p�x���	�	�3�$���%
����
������L�'	�����P��4���O���k���^��
�f���U�����h�Y�������������
������0@�1G<3N\T�gG�	8�
+	:	c
	;	cm�5
j�
=
lS
u
m�)��
n�������
�c �
�,2cF��^
�RXcq� �	�
?~����
���& �A1���9 6
�
7�
�8�
]9c
;�9=��(
+U
�
,�
�
-Z
^
.S
�
/
� �U�
0
<�
�
=	c
�
>�Th
J	
�
K`
�
L�(
j
M�0
�

NS8
�
O	@
�
P	H
�
QFP
1
R�X

Sq`l������?N�	�6����Q�	���
8

.8WgfN$�	z�XL)�	�N?
y�
Ik�9

H��G�s

w�?

��
x
K
��
9
K
�
��
�
�
J
�
�
�
|�
�
�
9�
�
�
��)
��?

#�-
z�
h	���
�
.����?
�-G��PG99�'
��������
���\���'���
s
�
&�
1�
<�
G)R�]�h�s�~�����@�9
N+1
d
�3�
- �@g��^`�Q ]@���o�

Oq9
qr9
�sGirqt@dmau@
�v@��
���
��
9�MH�K
b�K
��K

�K
�K
!�\��c�
�c��1
w��
��
���(~u
��	�

&�	�
&��,�
�-�
8
�
!	�
�"N
�$�

X
%�
 
5	.u(
�8	�0�EG{ -
�	"�x;�gA�
g��w=	��/w9;�9G�9���
r�	9�	Gk�#3
F
G
�
�
�c
�G
�@

�@
��gj�P9 �g@	�a y�	@a!�^c��	�"�lc���#"@�c�!	�	�	c$E
�!�Bc!"9c4��"&��K�%L
^�!I4�tS!k(���#"�ac�c!j )c�c9#!�!rc�ccc!t
bc��	�c!*c��#!�
Kc:���!a"�Po!�
Lcp��o!/����c�"�����#!Nc���!d���!�����&�$2
�!#cvc"Uko.c'���P5�w(mod��\X(v����)c5p�*U	@a*T3)�5P�*U|*T	uA*Q9)�5P�*U|*T	A*Q4)�5P*U|*T	�A*Q0)�5PE*U|*T	�A*Q2)�5Po*U|*T	�A*Q1)6P�*U|*T	�A*Q8)(6P�*U|*T	�A*Q7)D6P�*U|*T	�A*Q6)`6P*U|*T	�A*Q5)|6PA*U|*T	�A*Q3)�6Pk*U|*T	�A*Q:)�6P�*U|*T	�A*Q<)�6P�*U|*T	B*Q=)�6P�*U|*T	B*Q>)7P*U|*T	(B*Q?)7P=*U|*T	6B*Q;)(7:U*U	�+?7*U|*T	HB,���&��-}�$���-b�4��� �����.��	cRF(ret�	c��/ifr�M�@0��)�&�E*U�T*T	�B*Q��)�&�f*U2*T2*Q0)'8�*U�@*Q?)'��*Uv*T
�)&'��*Uv)B't�*U	&B1U'�1d'�+�'t*U	&B,�	��P-���*-}��-b�/�WM �����.��	c��(ret�	c��/ifr�M��.�����.��\G?0�u2`&.�v���)�.K*U|+R1K*U|3�*�.�K54�*		4�*W	S	5�6�*�	�	7�*��6�*


+@4K*Uv8�*�.�6�*/
-
9�*�.6�*T
R
+�.K*Uv)�.4*U	[A+�.*U|*Tv:�*//P�:4�*y
w
4�*�
�
6�*�
�
8�*%/�;�*8�*//!6�*209�*//!6�*WU+E/K*U})/4*U	�@+#/*U|*T}:�*P/P/P�?4�*|z4�*��6�*��8�*u/�;�*8�*{/%6�*539�*{/%6�*ZX+�/K*U})\/4$*U	�@+s/*U|*T}:�*�/�/P�D4�*}4�*��6�*��8�*�/�;�*8�*�/%
6�*8
6
9�*�/%6�*]
[
+�/K*U})�/4)*U	�@+�/*U|*T}3�*�3ES4�*�
�
4�*�
�
56�*�
�
7�*@�6�*;9+0K*U}8�*46�*`^9�*46�*��+%4K*U})�347*U	QA+4*U|*T}:�*`0`0PX4�*��4�*��6�*�8�*�0�;�*8�*�0!6�*ca9�*�0!6�*��+�0K*U})l04=*U	�@+�0*U|*T}:�*�0�0P	] 4�*��4�*��6�*�8�*�0�;�*8�*�0!# 6�*fd9�*�0!6�*��+�0K*U})�04B *U	A+�0*U|*T}:�*11J3b!4�*��4�*��6�*	8�*%1� ;�*8�*/1(!6�*ig9�*/16�*��+E1K*U})14G!*U	9A+#1*U|*T}:�*`1`1P9g"4�*��4�*��6�*8�*�1�!;�*8�*�1!-"6�*lj9�*�1!6�*��+�1K*U})l14L"*U	?A+�1*U|*T}:�*�1�1P?l#4�*��4�*��6�*8�*�1�";�*8�*�1!2#6�*om9�*�1!6�*��+�1K*U})�14Q#*U	IA+�1*U|*T}:�*22Pq$4�*��4�*��6�*
8�*%2�#;�*8�*/2!7$6�*rp9�*/2!6�*��+E2K*U})24V$*U	A+#2*U|*T}:�*P2P2Pv%4�*��4�*��6�*
8�*u2�$;�*8�*2!<%6�*us9�*2!6�*��+�2K*U})\24[%*U	�B+s2*U|*T}:�*�2�2P{&4�*��4�*��6�*8�*�2�%;�*8�*�2!A&6�*xv9�*�2!6�*��+�2K*U})�24`&*U	A+�2*U|*T}:�*�2�2P!�'4�*��4�*��6�*8�*3�&;�*8�*3!F'6�*{y9�*3!6�*��+53K*U})�24e'*U	!A+3*U|*T}:�*@3@3P'�(4�*��4�*��6�*8�*e3�';�*8�*o3!K(6�*~|9�*o3!6�*��+�3K*U})L34j(*U	)A+c3*U|*T}:�*�3�3P-�)4�*��4�*��6�*!8�*�3�(;�*8�*�3!P)6�*�9�*�3!6�*��+�3K*U})�34o)*U	2A+�3*U|*T})c-^�)*U0)�-��)*Uv*T	�B*Q��)�-��)*U2*T2*Q0)�-8**U��*Q?)�-�+**Uv*T
�)�-�C**Uv)0�b**U	�@)40��**U	�@+I0�*Uv<I	�c+=���=��0�>		��?�*>��	�@>���@>���,���&��~,-}����-b�-� �����.��	cbX(ret�	c��/ifr�M�@0��)&��+*U�T*T	�B*Q��)6&��+*U2*T2*Q0)T&8
,*U�@*Q?)j&�,,*Uv*T
!�)v&�D,*Uv)�&tc,*U	�@1�&�1�&�,�*�)���1-}*�
-b*/�NJ B+��(ifa+��.�,	c��.�.�jd.9/���.�	0���.1���.r2�
 �.�3�D!*!A�v*2P�-.�l	�Y"Q"5P.�l	��"�"+(+K*U��2�3..�m	�%#!#5�.�m	�_#[#+;+K*U|2��..�n	��#�#5�.�n	��#�#+M+K*Us2��..�o	�
$	$5�.�o	�G$C$+_+K*U2/.�p	��$}$5.�p	��$�$+r+K*U}2@R/.�y��$�$+�+K*U��2p�/.mz�J%D%5�.�z��%�%1,K2��/.m{��%�%5.�{� &&+(,K*U|2@50.m|�\&V&5p.�|��&�&+H,K*Us2��0.m}��&�&5�.�}�2'.'+h,K*U2�0.m~�l'h'50.�~��'�'+�+K*U})%)^�0*U0)=)�1*U��)�)t81*U	�@*Q~*R|*Xs*Y)�)Z1*U��*T��)*�1r1*T~)?*�1�1*T~)b*�1�1*T~1�*�)�+��1*Uv)�+�1�1*T~1�,�B��x2C��(�
C��2cDbuf�
x2Derr�	cE,�	cDn�-Dlen�-E���Dptr��@>k�2��2F9�Bg
���2C}�$�Cb�4�Dpid��E��	cE 	�	cB���3C}�$�Cb�4�Dpid��E��	cGo��`4��3H}�(��'�'Hb�8�((1i4|4I~4t*U	OAJ���4i�R4Kpid�od(V(H�&�))1�4�L5��3*U�T)5R44*UsL!5�/4*U�TII5�*T	cA*Q�TM�]c|4Npid]�Dret^	cO�HoP4
��4IZ4*UNP�2�'a��54�2�)�)4�20***Q�2�hQ�2�l6�2�*|*R�2�'�'�a54�2�*�*4�2�*�*;�2;�2;�21�'�)�'��5*U�T*T	�@*Q�h*R�l+�'�*U0S�1(�c6T�1UT
2TQ2��w;"2;.2;:2;D2;P2;\2U�1�( �V
2V�15 Q2��w;"2;.2;:2QD2^;P2;\29h2�(;i2P�2�,v�p74�2
++4�2M+C+Q3�\63�+�+R�20-0-�74�2,,4�2;,9,;3;31?-�1�,�)�,�=7*Uv*T	�@*Q�\)-~T7*U0+(-t*U	�@PR4�4W�84c4b,^,6o4�,�,RR4�4�4]�74c4�,�,;o41�4�)�4�8*T01�4�Wi_%%$>$>&I:;9II:;9
:;9I8	7I
<4:;9I?<4:;9I?<
4:;9I4G:;9.?:;9'I<I.?:;9'<.?:;9'I<.?:;9'<.?:;9'I<.?:;9'I@�B��1���B.?:;9'I@�B:;9I�B4:;9I4:;9I�B��1��14:;9I U!4:;9I�B"U#I$!I/%.?:;9'I@�B%:;9I$>$>&II7I	:;9I
>I:;9(:;9

:;9I8<'II'4:;9I?<4:;9I?<'I>I:;9>I:;9((I!I/
:;9I8
:;9I8:;9
:;9I4:;9I 4:;9I!.?:;9'I<".?:;9'I<#$.?:;9'<%.?:;9'<&.?:;9'I<'.?:;9'I@�B(4:;9I�B)��1*���B+��1,.:;9'I@�B-:;9I�B.4:;9I�B/4:;9I0
:;91��12U31R�BUXYW41�B5U641�B71U8191:1R�BXYW;41<.:;9'I =:;9I>4:;9I?@A
:;9B.:;9'I C:;9ID4:;9IE4:;9IF!I/G.:;9'I@�BH:;9I�BI���B1J.?:;9'@�BK:;9I�BL���B1M.?:;9'I N:;9IO.?:;9'I@�BP.1@�BQ41R1R�BXYWS.1@�BT1U1R�BUXYWV1W.?<n:;k.�
psutil/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6m_psutil_common.ctypes.hstdio.htypes.hpyport.htime.hobject.hpyerrors.h_psutil_common.hstdlib.hmodsupport.habstract.hstring.herrno.h=	@#�=w:	�X:X<���I=�Xt����$n$\$����;=�Xt����#�#\#����;=�Xt����8�8yJ
Ct�L��z�4	�Y2�2J
@t�L	�
M
t��t�.��	K�	Y
���
psutil/opt/rh/devtoolset-10/root/usr/lib/gcc/x86_64-redhat-linux/10/include/usr/include/bits/usr/include/usr/include/sys/opt/python/cp36-cp36m/include/python3.6m/usr/include/netinet/usr/include/net/usr/include/asm-generic/usr/include/linux_psutil_posix.cstddef.htypes.hstdio.htypes.hunistd.hstdint.hpyport.htime.hobject.hboolobject.hmethodobject.hmoduleobject.hpyerrors.hresource.hresource.hsocket_type.hsockaddr.hsocket.hin.hconfname.hif.hifaddrs.hint-ll64.h	types.h
if_packet.h
_psutil_common.hnetdb.hlistobject.hunicodeobject.hmodsupport.hioctl.hsocket.hlongobject.hsignal.herrno.h<built-in>3	&�3v
J3v�
J�=-[/_fsY�	t.Z]'	Y�X:�t:zP:z�P�=-[/[fsY�	u.[Y	uR�	Y�X	ztPX:�|f:
JAt=-^�ZtKp�	t�:

�:s
.:s.
.:s<

�	Y�8	@	�	-��
^�
^X	#
	Y
Y��	�L
IY	\K�	Y
`�	lt�95`525*�XY�	��XJ
��	;	B	
' 	�
	������%L)J	�J	Z	K�q	?	0	��	=	�<
�
�tK	<�<XX	KXK�X�X�X�X�X��	l����������%L)J7�X�
]�
�tK		<.tXJt�����������z���	A�o;;-	D�v	
<:�~t:�Z�h>�-^�.L�fp.	�f5��5
35)�Y�t��J�=�~�/�fsY��u	X���������������	��~��	�	/Ij��t��	�~@��	�	/Ij���	7���	�	/I2���	=���	�	/I2���	� �����	/	;Z�	�����	�	/Ij���	����	�	/Ij���	��~��	�	/Ij��X��	B��~��	�	/Ij���	��~��	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	����	�	/Ij���	��~��	�	/Ij��X	���}�>��>KXuI��L.j�lJt=W	[
X.\dX
&�h�./�/	�X	g	EA 	
�
t	K	G? 	�=	I/ 	X	P5�0	�	X�	<�	�	<�	<�	<�	<�	<�	<�	<�	<�	<�	<N	<N	<N	<J	
�	Y����<tz_dsttimesyscallpsutil_setup/project_typeobject_objectob_refcntdoubleNoSuchProcessPy_ssize_tfloat_py_xdecref_tmplong long unsigned inttimezoneunsigned charpsutil_set_debugstrerror_py_decref_tmpPSUTIL_DEBUGshort unsigned intPyObject_IsTruepsutil_PyErr_SetFromOSErrnoWithSyscalltz_minuteswestPyObject_CallFunctionAccessDeniedpsutil/_psutil_common.cob_typeselfPyErr_SetObject__errno_locationPyObject__ssize_tfullmsglong long intGNU C17 10.2.1 20210130 (Red Hat 10.2.1-11) -mtune=generic -march=x86-64 -g -O3 -fwrapv -fPICPyArg_ParseTuplePyExc_ValueError_Py_Deallocshort intargsPSUTIL_CONN_NONE__pid_t_Py_NoneStructpsutil_check_pid_rangePyErr_SetStringsprintfgetenvPyExc_OSError_SC_EQUIV_CLASS_MAXifr_ifrnm_copyifa_addr_SC_THREAD_PRIO_PROTECTsin6_flowinfoifr_ifruPyModule_Create2getnameinfo__priority_which_t_SC_VERSIONPy_BuildValue_SC_NL_NMAXm_methods_longobjectslot_SC_SYNCHRONIZED_IO_SC_THREAD_PRIORITY_SCHEDULING_SC_NPROCESSORS_ONLNsa_datam_base_SC_TIMEOUTSsockaddr_SC_BASE_SC_PII_OSI_COTSsockaddr_un_SC_THREAD_SAFE_FUNCTIONS_SC_ATEXIT_MAXsockaddr_ns_SC_STREAM_MAXifru_slavepsutil_posix_getpriority_SC_PRIORITIZED_IOpy_ptp_SC_V6_ILP32_OFF32_SC_THREAD_SPORADIC_SERVERsll_pkttype__socket_typeifu_dstaddr_SC_SHRT_MIN_SC_USHRT_MAX_SC_NL_TEXTMAX_SC_STREAMS__rlimit_resourceIFF_PORTSEL_SC_THREAD_DESTRUCTOR_ITERATIONS_SC_PIPE_SC_BC_DIM_MAXpsutil_getpagesize_SC_MAPPED_FILES_SC_2_C_BIND_SC_MQ_OPEN_MAX_SC_XOPEN_SHM_SC_INT_MAX_SC_2_FORT_DEVkill_SC_XOPEN_XPG2_SC_NZERO_SC_XOPEN_XPG4IFF_NOTRAILERS_SC_CPUTIME_SC_PII_INTERNET_SC_V7_LP64_OFF64_SC_LEVEL3_CACHE_SIZE_SC_MB_LEN_MAXifreq__u6_addr16__caddr_t_py_tmpsockaddr_ipxsll_hatypegetifaddrsifru_broadaddr_SC_REALTIME_SIGNALS__RLIMIT_LOCKSm_freemoduledefpy_netmask_SC_DEVICE_SPECIFIC_Ruint32_tin_addr_tmem_start_SC_SAVED_IDS__RLIM_NLIMITS_SC_2_C_DEV_SC_XBS5_LPBIG_OFFBIGob_base_SC_2_C_VERSION_SC_SEM_VALUE_MAX_SC_SCHAR_MAXifru_map_SC_SSIZE_MAX_SC_2_UPEPyExc_RuntimeErrorfreeifaddrsRLIMIT_COREifa_name_SC_INT_MIN_SC_BC_BASE_MAX__u6_addr8_SC_POLLsysconfml_flags_SC_SYSTEM_DATABASE_Rsockaddr_dlsll_halen__RLIMIT_NPROC_SC_2_LOCALEDEFIFF_MULTICASTsin_family_SC_XOPEN_XPG3_SC_T_IOV_MAX_SC_LEVEL1_ICACHE_ASSOCin_port_tpy_str_SC_SYMLOOP_MAXretval_SC_TRACE_LOGifa_ifu__u6_addr32append_flag_SC_THREAD_CPUTIMEsin_zero_SC_CHAR_MAX_SC_XBS5_ILP32_OFFBIG_SC_PII_INTERNET_DGRAMs_addrpy_address_SC_2_PBS_TRACK__u16psutil_net_if_flags_SC_FILE_ATTRIBUTES_SC_ASYNCHRONOUS_IO_SC_FSYNC__RLIMIT_NICEsockaddr_inarp_SC_DEVICE_SPECIFICsockaddr_ax25ifa_netmaskIFF_UP_SC_THREAD_ATTR_STACKSIZE_SC_REGEX_VERSION_SC_MEMLOCK_SC_DELAYTIMER_MAX_SC_LONG_BIT_SC_SEM_NSEMS_MAXsockaddr_isoPyModule_AddObjectPyModule_AddIntConstant_SC_XOPEN_STREAMS_SC_LEVEL1_ICACHE_LINESIZE_SC_SIGNALSsll_family__RLIMIT_OFILEIFF_SLAVEioctl_SC_2_PBS_ACCOUNTING_SC_AIO_MAX_SC_LEVEL2_CACHE_LINESIZE_SC_XOPEN_VERSIONmod_methodssa_family_t_SC_CLK_TCK_SC_SHELLsll_protocol_SC_UIO_MAXIOV_SC_TZNAME_MAXifru_data_SC_SPORADIC_SERVER_SC_MEMLOCK_RANGE_SC_AVPHYS_PAGES__RLIMIT_NLIMITS_SC_V7_ILP32_OFFBIG_SC_PII_XTIclosesll_ifindexflag_namesock_SC_V7_LPBIG_OFFBIG_SC_C_LANG_SUPPORT_RSOCK_DCCP_SC_LEVEL3_CACHE_ASSOCuint8_t_SC_FILE_SYSTEMifru_netmask_SC_PAGESIZE_SC_V6_ILP32_OFFBIGSOCK_PACKET__id_t_SC_SIGQUEUE_MAX_SC_SPAWNpsutil_posix_setpriority_SC_DEVICE_IO_SC_V6_LPBIG_OFFBIG_SC_2_VERSIONifru_mtu_SC_LEVEL4_CACHE_SIZEml_nameSOCK_DGRAMm_sizeIFF_LOOPBACK_SC_USER_GROUPS_RPyModuleDef_Slotvisitprocsin_port_SC_LINE_MAXsockaddr_eonpsutil/_psutil_posix.cIFF_AUTOMEDIAlladdrpy_broadcast_SC_LEVEL1_DCACHE_ASSOC_SC_HOST_NAME_MAX_SC_C_LANG_SUPPORT__RLIMIT_RSS_SC_THREAD_STACK_MINIFF_RUNNING_SC_SEMAPHORES_SC_UINT_MAX_SC_CHILD_MAX__RLIMIT_MSGQUEUEPyUnicode_FromString_SC_NGROUPS_MAX_SC_SINGLE_PROCESSIFF_ALLMULTI__be16__in6_usin_addr_SC_TTY_NAME_MAX_SC_PII_INTERNET_STREAMRLIMIT_AS_SC_MEMORY_PROTECTIONPyModuleDef_Basem_name_SC_XOPEN_CRYPTPyCFunctionpsutil_net_if_is_runningifru_newname_Py_FalseStructRLIMIT_FSIZE_SC_CHAR_BIT_SC_LEVEL1_DCACHE_SIZEIFF_NOARP_SC_CLOCK_SELECTIONm_initifrn_namesin6_addrpsutil_net_if_mtu_SC_TIMERSfreefunc_SC_BC_SCALE_MAX_SC_ULONG_MAXuint16_tsin6_port_SC_MQ_PRIO_MAX_SC_TRACE_SC_SPIN_LOCKSifru_flagsaddrlen_SC_LEVEL1_DCACHE_LINESIZE_SC_BC_STRING_MAXPyLong_FromLongmem_endSOCK_STREAMRLIMIT_DATA_SC_V7_ILP32_OFF32_SC_TRACE_SYS_MAX_SC_FD_MGMT_SC_REGEXPsin6_familyIFF_PROMISCRLIMIT_CPUPyInit__psutil_posix_SC_LEVEL1_ICACHE_SIZE_SC_ADVISORY_INFO__RLIMIT_RTPRIO_SC_SHRT_MAX_SC_XBS5_LP64_OFF64__builtin_strncpy_SC_READER_WRITER_LOCKS_SC_SYSTEM_DATABASE_SC_XOPEN_REALTIME_THREADS_SC_THREAD_ROBUST_PRIO_PROTECT_SC_2_CHAR_TERM_SC_PASS_MAX_SC_FIFOm_slots_SC_ARG_MAXifru_hwaddrml_doc_SC_2_PBS_CHECKPOINTPyMethodDef_SC_XOPEN_REALTIMEPRIO_USERifru_dstaddrpsutil_getpagesize_pywrapper_SC_2_FORT_RUNsocket_SC_TRACE_EVENT_FILTERpsutil_raise_for_pid_SC_RE_DUP_MAX_SC_SCHAR_MINsockaddr_in_SC_THREAD_ROBUST_PRIO_INHERIT_SC_THREADSPyList_Append_SC_PII__RLIMIT_SIGPENDING_SC_TRACE_INHERIT_SC_WORD_BIT_SC_XBS5_ILP32_OFF32_SC_PII_OSI_MRLIMIT_NOFILEm_traverse_SC_2_SW_DEV_SC_OPEN_MAX_SC_XOPEN_UNIXsockaddr_in6_SC_AIO_LISTIO_MAXPyErr_SetFromErrno_SC_PII_OSI_SC_UCHAR_MAX_SC_MONOTONIC_CLOCKm_clearpy_tupleifaddrSOCK_RAW_SC_PRIORITY_SCHEDULINGm_doc_SC_SELECT_SC_NETWORKING_SC_TIMER_MAX_SC_TRACE_EVENT_NAME_MAX_SC_V6_LP64_OFF64_SC_GETGR_R_SIZE_MAX_SC_LEVEL2_CACHE_SIZE_SC_LOGIN_NAME_MAX_SC_EXPR_NEST_MAXIFF_POINTOPOINT_SC_NPROCESSORS_CONF__RLIMIT_RTTIMEifru_addr__socklen_ttraverseprocSOCK_SEQPACKETPRIO_PROCESSsockaddr_atpsutil_pid_existsifa_flags_SC_SS_REPL_MAX_SC_RAW_SOCKETS_SC_BARRIERS_SC_CHAR_MIN_SC_LEVEL4_CACHE_LINESIZEpsutil_convert_ipaddr_SC_THREAD_PROCESS_SHARED_SC_NL_MSGMAX_Py_TrueStructsin6_scope_idm_index_SC_LEVEL4_CACHE_ASSOC_SC_CHARCLASS_NAME_MAX_SC_PII_OSI_CLTSpsutil_net_if_addrspy_retlist_SC_TYPED_MEMORY_OBJECTSml_meth__RLIMIT_MEMLOCKbase_addr_SC_2_PBS_SC_PHYS_PAGESIFF_MASTER_SC_PII_SOCKETIFF_DEBUG_SC_MULTI_PROCESS_SC_LEVEL2_CACHE_ASSOC__priority_whichsa_familyifmap_SC_THREAD_KEYS_MAXPyErr_FormatIFF_BROADCAST_SC_THREAD_THREADS_MAX_SC_GETPW_R_SIZE_MAXifa_dataSOCK_NONBLOCKPRIO_PGRP_SC_2_PBS_MESSAGE_SC_RTSIG_MAXsockaddr_ll_SC_THREAD_ATTR_STACKADDRPyList_NewPyModuleDef_SC_FILE_LOCKING_SC_SHARED_MEMORY_OBJECTS_SC_TRACE_NAME_MAX_SC_COLL_WEIGHTS_MAX_SC_XOPEN_ENH_I18N_SC_XOPEN_LEGACY_SC_JOB_CONTROLIFF_DYNAMICifa_nextRLIMIT_STACK_SC_MESSAGE_PASSING_SC_NL_LANGMAX_SC_IOV_MAX_SC_USER_GROUPSSOCK_CLOEXEC_SC_IPV6_SC_LEVEL3_CACHE_LINESIZE_SC_2_PBS_LOCATEifru_ivalue_SC_NL_SETMAX_SC_NL_ARGMAXifu_broadaddrnic_name_SC_THREAD_PRIO_INHERITsll_addr_SC_TRACE_USER_EVENT_MAXinquirysockaddr_x25SOCK_RDM_SC_AIO_PRIO_DELTA_MAX_SC_XOPEN_XCU_VERSION07U7��U�0>T>IUI��T�XcP��U�*�U���T��U�*�T�0QUQ��U�xP�V��V��V��V��V��V��U�&�U���P�V
#V�V
#V��V
#VUG\G��U�^ePe|V��Vf|V��VkrV��Vc�P�A\+>P��U���U���T��U���T���	���PBVHTUTiVj�V%PHTPPTUTE�U�PbTb�V���T���V�E�T�P�	����P��V�
	��

P
Q
VV
J	��JWVWE	����P!
3
PcrPr�\�D
\V
E\��V�
VV
JVW*V��\��\4
D
\JW\��
[A�*@
[A���\*@\��0���P��V��0�*@V*EV��V��V�E	
�@��E	\�	0�	"	P"	/	]/	E	0�/	J	]/	J	]J	�	
�@�J	�	\J	_	0�_	r	Pr	{	]{	�	0�{	�	]{	�	]�	�	
�@��	�	\�	�	0��	�	P�	�	]�	�	0��	�	]�	�	]�
%
QA��
%\�
�
0��
P]%0��	
]*]*]V
�

�@�V
�
\V
o
0�o
�
P�
�
]�
�
0��
�
]�
�
]�
�

A��
�
\�
�
0��
�
P�
�
]�
�
0��
�
]�
�
]�
E
9A��
E\�
0�"P"/]/E0�/J]/J]W�
?A�W�\Wo0�o�P��]��0���]��]��
IA���\��0���P��]��0���]��]�E
A��E\�0�"P"/]/E0�/J]/J]J�
�B�J�\J_0�_rPr]�0��]�]��
A���\��0���P��]��0���]��]�5

!A��5
\��0��
P

]
5
0�
:
]
:
]:
�

)A�:
�
\:
O
0�O
b
Pb
o
]o
�
0�o
�
]o
�
]�
�

2A��
�
\�
�
0��
�
P�
�
]�
�
0��
�
]�
�
]U��U�
T
U��T�8	��8SPS�V��U��VjuP��PU��U�$T$��T�KV�V��Vm�VY�^^^��^m�^*<P<�����*�0���P��Z�����0��Z�����0�m�0���S��0���Z��0�*Y0�Y�\��0�(>P>�\(\(0��m\m�P��\��0�*Y0�Y�S�B0�BNPN�S;S;�0��mSm�0���S��P��0�*s0�y�_�e0�elPl|_�_M_M�0��m_m�0���S��0���Z��0�*s0�y�]�p0��]_]_�0���P�m]m�0���S��0���Z��0���Z����'Z'����Z����'Z'����\(\		��\(\��S;S	��S;S��_M_		��_M_��]_]		��]_]������Q�m����Z��Z�Z��Z�Z��\��\m\��\6\��S��S(mS��S6VS��_��_Hm_��_Vm_��]��]��]��]`hUh~�U�`hTh~�T���U��S��U�S!�U�!CSCI�U���T�VU�T�V U !�T�!DVDHQHI�T���U���U���T��U���T���P��P���U����T���U�F�U���T�.V./�T�/EVEF�T�P'T/>T/?�U�/?V��U���U���P��X���U�fr��kr��������������[f���� (��(;��;M��M_��_r������������(�� (��(H��@H��Hp��`p���������	4
?
JR��*E��*E�	
�
*�	
	8`��D��	 
  �"T7
@�BhC�]�]�]�]�_`@a�b��"�"!�"7�bC�]j0#v�]�����&���&���'a�()�$�,v=P-�Q`4n@ahx�a��G���]��]��B��b�`���2G` |���T7��P5���P4
&9Leu��� ������4i@#�3BXhy�4W��#����p%W���p$��b'4I cy%j�"�	 ��%)�crtstuff.cderegister_tm_clones__do_global_dtors_auxcompleted.0__do_global_dtors_aux_fini_array_entryframe_dummy__frame_dummy_init_array_entry_psutil_common.c_psutil_posix.cpsutil_net_if_mtupsutil_net_if_is_runningpsutil_posix_setprioritypsutil_convert_ipaddrpsutil_net_if_addrspsutil_posix_getprioritypsutil_net_if_flagspsutil_getpagesize_pywrappermoduledefmod_methods__FRAME_END____dso_handle_DYNAMIC__GNU_EH_FRAME_HDR__TMC_END___GLOBAL_OFFSET_TABLE_getenv@@GLIBC_2.2.5PyList_NewPyModule_AddIntConstant__errno_location@@GLIBC_2.2.5strncpy@@GLIBC_2.2.5getpriority@@GLIBC_2.2.5_ITM_deregisterTMCloneTablePyErr_SetFromErrno_Py_DeallocPyErr_SetObject_finiPyExc_RuntimeErrorPyInit__psutil_posixPyErr_SetStringPyExc_ValueErrorsetpriority@@GLIBC_2.2.5psutil_getpagesizeioctl@@GLIBC_2.2.5close@@GLIBC_2.2.5getnameinfo@@GLIBC_2.2.5PyLong_FromLongPyList_AppendPyExc_OSError_Py_FalseStruct__gmon_start__PyObject_CallFunctionPy_BuildValuekill@@GLIBC_2.2.5PyModule_Create2psutil_raise_for_pidpsutil_PyErr_SetFromOSErrnoWithSyscall_Py_NoneStructgetifaddrs@@GLIBC_2.3PyObject_IsTruePyArg_ParseTuplepsutil_pid_existsNoSuchProcess_Py_TrueStructfreeifaddrs@@GLIBC_2.3psutil_set_debugPyUnicode_FromStringPyModule_AddObjectAccessDeniedsysconf@@GLIBC_2.2.5PSUTIL_DEBUGPyErr_Formatsprintf@@GLIBC_2.2.5_ITM_registerTMCloneTablestrerror@@GLIBC_2.2.5psutil_check_pid_range__cxa_finalize@@GLIBC_2.2.5_initpsutil_setupsocket@@GLIBC_2.2.5.symtab.strtab.shstrtab.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.data.rel.ro.dynamic.got.got.plt.data.bss.comment.debug_aranges.debug_info.debug_abbrev.debug_line.debug_str.debug_loc.debug_ranges88$.���o```8��(@��[H���oDDnU���o��Pd�nB��xx  s    `~�"�"��T7T7	�2@@���B�B��hChC���]�M��]�M��]�M��]�M���_�OX�`P@�@a@Q� ��b�R�0�R/��R`	OS�?ےr#M�5/0��M:���,E�p@��
!<	���
SPKok\ػ�هc�cpsutil/_pssunos.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Sun OS Solaris platform implementation."""

import errno
import functools
import os
import socket
import subprocess
import sys
from collections import namedtuple
from socket import AF_INET

from . import _common
from . import _psposix
from . import _psutil_posix as cext_posix
from . import _psutil_sunos as cext
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import ZombieProcess
from ._common import debug
from ._common import get_procfs_path
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._compat import PY3
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import b


__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]


# =====================================================================
# --- globals
# =====================================================================


PAGE_SIZE = cext_posix.getpagesize()
AF_LINK = cext_posix.AF_LINK
IS_64_BIT = sys.maxsize > 2**32

CONN_IDLE = "IDLE"
CONN_BOUND = "BOUND"

PROC_STATUSES = {
    cext.SSLEEP: _common.STATUS_SLEEPING,
    cext.SRUN: _common.STATUS_RUNNING,
    cext.SZOMB: _common.STATUS_ZOMBIE,
    cext.SSTOP: _common.STATUS_STOPPED,
    cext.SIDL: _common.STATUS_IDLE,
    cext.SONPROC: _common.STATUS_RUNNING,  # same as run
    cext.SWAIT: _common.STATUS_WAITING,
}

TCP_STATUSES = {
    cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
    cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
    cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
    cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
    cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
    cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
    cext.TCPS_CLOSED: _common.CONN_CLOSE,
    cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
    cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
    cext.TCPS_LISTEN: _common.CONN_LISTEN,
    cext.TCPS_CLOSING: _common.CONN_CLOSING,
    cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
    cext.TCPS_IDLE: CONN_IDLE,  # sunos specific
    cext.TCPS_BOUND: CONN_BOUND,  # sunos specific
}

proc_info_map = dict(
    ppid=0,
    rss=1,
    vms=2,
    create_time=3,
    nice=4,
    num_threads=5,
    status=6,
    ttynr=7,
    uid=8,
    euid=9,
    gid=10,
    egid=11,
)


# =====================================================================
# --- named tuples
# =====================================================================


# psutil.cpu_times()
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.cpu_times(percpu=True)
pcputimes = namedtuple(
    'pcputimes', ['user', 'system', 'children_user', 'children_system']
)
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
pfullmem = pmem
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple(
    'pmmap_grouped', ['path', 'rss', 'anonymous', 'locked']
)
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
    'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)
)


# =====================================================================
# --- memory
# =====================================================================


def virtual_memory():
    """Report virtual memory metrics."""
    # we could have done this with kstat, but IMHO this is good enough
    total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE
    # note: there's no difference on Solaris
    free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
    used = total - free
    percent = usage_percent(used, total, round_=1)
    return svmem(total, avail, percent, used, free)


def swap_memory():
    """Report swap memory metrics."""
    sin, sout = cext.swap_mem()
    # XXX
    # we are supposed to get total/free by doing so:
    # http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/
    #     usr/src/cmd/swap/swap.c
    # ...nevertheless I can't manage to obtain the same numbers as 'swap'
    # cmdline utility, so let's parse its output (sigh!)
    p = subprocess.Popen(
        [
            '/usr/bin/env',
            'PATH=/usr/sbin:/sbin:%s' % os.environ['PATH'],
            'swap',
            '-l',
        ],
        stdout=subprocess.PIPE,
    )
    stdout, _ = p.communicate()
    if PY3:
        stdout = stdout.decode(sys.stdout.encoding)
    if p.returncode != 0:
        raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode)

    lines = stdout.strip().split('\n')[1:]
    if not lines:
        msg = 'no swap device(s) configured'
        raise RuntimeError(msg)
    total = free = 0
    for line in lines:
        line = line.split()
        t, f = line[3:5]
        total += int(int(t) * 512)
        free += int(int(f) * 512)
    used = total - free
    percent = usage_percent(used, total, round_=1)
    return _common.sswap(
        total, used, free, percent, sin * PAGE_SIZE, sout * PAGE_SIZE
    )


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return system-wide CPU times as a named tuple."""
    ret = cext.per_cpu_times()
    return scputimes(*[sum(x) for x in zip(*ret)])


def per_cpu_times():
    """Return system per-CPU times as a list of named tuples."""
    ret = cext.per_cpu_times()
    return [scputimes(*x) for x in ret]


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    try:
        return os.sysconf("SC_NPROCESSORS_ONLN")
    except ValueError:
        # mimic os.cpu_count() behavior
        return None


def cpu_count_cores():
    """Return the number of CPU cores in the system."""
    return cext.cpu_count_cores()


def cpu_stats():
    """Return various CPU stats as a named tuple."""
    ctx_switches, interrupts, syscalls, _traps = cext.cpu_stats()
    soft_interrupts = 0
    return _common.scpustats(
        ctx_switches, interrupts, soft_interrupts, syscalls
    )


# =====================================================================
# --- disks
# =====================================================================


disk_io_counters = cext.disk_io_counters
disk_usage = _psposix.disk_usage


def disk_partitions(all=False):
    """Return system disk partitions."""
    # TODO - the filtering logic should be better checked so that
    # it tries to reflect 'df' as much as possible
    retlist = []
    partitions = cext.disk_partitions()
    for partition in partitions:
        device, mountpoint, fstype, opts = partition
        if device == 'none':
            device = ''
        if not all:
            # Differently from, say, Linux, we don't have a list of
            # common fs types so the best we can do, AFAIK, is to
            # filter by filesystem having a total size > 0.
            try:
                if not disk_usage(mountpoint).total:
                    continue
            except OSError as err:
                # https://github.com/giampaolo/psutil/issues/1674
                debug("skipping %r: %s" % (mountpoint, err))
                continue
        ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
        retlist.append(ntuple)
    return retlist


# =====================================================================
# --- network
# =====================================================================


net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs


def net_connections(kind, _pid=-1):
    """Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    Only INET sockets are returned (UNIX are not).
    """
    cmap = _common.conn_tmap.copy()
    if _pid == -1:
        cmap.pop('unix', 0)
    if kind not in cmap:
        raise ValueError(
            "invalid %r kind argument; choose between %s"
            % (kind, ', '.join([repr(x) for x in cmap]))
        )
    families, types = _common.conn_tmap[kind]
    rawlist = cext.net_connections(_pid)
    ret = set()
    for item in rawlist:
        fd, fam, type_, laddr, raddr, status, pid = item
        if fam not in families:
            continue
        if type_ not in types:
            continue
        # TODO: refactor and use _common.conn_to_ntuple.
        if fam in (AF_INET, AF_INET6):
            if laddr:
                laddr = _common.addr(*laddr)
            if raddr:
                raddr = _common.addr(*raddr)
        status = TCP_STATUSES[status]
        fam = sockfam_to_enum(fam)
        type_ = socktype_to_enum(type_)
        if _pid == -1:
            nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
        else:
            nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
        ret.add(nt)
    return list(ret)


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    ret = cext.net_if_stats()
    for name, items in ret.items():
        isup, duplex, speed, mtu = items
        if hasattr(_common, 'NicDuplex'):
            duplex = _common.NicDuplex(duplex)
        ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
    return ret


# =====================================================================
# --- other system functions
# =====================================================================


def boot_time():
    """The system boot time expressed in seconds since the epoch."""
    return cext.boot_time()


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    localhost = (':0.0', ':0')
    for item in rawlist:
        user, tty, hostname, tstamp, user_process, pid = item
        # note: the underlying C function includes entries about
        # system boot, run level and others.  We might want
        # to use them in the future.
        if not user_process:
            continue
        if hostname in localhost:
            hostname = 'localhost'
        nt = _common.suser(user, tty, hostname, tstamp, pid)
        retlist.append(nt)
    return retlist


# =====================================================================
# --- processes
# =====================================================================


def pids():
    """Returns a list of PIDs currently running on the system."""
    return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()]


def pid_exists(pid):
    """Check for the existence of a unix pid."""
    return _psposix.pid_exists(pid)


def wrap_exceptions(fun):
    """Call callable into a try/except clause and translate ENOENT,
    EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except (FileNotFoundError, ProcessLookupError):
            # ENOENT (no such file or directory) gets raised on open().
            # ESRCH (no such process) can get raised on read() if
            # process is gone in meantime.
            if not pid_exists(self.pid):
                raise NoSuchProcess(self.pid, self._name)
            else:
                raise ZombieProcess(self.pid, self._name, self._ppid)
        except PermissionError:
            raise AccessDenied(self.pid, self._name)
        except OSError:
            if self.pid == 0:
                if 0 in pids():
                    raise AccessDenied(self.pid, self._name)
                else:
                    raise
            raise

    return wrapper


class Process:
    """Wrapper class around underlying C implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "_procfs_path", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None
        self._procfs_path = get_procfs_path()

    def _assert_alive(self):
        """Raise NSP if the process disappeared on us."""
        # For those C function who do not raise NSP, possibly returning
        # incorrect or incomplete result.
        os.stat('%s/%s' % (self._procfs_path, self.pid))

    def oneshot_enter(self):
        self._proc_name_and_args.cache_activate(self)
        self._proc_basic_info.cache_activate(self)
        self._proc_cred.cache_activate(self)

    def oneshot_exit(self):
        self._proc_name_and_args.cache_deactivate(self)
        self._proc_basic_info.cache_deactivate(self)
        self._proc_cred.cache_deactivate(self)

    @wrap_exceptions
    @memoize_when_activated
    def _proc_name_and_args(self):
        return cext.proc_name_and_args(self.pid, self._procfs_path)

    @wrap_exceptions
    @memoize_when_activated
    def _proc_basic_info(self):
        if self.pid == 0 and not os.path.exists(
            '%s/%s/psinfo' % (self._procfs_path, self.pid)
        ):
            raise AccessDenied(self.pid)
        ret = cext.proc_basic_info(self.pid, self._procfs_path)
        assert len(ret) == len(proc_info_map)
        return ret

    @wrap_exceptions
    @memoize_when_activated
    def _proc_cred(self):
        return cext.proc_cred(self.pid, self._procfs_path)

    @wrap_exceptions
    def name(self):
        # note: max len == 15
        return self._proc_name_and_args()[0]

    @wrap_exceptions
    def exe(self):
        try:
            return os.readlink(
                "%s/%s/path/a.out" % (self._procfs_path, self.pid)
            )
        except OSError:
            pass  # continue and guess the exe name from the cmdline
        # Will be guessed later from cmdline but we want to explicitly
        # invoke cmdline here in order to get an AccessDenied
        # exception if the user has not enough privileges.
        self.cmdline()
        return ""

    @wrap_exceptions
    def cmdline(self):
        return self._proc_name_and_args()[1].split(' ')

    @wrap_exceptions
    def environ(self):
        return cext.proc_environ(self.pid, self._procfs_path)

    @wrap_exceptions
    def create_time(self):
        return self._proc_basic_info()[proc_info_map['create_time']]

    @wrap_exceptions
    def num_threads(self):
        return self._proc_basic_info()[proc_info_map['num_threads']]

    @wrap_exceptions
    def nice_get(self):
        # Note #1: getpriority(3) doesn't work for realtime processes.
        # Psinfo is what ps uses, see:
        # https://github.com/giampaolo/psutil/issues/1194
        return self._proc_basic_info()[proc_info_map['nice']]

    @wrap_exceptions
    def nice_set(self, value):
        if self.pid in (2, 3):
            # Special case PIDs: internally setpriority(3) return ESRCH
            # (no such process), no matter what.
            # The process actually exists though, as it has a name,
            # creation time, etc.
            raise AccessDenied(self.pid, self._name)
        return cext_posix.setpriority(self.pid, value)

    @wrap_exceptions
    def ppid(self):
        self._ppid = self._proc_basic_info()[proc_info_map['ppid']]
        return self._ppid

    @wrap_exceptions
    def uids(self):
        try:
            real, effective, saved, _, _, _ = self._proc_cred()
        except AccessDenied:
            real = self._proc_basic_info()[proc_info_map['uid']]
            effective = self._proc_basic_info()[proc_info_map['euid']]
            saved = None
        return _common.puids(real, effective, saved)

    @wrap_exceptions
    def gids(self):
        try:
            _, _, _, real, effective, saved = self._proc_cred()
        except AccessDenied:
            real = self._proc_basic_info()[proc_info_map['gid']]
            effective = self._proc_basic_info()[proc_info_map['egid']]
            saved = None
        return _common.puids(real, effective, saved)

    @wrap_exceptions
    def cpu_times(self):
        try:
            times = cext.proc_cpu_times(self.pid, self._procfs_path)
        except OSError as err:
            if err.errno == errno.EOVERFLOW and not IS_64_BIT:
                # We may get here if we attempt to query a 64bit process
                # with a 32bit python.
                # Error originates from read() and also tools like "cat"
                # fail in the same way (!).
                # Since there simply is no way to determine CPU times we
                # return 0.0 as a fallback. See:
                # https://github.com/giampaolo/psutil/issues/857
                times = (0.0, 0.0, 0.0, 0.0)
            else:
                raise
        return _common.pcputimes(*times)

    @wrap_exceptions
    def cpu_num(self):
        return cext.proc_cpu_num(self.pid, self._procfs_path)

    @wrap_exceptions
    def terminal(self):
        procfs_path = self._procfs_path
        hit_enoent = False
        tty = wrap_exceptions(self._proc_basic_info()[proc_info_map['ttynr']])
        if tty != cext.PRNODEV:
            for x in (0, 1, 2, 255):
                try:
                    return os.readlink(
                        '%s/%d/path/%d' % (procfs_path, self.pid, x)
                    )
                except FileNotFoundError:
                    hit_enoent = True
                    continue
        if hit_enoent:
            self._assert_alive()

    @wrap_exceptions
    def cwd(self):
        # /proc/PID/path/cwd may not be resolved by readlink() even if
        # it exists (ls shows it). If that's the case and the process
        # is still alive return None (we can return None also on BSD).
        # Reference: http://goo.gl/55XgO
        procfs_path = self._procfs_path
        try:
            return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid))
        except FileNotFoundError:
            os.stat("%s/%s" % (procfs_path, self.pid))  # raise NSP or AD
            return ""

    @wrap_exceptions
    def memory_info(self):
        ret = self._proc_basic_info()
        rss = ret[proc_info_map['rss']] * 1024
        vms = ret[proc_info_map['vms']] * 1024
        return pmem(rss, vms)

    memory_full_info = memory_info

    @wrap_exceptions
    def status(self):
        code = self._proc_basic_info()[proc_info_map['status']]
        # XXX is '?' legit? (we're not supposed to return it anyway)
        return PROC_STATUSES.get(code, '?')

    @wrap_exceptions
    def threads(self):
        procfs_path = self._procfs_path
        ret = []
        tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid))
        hit_enoent = False
        for tid in tids:
            tid = int(tid)
            try:
                utime, stime = cext.query_process_thread(
                    self.pid, tid, procfs_path
                )
            except EnvironmentError as err:
                if err.errno == errno.EOVERFLOW and not IS_64_BIT:
                    # We may get here if we attempt to query a 64bit process
                    # with a 32bit python.
                    # Error originates from read() and also tools like "cat"
                    # fail in the same way (!).
                    # Since there simply is no way to determine CPU times we
                    # return 0.0 as a fallback. See:
                    # https://github.com/giampaolo/psutil/issues/857
                    continue
                # ENOENT == thread gone in meantime
                if err.errno == errno.ENOENT:
                    hit_enoent = True
                    continue
                raise
            else:
                nt = _common.pthread(tid, utime, stime)
                ret.append(nt)
        if hit_enoent:
            self._assert_alive()
        return ret

    @wrap_exceptions
    def open_files(self):
        retlist = []
        hit_enoent = False
        procfs_path = self._procfs_path
        pathdir = '%s/%d/path' % (procfs_path, self.pid)
        for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)):
            path = os.path.join(pathdir, fd)
            if os.path.islink(path):
                try:
                    file = os.readlink(path)
                except FileNotFoundError:
                    hit_enoent = True
                    continue
                else:
                    if isfile_strict(file):
                        retlist.append(_common.popenfile(file, int(fd)))
        if hit_enoent:
            self._assert_alive()
        return retlist

    def _get_unix_sockets(self, pid):
        """Get UNIX sockets used by process by parsing 'pfiles' output."""
        # TODO: rewrite this in C (...but the damn netstat source code
        # does not include this part! Argh!!)
        cmd = ["pfiles", str(pid)]
        p = subprocess.Popen(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
        stdout, stderr = p.communicate()
        if PY3:
            stdout, stderr = (
                x.decode(sys.stdout.encoding) for x in (stdout, stderr)
            )
        if p.returncode != 0:
            if 'permission denied' in stderr.lower():
                raise AccessDenied(self.pid, self._name)
            if 'no such process' in stderr.lower():
                raise NoSuchProcess(self.pid, self._name)
            raise RuntimeError("%r command error\n%s" % (cmd, stderr))

        lines = stdout.split('\n')[2:]
        for i, line in enumerate(lines):
            line = line.lstrip()
            if line.startswith('sockname: AF_UNIX'):
                path = line.split(' ', 2)[2]
                type = lines[i - 2].strip()
                if type == 'SOCK_STREAM':
                    type = socket.SOCK_STREAM
                elif type == 'SOCK_DGRAM':
                    type = socket.SOCK_DGRAM
                else:
                    type = -1
                yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE)

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        ret = net_connections(kind, _pid=self.pid)
        # The underlying C implementation retrieves all OS connections
        # and filters them by PID.  At this point we can't tell whether
        # an empty list means there were no connections for process or
        # process is no longer active so we force NSP in case the PID
        # is no longer there.
        if not ret:
            # will raise NSP if process is gone
            os.stat('%s/%s' % (self._procfs_path, self.pid))

        # UNIX sockets
        if kind in ('all', 'unix'):
            ret.extend([
                _common.pconn(*conn)
                for conn in self._get_unix_sockets(self.pid)
            ])
        return ret

    nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked')
    nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked')

    @wrap_exceptions
    def memory_maps(self):
        def toaddr(start, end):
            return '%s-%s' % (
                hex(start)[2:].strip('L'),
                hex(end)[2:].strip('L'),
            )

        procfs_path = self._procfs_path
        retlist = []
        try:
            rawlist = cext.proc_memory_maps(self.pid, procfs_path)
        except OSError as err:
            if err.errno == errno.EOVERFLOW and not IS_64_BIT:
                # We may get here if we attempt to query a 64bit process
                # with a 32bit python.
                # Error originates from read() and also tools like "cat"
                # fail in the same way (!).
                # Since there simply is no way to determine CPU times we
                # return 0.0 as a fallback. See:
                # https://github.com/giampaolo/psutil/issues/857
                return []
            else:
                raise
        hit_enoent = False
        for item in rawlist:
            addr, addrsize, perm, name, rss, anon, locked = item
            addr = toaddr(addr, addrsize)
            if not name.startswith('['):
                try:
                    name = os.readlink(
                        '%s/%s/path/%s' % (procfs_path, self.pid, name)
                    )
                except OSError as err:
                    if err.errno == errno.ENOENT:
                        # sometimes the link may not be resolved by
                        # readlink() even if it exists (ls shows it).
                        # If that's the case we just return the
                        # unresolved link path.
                        # This seems an inconsistency with /proc similar
                        # to: http://goo.gl/55XgO
                        name = '%s/%s/path/%s' % (procfs_path, self.pid, name)
                        hit_enoent = True
                    else:
                        raise
            retlist.append((addr, perm, name, rss, anon, locked))
        if hit_enoent:
            self._assert_alive()
        return retlist

    @wrap_exceptions
    def num_fds(self):
        return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))

    @wrap_exceptions
    def num_ctx_switches(self):
        return _common.pctxsw(
            *cext.proc_num_ctx_switches(self.pid, self._procfs_path)
        )

    @wrap_exceptions
    def wait(self, timeout=None):
        return _psposix.wait_pid(self.pid, timeout, self._name)
PKok\;�`�}�}psutil/_psbsd.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""FreeBSD, OpenBSD and NetBSD platforms implementation."""

import contextlib
import errno
import functools
import os
from collections import defaultdict
from collections import namedtuple
from xml.etree import ElementTree  # noqa ICN001

from . import _common
from . import _psposix
from . import _psutil_bsd as cext
from . import _psutil_posix as cext_posix
from ._common import FREEBSD
from ._common import NETBSD
from ._common import OPENBSD
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import ZombieProcess
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import debug
from ._common import memoize
from ._common import memoize_when_activated
from ._common import usage_percent
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import which


__extra__all__ = []


# =====================================================================
# --- globals
# =====================================================================


if FREEBSD:
    PROC_STATUSES = {
        cext.SIDL: _common.STATUS_IDLE,
        cext.SRUN: _common.STATUS_RUNNING,
        cext.SSLEEP: _common.STATUS_SLEEPING,
        cext.SSTOP: _common.STATUS_STOPPED,
        cext.SZOMB: _common.STATUS_ZOMBIE,
        cext.SWAIT: _common.STATUS_WAITING,
        cext.SLOCK: _common.STATUS_LOCKED,
    }
elif OPENBSD:
    PROC_STATUSES = {
        cext.SIDL: _common.STATUS_IDLE,
        cext.SSLEEP: _common.STATUS_SLEEPING,
        cext.SSTOP: _common.STATUS_STOPPED,
        # According to /usr/include/sys/proc.h SZOMB is unused.
        # test_zombie_process() shows that SDEAD is the right
        # equivalent. Also it appears there's no equivalent of
        # psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE.
        # cext.SZOMB: _common.STATUS_ZOMBIE,
        cext.SDEAD: _common.STATUS_ZOMBIE,
        cext.SZOMB: _common.STATUS_ZOMBIE,
        # From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt
        # OpenBSD has SRUN and SONPROC: SRUN indicates that a process
        # is runnable but *not* yet running, i.e. is on a run queue.
        # SONPROC indicates that the process is actually executing on
        # a CPU, i.e. it is no longer on a run queue.
        # As such we'll map SRUN to STATUS_WAKING and SONPROC to
        # STATUS_RUNNING
        cext.SRUN: _common.STATUS_WAKING,
        cext.SONPROC: _common.STATUS_RUNNING,
    }
elif NETBSD:
    PROC_STATUSES = {
        cext.SIDL: _common.STATUS_IDLE,
        cext.SSLEEP: _common.STATUS_SLEEPING,
        cext.SSTOP: _common.STATUS_STOPPED,
        cext.SZOMB: _common.STATUS_ZOMBIE,
        cext.SRUN: _common.STATUS_WAKING,
        cext.SONPROC: _common.STATUS_RUNNING,
    }

TCP_STATUSES = {
    cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
    cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
    cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
    cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
    cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
    cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
    cext.TCPS_CLOSED: _common.CONN_CLOSE,
    cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
    cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
    cext.TCPS_LISTEN: _common.CONN_LISTEN,
    cext.TCPS_CLOSING: _common.CONN_CLOSING,
    cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}

PAGESIZE = cext_posix.getpagesize()
AF_LINK = cext_posix.AF_LINK

HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times")
HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads")
HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files')
HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds')

kinfo_proc_map = dict(
    ppid=0,
    status=1,
    real_uid=2,
    effective_uid=3,
    saved_uid=4,
    real_gid=5,
    effective_gid=6,
    saved_gid=7,
    ttynr=8,
    create_time=9,
    ctx_switches_vol=10,
    ctx_switches_unvol=11,
    read_io_count=12,
    write_io_count=13,
    user_time=14,
    sys_time=15,
    ch_user_time=16,
    ch_sys_time=17,
    rss=18,
    vms=19,
    memtext=20,
    memdata=21,
    memstack=22,
    cpunum=23,
    name=24,
)


# =====================================================================
# --- named tuples
# =====================================================================


# fmt: off
# psutil.virtual_memory()
svmem = namedtuple(
    'svmem', ['total', 'available', 'percent', 'used', 'free',
              'active', 'inactive', 'buffers', 'cached', 'shared', 'wired'])
# psutil.cpu_times()
scputimes = namedtuple(
    'scputimes', ['user', 'nice', 'system', 'idle', 'irq'])
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack'])
# psutil.Process.memory_full_info()
pfullmem = pmem
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes',
                       ['user', 'system', 'children_user', 'children_system'])
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple(
    'pmmap_grouped', 'path rss, private, ref_count, shadow_count')
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
    'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count')
# psutil.disk_io_counters()
if FREEBSD:
    sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
                                     'read_bytes', 'write_bytes',
                                     'read_time', 'write_time',
                                     'busy_time'])
else:
    sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
                                     'read_bytes', 'write_bytes'])
# fmt: on


# =====================================================================
# --- memory
# =====================================================================


def virtual_memory():
    mem = cext.virtual_mem()
    if NETBSD:
        total, free, active, inactive, wired, cached = mem
        # On NetBSD buffers and shared mem is determined via /proc.
        # The C ext set them to 0.
        with open('/proc/meminfo', 'rb') as f:
            for line in f:
                if line.startswith(b'Buffers:'):
                    buffers = int(line.split()[1]) * 1024
                elif line.startswith(b'MemShared:'):
                    shared = int(line.split()[1]) * 1024
        # Before avail was calculated as (inactive + cached + free),
        # same as zabbix, but it turned out it could exceed total (see
        # #2233), so zabbix seems to be wrong. Htop calculates it
        # differently, and the used value seem more realistic, so let's
        # match htop.
        # https://github.com/htop-dev/htop/blob/e7f447b/netbsd/NetBSDProcessList.c#L162  # noqa
        # https://github.com/zabbix/zabbix/blob/af5e0f8/src/libs/zbxsysinfo/netbsd/memory.c#L135  # noqa
        used = active + wired
        avail = total - used
    else:
        total, free, active, inactive, wired, cached, buffers, shared = mem
        # matches freebsd-memory CLI:
        # * https://people.freebsd.org/~rse/dist/freebsd-memory
        # * https://www.cyberciti.biz/files/scripts/freebsd-memory.pl.txt
        # matches zabbix:
        # * https://github.com/zabbix/zabbix/blob/af5e0f8/src/libs/zbxsysinfo/freebsd/memory.c#L143  # noqa
        avail = inactive + cached + free
        used = active + wired + cached

    percent = usage_percent((total - avail), total, round_=1)
    return svmem(
        total,
        avail,
        percent,
        used,
        free,
        active,
        inactive,
        buffers,
        cached,
        shared,
        wired,
    )


def swap_memory():
    """System swap memory as (total, used, free, sin, sout) namedtuple."""
    total, used, free, sin, sout = cext.swap_mem()
    percent = usage_percent(used, total, round_=1)
    return _common.sswap(total, used, free, percent, sin, sout)


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return system per-CPU times as a namedtuple."""
    user, nice, system, idle, irq = cext.cpu_times()
    return scputimes(user, nice, system, idle, irq)


if HAS_PER_CPU_TIMES:

    def per_cpu_times():
        """Return system CPU times as a namedtuple."""
        ret = []
        for cpu_t in cext.per_cpu_times():
            user, nice, system, idle, irq = cpu_t
            item = scputimes(user, nice, system, idle, irq)
            ret.append(item)
        return ret

else:
    # XXX
    # Ok, this is very dirty.
    # On FreeBSD < 8 we cannot gather per-cpu information, see:
    # https://github.com/giampaolo/psutil/issues/226
    # If num cpus > 1, on first call we return single cpu times to avoid a
    # crash at psutil import time.
    # Next calls will fail with NotImplementedError
    def per_cpu_times():
        """Return system CPU times as a namedtuple."""
        if cpu_count_logical() == 1:
            return [cpu_times()]
        if per_cpu_times.__called__:
            msg = "supported only starting from FreeBSD 8"
            raise NotImplementedError(msg)
        per_cpu_times.__called__ = True
        return [cpu_times()]

    per_cpu_times.__called__ = False


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    return cext.cpu_count_logical()


if OPENBSD or NETBSD:

    def cpu_count_cores():
        # OpenBSD and NetBSD do not implement this.
        return 1 if cpu_count_logical() == 1 else None

else:

    def cpu_count_cores():
        """Return the number of CPU cores in the system."""
        # From the C module we'll get an XML string similar to this:
        # http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html
        # We may get None in case "sysctl kern.sched.topology_spec"
        # is not supported on this BSD version, in which case we'll mimic
        # os.cpu_count() and return None.
        ret = None
        s = cext.cpu_topology()
        if s is not None:
            # get rid of padding chars appended at the end of the string
            index = s.rfind("</groups>")
            if index != -1:
                s = s[: index + 9]
                root = ElementTree.fromstring(s)
                try:
                    ret = len(root.findall('group/children/group/cpu')) or None
                finally:
                    # needed otherwise it will memleak
                    root.clear()
        if not ret:
            # If logical CPUs == 1 it's obvious we' have only 1 core.
            if cpu_count_logical() == 1:
                return 1
        return ret


def cpu_stats():
    """Return various CPU stats as a named tuple."""
    if FREEBSD:
        # Note: the C ext is returning some metrics we are not exposing:
        # traps.
        ctxsw, intrs, soft_intrs, syscalls, _traps = cext.cpu_stats()
    elif NETBSD:
        # XXX
        # Note about intrs: the C extension returns 0. intrs
        # can be determined via /proc/stat; it has the same value as
        # soft_intrs thought so the kernel is faking it (?).
        #
        # Note about syscalls: the C extension always sets it to 0 (?).
        #
        # Note: the C ext is returning some metrics we are not exposing:
        # traps, faults and forks.
        ctxsw, intrs, soft_intrs, syscalls, _traps, _faults, _forks = (
            cext.cpu_stats()
        )
        with open('/proc/stat', 'rb') as f:
            for line in f:
                if line.startswith(b'intr'):
                    intrs = int(line.split()[1])
    elif OPENBSD:
        # Note: the C ext is returning some metrics we are not exposing:
        # traps, faults and forks.
        ctxsw, intrs, soft_intrs, syscalls, _traps, _faults, _forks = (
            cext.cpu_stats()
        )
    return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls)


if FREEBSD:

    def cpu_freq():
        """Return frequency metrics for CPUs. As of Dec 2018 only
        CPU 0 appears to be supported by FreeBSD and all other cores
        match the frequency of CPU 0.
        """
        ret = []
        num_cpus = cpu_count_logical()
        for cpu in range(num_cpus):
            try:
                current, available_freq = cext.cpu_freq(cpu)
            except NotImplementedError:
                continue
            if available_freq:
                try:
                    min_freq = int(available_freq.split(" ")[-1].split("/")[0])
                except (IndexError, ValueError):
                    min_freq = None
                try:
                    max_freq = int(available_freq.split(" ")[0].split("/")[0])
                except (IndexError, ValueError):
                    max_freq = None
            ret.append(_common.scpufreq(current, min_freq, max_freq))
        return ret

elif OPENBSD:

    def cpu_freq():
        curr = float(cext.cpu_freq())
        return [_common.scpufreq(curr, 0.0, 0.0)]


# =====================================================================
# --- disks
# =====================================================================


def disk_partitions(all=False):
    """Return mounted disk partitions as a list of namedtuples.
    'all' argument is ignored, see:
    https://github.com/giampaolo/psutil/issues/906.
    """
    retlist = []
    partitions = cext.disk_partitions()
    for partition in partitions:
        device, mountpoint, fstype, opts = partition
        ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
        retlist.append(ntuple)
    return retlist


disk_usage = _psposix.disk_usage
disk_io_counters = cext.disk_io_counters


# =====================================================================
# --- network
# =====================================================================


net_io_counters = cext.net_io_counters
net_if_addrs = cext_posix.net_if_addrs


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    names = net_io_counters().keys()
    ret = {}
    for name in names:
        try:
            mtu = cext_posix.net_if_mtu(name)
            flags = cext_posix.net_if_flags(name)
            duplex, speed = cext_posix.net_if_duplex_speed(name)
        except OSError as err:
            # https://github.com/giampaolo/psutil/issues/1279
            if err.errno != errno.ENODEV:
                raise
        else:
            if hasattr(_common, 'NicDuplex'):
                duplex = _common.NicDuplex(duplex)
            output_flags = ','.join(flags)
            isup = 'running' in flags
            ret[name] = _common.snicstats(
                isup, duplex, speed, mtu, output_flags
            )
    return ret


def net_connections(kind):
    """System-wide network connections."""
    if kind not in _common.conn_tmap:
        raise ValueError(
            "invalid %r kind argument; choose between %s"
            % (kind, ', '.join([repr(x) for x in conn_tmap]))
        )
    families, types = conn_tmap[kind]
    ret = set()

    if OPENBSD:
        rawlist = cext.net_connections(-1, families, types)
    elif NETBSD:
        rawlist = cext.net_connections(-1, kind)
    else:  # FreeBSD
        rawlist = cext.net_connections(families, types)

    for item in rawlist:
        fd, fam, type, laddr, raddr, status, pid = item
        nt = conn_to_ntuple(
            fd, fam, type, laddr, raddr, status, TCP_STATUSES, pid
        )
        ret.add(nt)
    return list(ret)


# =====================================================================
#  --- sensors
# =====================================================================


if FREEBSD:

    def sensors_battery():
        """Return battery info."""
        try:
            percent, minsleft, power_plugged = cext.sensors_battery()
        except NotImplementedError:
            # See: https://github.com/giampaolo/psutil/issues/1074
            return None
        power_plugged = power_plugged == 1
        if power_plugged:
            secsleft = _common.POWER_TIME_UNLIMITED
        elif minsleft == -1:
            secsleft = _common.POWER_TIME_UNKNOWN
        else:
            secsleft = minsleft * 60
        return _common.sbattery(percent, secsleft, power_plugged)

    def sensors_temperatures():
        """Return CPU cores temperatures if available, else an empty dict."""
        ret = defaultdict(list)
        num_cpus = cpu_count_logical()
        for cpu in range(num_cpus):
            try:
                current, high = cext.sensors_cpu_temperature(cpu)
                if high <= 0:
                    high = None
                name = "Core %s" % cpu
                ret["coretemp"].append(
                    _common.shwtemp(name, current, high, high)
                )
            except NotImplementedError:
                pass

        return ret


# =====================================================================
#  --- other system functions
# =====================================================================


def boot_time():
    """The system boot time expressed in seconds since the epoch."""
    return cext.boot_time()


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    for item in rawlist:
        user, tty, hostname, tstamp, pid = item
        if pid == -1:
            assert OPENBSD
            pid = None
        if tty == '~':
            continue  # reboot or shutdown
        nt = _common.suser(user, tty or None, hostname, tstamp, pid)
        retlist.append(nt)
    return retlist


# =====================================================================
# --- processes
# =====================================================================


@memoize
def _pid_0_exists():
    try:
        Process(0).name()
    except NoSuchProcess:
        return False
    except AccessDenied:
        return True
    else:
        return True


def pids():
    """Returns a list of PIDs currently running on the system."""
    ret = cext.pids()
    if OPENBSD and (0 not in ret) and _pid_0_exists():
        # On OpenBSD the kernel does not return PID 0 (neither does
        # ps) but it's actually querable (Process(0) will succeed).
        ret.insert(0, 0)
    return ret


if NETBSD:

    def pid_exists(pid):
        exists = _psposix.pid_exists(pid)
        if not exists:
            # We do this because _psposix.pid_exists() lies in case of
            # zombie processes.
            return pid in pids()
        else:
            return True

elif OPENBSD:

    def pid_exists(pid):
        exists = _psposix.pid_exists(pid)
        if not exists:
            return False
        else:
            # OpenBSD seems to be the only BSD platform where
            # _psposix.pid_exists() returns True for thread IDs (tids),
            # so we can't use it.
            return pid in pids()

else:  # FreeBSD
    pid_exists = _psposix.pid_exists


def is_zombie(pid):
    try:
        st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']]
        return PROC_STATUSES.get(st) == _common.STATUS_ZOMBIE
    except OSError:
        return False


def wrap_exceptions(fun):
    """Decorator which translates bare OSError exceptions into
    NoSuchProcess and AccessDenied.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except ProcessLookupError:
            if is_zombie(self.pid):
                raise ZombieProcess(self.pid, self._name, self._ppid)
            else:
                raise NoSuchProcess(self.pid, self._name)
        except PermissionError:
            raise AccessDenied(self.pid, self._name)
        except OSError:
            if self.pid == 0:
                if 0 in pids():
                    raise AccessDenied(self.pid, self._name)
                else:
                    raise
            raise

    return wrapper


@contextlib.contextmanager
def wrap_exceptions_procfs(inst):
    """Same as above, for routines relying on reading /proc fs."""
    try:
        yield
    except (ProcessLookupError, FileNotFoundError):
        # ENOENT (no such file or directory) gets raised on open().
        # ESRCH (no such process) can get raised on read() if
        # process is gone in meantime.
        if is_zombie(inst.pid):
            raise ZombieProcess(inst.pid, inst._name, inst._ppid)
        else:
            raise NoSuchProcess(inst.pid, inst._name)
    except PermissionError:
        raise AccessDenied(inst.pid, inst._name)


class Process:
    """Wrapper class around underlying C implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None

    def _assert_alive(self):
        """Raise NSP if the process disappeared on us."""
        # For those C function who do not raise NSP, possibly returning
        # incorrect or incomplete result.
        cext.proc_name(self.pid)

    @wrap_exceptions
    @memoize_when_activated
    def oneshot(self):
        """Retrieves multiple process info in one shot as a raw tuple."""
        ret = cext.proc_oneshot_info(self.pid)
        assert len(ret) == len(kinfo_proc_map)
        return ret

    def oneshot_enter(self):
        self.oneshot.cache_activate(self)

    def oneshot_exit(self):
        self.oneshot.cache_deactivate(self)

    @wrap_exceptions
    def name(self):
        name = self.oneshot()[kinfo_proc_map['name']]
        return name if name is not None else cext.proc_name(self.pid)

    @wrap_exceptions
    def exe(self):
        if FREEBSD:
            if self.pid == 0:
                return ''  # else NSP
            return cext.proc_exe(self.pid)
        elif NETBSD:
            if self.pid == 0:
                # /proc/0 dir exists but /proc/0/exe doesn't
                return ""
            with wrap_exceptions_procfs(self):
                return os.readlink("/proc/%s/exe" % self.pid)
        else:
            # OpenBSD: exe cannot be determined; references:
            # https://chromium.googlesource.com/chromium/src/base/+/
            #     master/base_paths_posix.cc
            # We try our best guess by using which against the first
            # cmdline arg (may return None).
            cmdline = self.cmdline()
            if cmdline:
                return which(cmdline[0]) or ""
            else:
                return ""

    @wrap_exceptions
    def cmdline(self):
        if OPENBSD and self.pid == 0:
            return []  # ...else it crashes
        elif NETBSD:
            # XXX - most of the times the underlying sysctl() call on
            # NetBSD and OpenBSD returns a truncated string. Also
            # /proc/pid/cmdline behaves the same so it looks like this
            # is a kernel bug.
            try:
                return cext.proc_cmdline(self.pid)
            except OSError as err:
                if err.errno == errno.EINVAL:
                    if is_zombie(self.pid):
                        raise ZombieProcess(self.pid, self._name, self._ppid)
                    elif not pid_exists(self.pid):
                        raise NoSuchProcess(self.pid, self._name, self._ppid)
                    else:
                        # XXX: this happens with unicode tests. It means the C
                        # routine is unable to decode invalid unicode chars.
                        debug("ignoring %r and returning an empty list" % err)
                        return []
                else:
                    raise
        else:
            return cext.proc_cmdline(self.pid)

    @wrap_exceptions
    def environ(self):
        return cext.proc_environ(self.pid)

    @wrap_exceptions
    def terminal(self):
        tty_nr = self.oneshot()[kinfo_proc_map['ttynr']]
        tmap = _psposix.get_terminal_map()
        try:
            return tmap[tty_nr]
        except KeyError:
            return None

    @wrap_exceptions
    def ppid(self):
        self._ppid = self.oneshot()[kinfo_proc_map['ppid']]
        return self._ppid

    @wrap_exceptions
    def uids(self):
        rawtuple = self.oneshot()
        return _common.puids(
            rawtuple[kinfo_proc_map['real_uid']],
            rawtuple[kinfo_proc_map['effective_uid']],
            rawtuple[kinfo_proc_map['saved_uid']],
        )

    @wrap_exceptions
    def gids(self):
        rawtuple = self.oneshot()
        return _common.pgids(
            rawtuple[kinfo_proc_map['real_gid']],
            rawtuple[kinfo_proc_map['effective_gid']],
            rawtuple[kinfo_proc_map['saved_gid']],
        )

    @wrap_exceptions
    def cpu_times(self):
        rawtuple = self.oneshot()
        return _common.pcputimes(
            rawtuple[kinfo_proc_map['user_time']],
            rawtuple[kinfo_proc_map['sys_time']],
            rawtuple[kinfo_proc_map['ch_user_time']],
            rawtuple[kinfo_proc_map['ch_sys_time']],
        )

    if FREEBSD:

        @wrap_exceptions
        def cpu_num(self):
            return self.oneshot()[kinfo_proc_map['cpunum']]

    @wrap_exceptions
    def memory_info(self):
        rawtuple = self.oneshot()
        return pmem(
            rawtuple[kinfo_proc_map['rss']],
            rawtuple[kinfo_proc_map['vms']],
            rawtuple[kinfo_proc_map['memtext']],
            rawtuple[kinfo_proc_map['memdata']],
            rawtuple[kinfo_proc_map['memstack']],
        )

    memory_full_info = memory_info

    @wrap_exceptions
    def create_time(self):
        return self.oneshot()[kinfo_proc_map['create_time']]

    @wrap_exceptions
    def num_threads(self):
        if HAS_PROC_NUM_THREADS:
            # FreeBSD
            return cext.proc_num_threads(self.pid)
        else:
            return len(self.threads())

    @wrap_exceptions
    def num_ctx_switches(self):
        rawtuple = self.oneshot()
        return _common.pctxsw(
            rawtuple[kinfo_proc_map['ctx_switches_vol']],
            rawtuple[kinfo_proc_map['ctx_switches_unvol']],
        )

    @wrap_exceptions
    def threads(self):
        # Note: on OpenSBD this (/dev/mem) requires root access.
        rawlist = cext.proc_threads(self.pid)
        retlist = []
        for thread_id, utime, stime in rawlist:
            ntuple = _common.pthread(thread_id, utime, stime)
            retlist.append(ntuple)
        if OPENBSD:
            self._assert_alive()
        return retlist

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        if kind not in conn_tmap:
            raise ValueError(
                "invalid %r kind argument; choose between %s"
                % (kind, ', '.join([repr(x) for x in conn_tmap]))
            )
        families, types = conn_tmap[kind]
        ret = []

        if NETBSD:
            rawlist = cext.net_connections(self.pid, kind)
        elif OPENBSD:
            rawlist = cext.net_connections(self.pid, families, types)
        else:
            rawlist = cext.proc_net_connections(self.pid, families, types)

        for item in rawlist:
            fd, fam, type, laddr, raddr, status = item[:6]
            if FREEBSD:
                if (fam not in families) or (type not in types):
                    continue
            nt = conn_to_ntuple(
                fd, fam, type, laddr, raddr, status, TCP_STATUSES
            )
            ret.append(nt)

        self._assert_alive()
        return ret

    @wrap_exceptions
    def wait(self, timeout=None):
        return _psposix.wait_pid(self.pid, timeout, self._name)

    @wrap_exceptions
    def nice_get(self):
        return cext_posix.getpriority(self.pid)

    @wrap_exceptions
    def nice_set(self, value):
        return cext_posix.setpriority(self.pid, value)

    @wrap_exceptions
    def status(self):
        code = self.oneshot()[kinfo_proc_map['status']]
        # XXX is '?' legit? (we're not supposed to return it anyway)
        return PROC_STATUSES.get(code, '?')

    @wrap_exceptions
    def io_counters(self):
        rawtuple = self.oneshot()
        return _common.pio(
            rawtuple[kinfo_proc_map['read_io_count']],
            rawtuple[kinfo_proc_map['write_io_count']],
            -1,
            -1,
        )

    @wrap_exceptions
    def cwd(self):
        """Return process current working directory."""
        # sometimes we get an empty string, in which case we turn
        # it into None
        if OPENBSD and self.pid == 0:
            return ""  # ...else it would raise EINVAL
        elif NETBSD or HAS_PROC_OPEN_FILES:
            # FreeBSD < 8 does not support functions based on
            # kinfo_getfile() and kinfo_getvmmap()
            return cext.proc_cwd(self.pid)
        else:
            raise NotImplementedError(
                "supported only starting from FreeBSD 8" if FREEBSD else ""
            )

    nt_mmap_grouped = namedtuple(
        'mmap', 'path rss, private, ref_count, shadow_count'
    )
    nt_mmap_ext = namedtuple(
        'mmap', 'addr, perms path rss, private, ref_count, shadow_count'
    )

    def _not_implemented(self):
        raise NotImplementedError

    # FreeBSD < 8 does not support functions based on kinfo_getfile()
    # and kinfo_getvmmap()
    if HAS_PROC_OPEN_FILES:

        @wrap_exceptions
        def open_files(self):
            """Return files opened by process as a list of namedtuples."""
            rawlist = cext.proc_open_files(self.pid)
            return [_common.popenfile(path, fd) for path, fd in rawlist]

    else:
        open_files = _not_implemented

    # FreeBSD < 8 does not support functions based on kinfo_getfile()
    # and kinfo_getvmmap()
    if HAS_PROC_NUM_FDS:

        @wrap_exceptions
        def num_fds(self):
            """Return the number of file descriptors opened by this process."""
            ret = cext.proc_num_fds(self.pid)
            if NETBSD:
                self._assert_alive()
            return ret

    else:
        num_fds = _not_implemented

    # --- FreeBSD only APIs

    if FREEBSD:

        @wrap_exceptions
        def cpu_affinity_get(self):
            return cext.proc_cpu_affinity_get(self.pid)

        @wrap_exceptions
        def cpu_affinity_set(self, cpus):
            # Pre-emptively check if CPUs are valid because the C
            # function has a weird behavior in case of invalid CPUs,
            # see: https://github.com/giampaolo/psutil/issues/586
            allcpus = tuple(range(len(per_cpu_times())))
            for cpu in cpus:
                if cpu not in allcpus:
                    raise ValueError(
                        "invalid CPU #%i (choose between %s)" % (cpu, allcpus)
                    )
            try:
                cext.proc_cpu_affinity_set(self.pid, cpus)
            except OSError as err:
                # 'man cpuset_setaffinity' about EDEADLK:
                # <<the call would leave a thread without a valid CPU to run
                # on because the set does not overlap with the thread's
                # anonymous mask>>
                if err.errno in (errno.EINVAL, errno.EDEADLK):
                    for cpu in cpus:
                        if cpu not in allcpus:
                            raise ValueError(
                                "invalid CPU #%i (choose between %s)"
                                % (cpu, allcpus)
                            )
                raise

        @wrap_exceptions
        def memory_maps(self):
            return cext.proc_memory_maps(self.pid)

        @wrap_exceptions
        def rlimit(self, resource, limits=None):
            if limits is None:
                return cext.proc_getrlimit(self.pid, resource)
            else:
                if len(limits) != 2:
                    raise ValueError(
                        "second argument must be a (soft, hard) tuple, got %s"
                        % repr(limits)
                    )
                soft, hard = limits
                return cext.proc_setrlimit(self.pid, resource, soft, hard)
PKok\w�]���psutil/_pswindows.pynu�[���# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Windows platform implementation."""

import contextlib
import errno
import functools
import os
import signal
import sys
import time
from collections import namedtuple

from . import _common
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import AccessDenied
from ._common import NoSuchProcess
from ._common import TimeoutExpired
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import debug
from ._common import isfile_strict
from ._common import memoize
from ._common import memoize_when_activated
from ._common import parse_environ_block
from ._common import usage_percent
from ._compat import PY3
from ._compat import long
from ._compat import lru_cache
from ._compat import range
from ._compat import unicode
from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS
from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS
from ._psutil_windows import HIGH_PRIORITY_CLASS
from ._psutil_windows import IDLE_PRIORITY_CLASS
from ._psutil_windows import NORMAL_PRIORITY_CLASS
from ._psutil_windows import REALTIME_PRIORITY_CLASS


try:
    from . import _psutil_windows as cext
except ImportError as err:
    if (
        str(err).lower().startswith("dll load failed")
        and sys.getwindowsversion()[0] < 6
    ):
        # We may get here if:
        # 1) we are on an old Windows version
        # 2) psutil was installed via pip + wheel
        # See: https://github.com/giampaolo/psutil/issues/811
        msg = "this Windows version is too old (< Windows Vista); "
        msg += "psutil 3.4.2 is the latest version which supports Windows "
        msg += "2000, XP and 2003 server"
        raise RuntimeError(msg)
    else:
        raise

if PY3:
    import enum
else:
    enum = None

# process priority constants, import from __init__.py:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
# fmt: off
__extra__all__ = [
    "win_service_iter", "win_service_get",
    # Process priority
    "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
    "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS",
    "REALTIME_PRIORITY_CLASS",
    # IO priority
    "IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH",
    # others
    "CONN_DELETE_TCB", "AF_LINK",
]
# fmt: on


# =====================================================================
# --- globals
# =====================================================================

CONN_DELETE_TCB = "DELETE_TCB"
ERROR_PARTIAL_COPY = 299
PYPY = '__pypy__' in sys.builtin_module_names

if enum is None:
    AF_LINK = -1
else:
    AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1})
    AF_LINK = AddressFamily.AF_LINK

TCP_STATUSES = {
    cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED,
    cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT,
    cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV,
    cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1,
    cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2,
    cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT,
    cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE,
    cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
    cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK,
    cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN,
    cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING,
    cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB,
    cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}

if enum is not None:

    class Priority(enum.IntEnum):
        ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS
        BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS
        HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS
        IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS
        NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS
        REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS

    globals().update(Priority.__members__)

if enum is None:
    IOPRIO_VERYLOW = 0
    IOPRIO_LOW = 1
    IOPRIO_NORMAL = 2
    IOPRIO_HIGH = 3
else:

    class IOPriority(enum.IntEnum):
        IOPRIO_VERYLOW = 0
        IOPRIO_LOW = 1
        IOPRIO_NORMAL = 2
        IOPRIO_HIGH = 3

    globals().update(IOPriority.__members__)

pinfo_map = dict(
    num_handles=0,
    ctx_switches=1,
    user_time=2,
    kernel_time=3,
    create_time=4,
    num_threads=5,
    io_rcount=6,
    io_wcount=7,
    io_rbytes=8,
    io_wbytes=9,
    io_count_others=10,
    io_bytes_others=11,
    num_page_faults=12,
    peak_wset=13,
    wset=14,
    peak_paged_pool=15,
    paged_pool=16,
    peak_non_paged_pool=17,
    non_paged_pool=18,
    pagefile=19,
    peak_pagefile=20,
    mem_private=21,
)


# =====================================================================
# --- named tuples
# =====================================================================


# fmt: off
# psutil.cpu_times()
scputimes = namedtuple('scputimes',
                       ['user', 'system', 'idle', 'interrupt', 'dpc'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_info()
pmem = namedtuple(
    'pmem', ['rss', 'vms',
             'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
             'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
             'pagefile', 'peak_pagefile', 'private'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
    'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
                         'read_bytes', 'write_bytes',
                         'other_count', 'other_bytes'])
# fmt: on


# =====================================================================
# --- utils
# =====================================================================


@lru_cache(maxsize=512)
def convert_dos_path(s):
    r"""Convert paths using native DOS format like:
        "\Device\HarddiskVolume1\Windows\systemew\file.txt"
    into:
        "C:\Windows\systemew\file.txt".
    """
    rawdrive = '\\'.join(s.split('\\')[:3])
    driveletter = cext.QueryDosDevice(rawdrive)
    remainder = s[len(rawdrive) :]
    return os.path.join(driveletter, remainder)


def py2_strencode(s):
    """Encode a unicode string to a byte string by using the default fs
    encoding + "replace" error handler.
    """
    if PY3:
        return s
    else:
        if isinstance(s, str):
            return s
        else:
            return s.encode(ENCODING, ENCODING_ERRS)


@memoize
def getpagesize():
    return cext.getpagesize()


# =====================================================================
# --- memory
# =====================================================================


def virtual_memory():
    """System virtual memory as a namedtuple."""
    mem = cext.virtual_mem()
    totphys, availphys, _totsys, _availsys = mem
    total = totphys
    avail = availphys
    free = availphys
    used = total - avail
    percent = usage_percent((total - avail), total, round_=1)
    return svmem(total, avail, percent, used, free)


def swap_memory():
    """Swap system memory as a (total, used, free, sin, sout) tuple."""
    mem = cext.virtual_mem()

    total_phys = mem[0]
    total_system = mem[2]

    # system memory (commit total/limit) is the sum of physical and swap
    # thus physical memory values need to be subtracted to get swap values
    total = total_system - total_phys
    # commit total is incremented immediately (decrementing free_system)
    # while the corresponding free physical value is not decremented until
    # pages are accessed, so we can't use free system memory for swap.
    # instead, we calculate page file usage based on performance counter
    if total > 0:
        percentswap = cext.swap_percent()
        used = int(0.01 * percentswap * total)
    else:
        percentswap = 0.0
        used = 0

    free = total - used
    percent = round(percentswap, 1)
    return _common.sswap(total, used, free, percent, 0, 0)


# =====================================================================
# --- disk
# =====================================================================


disk_io_counters = cext.disk_io_counters


def disk_usage(path):
    """Return disk usage associated with path."""
    if PY3 and isinstance(path, bytes):
        # XXX: do we want to use "strict"? Probably yes, in order
        # to fail immediately. After all we are accepting input here...
        path = path.decode(ENCODING, errors="strict")
    total, free = cext.disk_usage(path)
    used = total - free
    percent = usage_percent(used, total, round_=1)
    return _common.sdiskusage(total, used, free, percent)


def disk_partitions(all):
    """Return disk partitions."""
    rawlist = cext.disk_partitions(all)
    return [_common.sdiskpart(*x) for x in rawlist]


# =====================================================================
# --- CPU
# =====================================================================


def cpu_times():
    """Return system CPU times as a named tuple."""
    user, system, idle = cext.cpu_times()
    # Internally, GetSystemTimes() is used, and it doesn't return
    # interrupt and dpc times. cext.per_cpu_times() does, so we
    # rely on it to get those only.
    percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())])
    return scputimes(
        user, system, idle, percpu_summed.interrupt, percpu_summed.dpc
    )


def per_cpu_times():
    """Return system per-CPU times as a list of named tuples."""
    ret = []
    for user, system, idle, interrupt, dpc in cext.per_cpu_times():
        item = scputimes(user, system, idle, interrupt, dpc)
        ret.append(item)
    return ret


def cpu_count_logical():
    """Return the number of logical CPUs in the system."""
    return cext.cpu_count_logical()


def cpu_count_cores():
    """Return the number of CPU cores in the system."""
    return cext.cpu_count_cores()


def cpu_stats():
    """Return CPU statistics."""
    ctx_switches, interrupts, _dpcs, syscalls = cext.cpu_stats()
    soft_interrupts = 0
    return _common.scpustats(
        ctx_switches, interrupts, soft_interrupts, syscalls
    )


def cpu_freq():
    """Return CPU frequency.
    On Windows per-cpu frequency is not supported.
    """
    curr, max_ = cext.cpu_freq()
    min_ = 0.0
    return [_common.scpufreq(float(curr), min_, float(max_))]


_loadavg_inititialized = False


def getloadavg():
    """Return the number of processes in the system run queue averaged
    over the last 1, 5, and 15 minutes respectively as a tuple.
    """
    global _loadavg_inititialized

    if not _loadavg_inititialized:
        cext.init_loadavg_counter()
        _loadavg_inititialized = True

    # Drop to 2 decimal points which is what Linux does
    raw_loads = cext.getloadavg()
    return tuple([round(load, 2) for load in raw_loads])


# =====================================================================
# --- network
# =====================================================================


def net_connections(kind, _pid=-1):
    """Return socket connections.  If pid == -1 return system-wide
    connections (as opposed to connections opened by one process only).
    """
    if kind not in conn_tmap:
        raise ValueError(
            "invalid %r kind argument; choose between %s"
            % (kind, ', '.join([repr(x) for x in conn_tmap]))
        )
    families, types = conn_tmap[kind]
    rawlist = cext.net_connections(_pid, families, types)
    ret = set()
    for item in rawlist:
        fd, fam, type, laddr, raddr, status, pid = item
        nt = conn_to_ntuple(
            fd,
            fam,
            type,
            laddr,
            raddr,
            status,
            TCP_STATUSES,
            pid=pid if _pid == -1 else None,
        )
        ret.add(nt)
    return list(ret)


def net_if_stats():
    """Get NIC stats (isup, duplex, speed, mtu)."""
    ret = {}
    rawdict = cext.net_if_stats()
    for name, items in rawdict.items():
        if not PY3:
            assert isinstance(name, unicode), type(name)
            name = py2_strencode(name)
        isup, duplex, speed, mtu = items
        if hasattr(_common, 'NicDuplex'):
            duplex = _common.NicDuplex(duplex)
        ret[name] = _common.snicstats(isup, duplex, speed, mtu, '')
    return ret


def net_io_counters():
    """Return network I/O statistics for every network interface
    installed on the system as a dict of raw tuples.
    """
    ret = cext.net_io_counters()
    return dict([(py2_strencode(k), v) for k, v in ret.items()])


def net_if_addrs():
    """Return the addresses associated to each NIC."""
    ret = []
    for items in cext.net_if_addrs():
        items = list(items)
        items[0] = py2_strencode(items[0])
        ret.append(items)
    return ret


# =====================================================================
# --- sensors
# =====================================================================


def sensors_battery():
    """Return battery information."""
    # For constants meaning see:
    # https://msdn.microsoft.com/en-us/library/windows/desktop/
    #     aa373232(v=vs.85).aspx
    acline_status, flags, percent, secsleft = cext.sensors_battery()
    power_plugged = acline_status == 1
    no_battery = bool(flags & 128)
    charging = bool(flags & 8)

    if no_battery:
        return None
    if power_plugged or charging:
        secsleft = _common.POWER_TIME_UNLIMITED
    elif secsleft == -1:
        secsleft = _common.POWER_TIME_UNKNOWN

    return _common.sbattery(percent, secsleft, power_plugged)


# =====================================================================
# --- other system functions
# =====================================================================


_last_btime = 0


def boot_time():
    """The system boot time expressed in seconds since the epoch."""
    # This dirty hack is to adjust the precision of the returned
    # value which may have a 1 second fluctuation, see:
    # https://github.com/giampaolo/psutil/issues/1007
    global _last_btime
    ret = float(cext.boot_time())
    if abs(ret - _last_btime) <= 1:
        return _last_btime
    else:
        _last_btime = ret
        return ret


def users():
    """Return currently connected users as a list of namedtuples."""
    retlist = []
    rawlist = cext.users()
    for item in rawlist:
        user, hostname, tstamp = item
        user = py2_strencode(user)
        nt = _common.suser(user, None, hostname, tstamp, None)
        retlist.append(nt)
    return retlist


# =====================================================================
# --- Windows services
# =====================================================================


def win_service_iter():
    """Yields a list of WindowsService instances."""
    for name, display_name in cext.winservice_enumerate():
        yield WindowsService(py2_strencode(name), py2_strencode(display_name))


def win_service_get(name):
    """Open a Windows service and return it as a WindowsService instance."""
    service = WindowsService(name, None)
    service._display_name = service._query_config()['display_name']
    return service


class WindowsService:  # noqa: PLW1641
    """Represents an installed Windows service."""

    def __init__(self, name, display_name):
        self._name = name
        self._display_name = display_name

    def __str__(self):
        details = "(name=%r, display_name=%r)" % (
            self._name,
            self._display_name,
        )
        return "%s%s" % (self.__class__.__name__, details)

    def __repr__(self):
        return "<%s at %s>" % (self.__str__(), id(self))

    def __eq__(self, other):
        # Test for equality with another WindosService object based
        # on name.
        if not isinstance(other, WindowsService):
            return NotImplemented
        return self._name == other._name

    def __ne__(self, other):
        return not self == other

    def _query_config(self):
        with self._wrap_exceptions():
            display_name, binpath, username, start_type = (
                cext.winservice_query_config(self._name)
            )
        # XXX - update _self.display_name?
        return dict(
            display_name=py2_strencode(display_name),
            binpath=py2_strencode(binpath),
            username=py2_strencode(username),
            start_type=py2_strencode(start_type),
        )

    def _query_status(self):
        with self._wrap_exceptions():
            status, pid = cext.winservice_query_status(self._name)
        if pid == 0:
            pid = None
        return dict(status=status, pid=pid)

    @contextlib.contextmanager
    def _wrap_exceptions(self):
        """Ctx manager which translates bare OSError and WindowsError
        exceptions into NoSuchProcess and AccessDenied.
        """
        try:
            yield
        except OSError as err:
            if is_permission_err(err):
                msg = (
                    "service %r is not querable (not enough privileges)"
                    % self._name
                )
                raise AccessDenied(pid=None, name=self._name, msg=msg)
            elif err.winerror in (
                cext.ERROR_INVALID_NAME,
                cext.ERROR_SERVICE_DOES_NOT_EXIST,
            ):
                msg = "service %r does not exist" % self._name
                raise NoSuchProcess(pid=None, name=self._name, msg=msg)
            else:
                raise

    # config query

    def name(self):
        """The service name. This string is how a service is referenced
        and can be passed to win_service_get() to get a new
        WindowsService instance.
        """
        return self._name

    def display_name(self):
        """The service display name. The value is cached when this class
        is instantiated.
        """
        return self._display_name

    def binpath(self):
        """The fully qualified path to the service binary/exe file as
        a string, including command line arguments.
        """
        return self._query_config()['binpath']

    def username(self):
        """The name of the user that owns this service."""
        return self._query_config()['username']

    def start_type(self):
        """A string which can either be "automatic", "manual" or
        "disabled".
        """
        return self._query_config()['start_type']

    # status query

    def pid(self):
        """The process PID, if any, else None. This can be passed
        to Process class to control the service's process.
        """
        return self._query_status()['pid']

    def status(self):
        """Service status as a string."""
        return self._query_status()['status']

    def description(self):
        """Service long description."""
        return py2_strencode(cext.winservice_query_descr(self.name()))

    # utils

    def as_dict(self):
        """Utility method retrieving all the information above as a
        dictionary.
        """
        d = self._query_config()
        d.update(self._query_status())
        d['name'] = self.name()
        d['display_name'] = self.display_name()
        d['description'] = self.description()
        return d

    # actions
    # XXX: the necessary C bindings for start() and stop() are
    # implemented but for now I prefer not to expose them.
    # I may change my mind in the future. Reasons:
    # - they require Administrator privileges
    # - can't implement a timeout for stop() (unless by using a thread,
    #   which sucks)
    # - would require adding ServiceAlreadyStarted and
    #   ServiceAlreadyStopped exceptions, adding two new APIs.
    # - we might also want to have modify(), which would basically mean
    #   rewriting win32serviceutil.ChangeServiceConfig, which involves a
    #   lot of stuff (and API constants which would pollute the API), see:
    #   http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/
    #       win32/lib/win32serviceutil.py.html#0175
    # - psutil is typically about "read only" monitoring stuff;
    #   win_service_* APIs should only be used to retrieve a service and
    #   check whether it's running

    # def start(self, timeout=None):
    #     with self._wrap_exceptions():
    #         cext.winservice_start(self.name())
    #         if timeout:
    #             giveup_at = time.time() + timeout
    #             while True:
    #                 if self.status() == "running":
    #                     return
    #                 else:
    #                     if time.time() > giveup_at:
    #                         raise TimeoutExpired(timeout)
    #                     else:
    #                         time.sleep(.1)

    # def stop(self):
    #     # Note: timeout is not implemented because it's just not
    #     # possible, see:
    #     # http://stackoverflow.com/questions/11973228/
    #     with self._wrap_exceptions():
    #         return cext.winservice_stop(self.name())


# =====================================================================
# --- processes
# =====================================================================


pids = cext.pids
pid_exists = cext.pid_exists
ppid_map = cext.ppid_map  # used internally by Process.children()


def is_permission_err(exc):
    """Return True if this is a permission error."""
    assert isinstance(exc, OSError), exc
    if exc.errno in (errno.EPERM, errno.EACCES):
        return True
    # On Python 2 OSError doesn't always have 'winerror'. Sometimes
    # it does, in which case the original exception was WindowsError
    # (which is a subclass of OSError).
    return getattr(exc, "winerror", -1) in (
        cext.ERROR_ACCESS_DENIED,
        cext.ERROR_PRIVILEGE_NOT_HELD,
    )


def convert_oserror(exc, pid=None, name=None):
    """Convert OSError into NoSuchProcess or AccessDenied."""
    assert isinstance(exc, OSError), exc
    if is_permission_err(exc):
        return AccessDenied(pid=pid, name=name)
    if exc.errno == errno.ESRCH:
        return NoSuchProcess(pid=pid, name=name)
    raise exc


def wrap_exceptions(fun):
    """Decorator which converts OSError into NoSuchProcess or AccessDenied."""

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        try:
            return fun(self, *args, **kwargs)
        except OSError as err:
            raise convert_oserror(err, pid=self.pid, name=self._name)

    return wrapper


def retry_error_partial_copy(fun):
    """Workaround for https://github.com/giampaolo/psutil/issues/875.
    See: https://stackoverflow.com/questions/4457745#4457745.
    """

    @functools.wraps(fun)
    def wrapper(self, *args, **kwargs):
        delay = 0.0001
        times = 33
        for _ in range(times):  # retries for roughly 1 second
            try:
                return fun(self, *args, **kwargs)
            except WindowsError as _:
                err = _
                if err.winerror == ERROR_PARTIAL_COPY:
                    time.sleep(delay)
                    delay = min(delay * 2, 0.04)
                    continue
                raise
        msg = (
            "{} retried {} times, converted to AccessDenied as it's still"
            "returning {}".format(fun, times, err)
        )
        raise AccessDenied(pid=self.pid, name=self._name, msg=msg)

    return wrapper


class Process:
    """Wrapper class around underlying C implementation."""

    __slots__ = ["_cache", "_name", "_ppid", "pid"]

    def __init__(self, pid):
        self.pid = pid
        self._name = None
        self._ppid = None

    # --- oneshot() stuff

    def oneshot_enter(self):
        self._proc_info.cache_activate(self)
        self.exe.cache_activate(self)

    def oneshot_exit(self):
        self._proc_info.cache_deactivate(self)
        self.exe.cache_deactivate(self)

    @memoize_when_activated
    def _proc_info(self):
        """Return multiple information about this process as a
        raw tuple.
        """
        ret = cext.proc_info(self.pid)
        assert len(ret) == len(pinfo_map)
        return ret

    def name(self):
        """Return process name, which on Windows is always the final
        part of the executable.
        """
        # This is how PIDs 0 and 4 are always represented in taskmgr
        # and process-hacker.
        if self.pid == 0:
            return "System Idle Process"
        if self.pid == 4:
            return "System"
        return os.path.basename(self.exe())

    @wrap_exceptions
    @memoize_when_activated
    def exe(self):
        if PYPY:
            try:
                exe = cext.proc_exe(self.pid)
            except WindowsError as err:
                # 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens
                # (perhaps PyPy's JIT delaying garbage collection of files?).
                if err.errno == 24:
                    debug("%r translated into AccessDenied" % err)
                    raise AccessDenied(self.pid, self._name)
                raise
        else:
            exe = cext.proc_exe(self.pid)
        if not PY3:
            exe = py2_strencode(exe)
        if exe.startswith('\\'):
            return convert_dos_path(exe)
        return exe  # May be "Registry", "MemCompression", ...

    @wrap_exceptions
    @retry_error_partial_copy
    def cmdline(self):
        if cext.WINVER >= cext.WINDOWS_8_1:
            # PEB method detects cmdline changes but requires more
            # privileges: https://github.com/giampaolo/psutil/pull/1398
            try:
                ret = cext.proc_cmdline(self.pid, use_peb=True)
            except OSError as err:
                if is_permission_err(err):
                    ret = cext.proc_cmdline(self.pid, use_peb=False)
                else:
                    raise
        else:
            ret = cext.proc_cmdline(self.pid, use_peb=True)
        if PY3:
            return ret
        else:
            return [py2_strencode(s) for s in ret]

    @wrap_exceptions
    @retry_error_partial_copy
    def environ(self):
        ustr = cext.proc_environ(self.pid)
        if ustr and not PY3:
            assert isinstance(ustr, unicode), type(ustr)
        return parse_environ_block(py2_strencode(ustr))

    def ppid(self):
        try:
            return ppid_map()[self.pid]
        except KeyError:
            raise NoSuchProcess(self.pid, self._name)

    def _get_raw_meminfo(self):
        try:
            return cext.proc_memory_info(self.pid)
        except OSError as err:
            if is_permission_err(err):
                # TODO: the C ext can probably be refactored in order
                # to get this from cext.proc_info()
                debug("attempting memory_info() fallback (slower)")
                info = self._proc_info()
                return (
                    info[pinfo_map['num_page_faults']],
                    info[pinfo_map['peak_wset']],
                    info[pinfo_map['wset']],
                    info[pinfo_map['peak_paged_pool']],
                    info[pinfo_map['paged_pool']],
                    info[pinfo_map['peak_non_paged_pool']],
                    info[pinfo_map['non_paged_pool']],
                    info[pinfo_map['pagefile']],
                    info[pinfo_map['peak_pagefile']],
                    info[pinfo_map['mem_private']],
                )
            raise

    @wrap_exceptions
    def memory_info(self):
        # on Windows RSS == WorkingSetSize and VSM == PagefileUsage.
        # Underlying C function returns fields of PROCESS_MEMORY_COUNTERS
        # struct.
        t = self._get_raw_meminfo()
        rss = t[2]  # wset
        vms = t[7]  # pagefile
        return pmem(*(rss, vms) + t)

    @wrap_exceptions
    def memory_full_info(self):
        basic_mem = self.memory_info()
        uss = cext.proc_memory_uss(self.pid)
        uss *= getpagesize()
        return pfullmem(*basic_mem + (uss,))

    def memory_maps(self):
        try:
            raw = cext.proc_memory_maps(self.pid)
        except OSError as err:
            # XXX - can't use wrap_exceptions decorator as we're
            # returning a generator; probably needs refactoring.
            raise convert_oserror(err, self.pid, self._name)
        else:
            for addr, perm, path, rss in raw:
                path = convert_dos_path(path)
                if not PY3:
                    path = py2_strencode(path)
                addr = hex(addr)
                yield (addr, perm, path, rss)

    @wrap_exceptions
    def kill(self):
        return cext.proc_kill(self.pid)

    @wrap_exceptions
    def send_signal(self, sig):
        if sig == signal.SIGTERM:
            cext.proc_kill(self.pid)
        # py >= 2.7
        elif sig in (
            getattr(signal, "CTRL_C_EVENT", object()),
            getattr(signal, "CTRL_BREAK_EVENT", object()),
        ):
            os.kill(self.pid, sig)
        else:
            msg = (
                "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
                "are supported on Windows"
            )
            raise ValueError(msg)

    @wrap_exceptions
    def wait(self, timeout=None):
        if timeout is None:
            cext_timeout = cext.INFINITE
        else:
            # WaitForSingleObject() expects time in milliseconds.
            cext_timeout = int(timeout * 1000)

        timer = getattr(time, 'monotonic', time.time)
        stop_at = timer() + timeout if timeout is not None else None

        try:
            # Exit code is supposed to come from GetExitCodeProcess().
            # May also be None if OpenProcess() failed with
            # ERROR_INVALID_PARAMETER, meaning PID is already gone.
            exit_code = cext.proc_wait(self.pid, cext_timeout)
        except cext.TimeoutExpired:
            # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise.
            raise TimeoutExpired(timeout, self.pid, self._name)
        except cext.TimeoutAbandoned:
            # WaitForSingleObject() returned WAIT_ABANDONED, see:
            # https://github.com/giampaolo/psutil/issues/1224
            # We'll just rely on the internal polling and return None
            # when the PID disappears. Subprocess module does the same
            # (return None):
            # https://github.com/python/cpython/blob/
            #     be50a7b627d0aa37e08fa8e2d5568891f19903ce/
            #     Lib/subprocess.py#L1193-L1194
            exit_code = None

        # At this point WaitForSingleObject() returned WAIT_OBJECT_0,
        # meaning the process is gone. Stupidly there are cases where
        # its PID may still stick around so we do a further internal
        # polling.
        delay = 0.0001
        while True:
            if not pid_exists(self.pid):
                return exit_code
            if stop_at and timer() >= stop_at:
                raise TimeoutExpired(timeout, pid=self.pid, name=self._name)
            time.sleep(delay)
            delay = min(delay * 2, 0.04)  # incremental delay

    @wrap_exceptions
    def username(self):
        if self.pid in (0, 4):
            return 'NT AUTHORITY\\SYSTEM'
        domain, user = cext.proc_username(self.pid)
        return py2_strencode(domain) + '\\' + py2_strencode(user)

    @wrap_exceptions
    def create_time(self, fast_only=False):
        # Note: proc_times() not put under oneshot() 'cause create_time()
        # is already cached by the main Process class.
        try:
            _user, _system, created = cext.proc_times(self.pid)
            return created
        except OSError as err:
            if is_permission_err(err):
                if fast_only:
                    raise
                debug("attempting create_time() fallback (slower)")
                return self._proc_info()[pinfo_map['create_time']]
            raise

    @wrap_exceptions
    def num_threads(self):
        return self._proc_info()[pinfo_map['num_threads']]

    @wrap_exceptions
    def threads(self):
        rawlist = cext.proc_threads(self.pid)
        retlist = []
        for thread_id, utime, stime in rawlist:
            ntuple = _common.pthread(thread_id, utime, stime)
            retlist.append(ntuple)
        return retlist

    @wrap_exceptions
    def cpu_times(self):
        try:
            user, system, _created = cext.proc_times(self.pid)
        except OSError as err:
            if not is_permission_err(err):
                raise
            debug("attempting cpu_times() fallback (slower)")
            info = self._proc_info()
            user = info[pinfo_map['user_time']]
            system = info[pinfo_map['kernel_time']]
        # Children user/system times are not retrievable (set to 0).
        return _common.pcputimes(user, system, 0.0, 0.0)

    @wrap_exceptions
    def suspend(self):
        cext.proc_suspend_or_resume(self.pid, True)

    @wrap_exceptions
    def resume(self):
        cext.proc_suspend_or_resume(self.pid, False)

    @wrap_exceptions
    @retry_error_partial_copy
    def cwd(self):
        if self.pid in (0, 4):
            raise AccessDenied(self.pid, self._name)
        # return a normalized pathname since the native C function appends
        # "\\" at the and of the path
        path = cext.proc_cwd(self.pid)
        return py2_strencode(os.path.normpath(path))

    @wrap_exceptions
    def open_files(self):
        if self.pid in (0, 4):
            return []
        ret = set()
        # Filenames come in in native format like:
        # "\Device\HarddiskVolume1\Windows\systemew\file.txt"
        # Convert the first part in the corresponding drive letter
        # (e.g. "C:\") by using Windows's QueryDosDevice()
        raw_file_names = cext.proc_open_files(self.pid)
        for _file in raw_file_names:
            _file = convert_dos_path(_file)
            if isfile_strict(_file):
                if not PY3:
                    _file = py2_strencode(_file)
                ntuple = _common.popenfile(_file, -1)
                ret.add(ntuple)
        return list(ret)

    @wrap_exceptions
    def net_connections(self, kind='inet'):
        return net_connections(kind, _pid=self.pid)

    @wrap_exceptions
    def nice_get(self):
        value = cext.proc_priority_get(self.pid)
        if enum is not None:
            value = Priority(value)
        return value

    @wrap_exceptions
    def nice_set(self, value):
        return cext.proc_priority_set(self.pid, value)

    @wrap_exceptions
    def ionice_get(self):
        ret = cext.proc_io_priority_get(self.pid)
        if enum is not None:
            ret = IOPriority(ret)
        return ret

    @wrap_exceptions
    def ionice_set(self, ioclass, value):
        if value:
            msg = "value argument not accepted on Windows"
            raise TypeError(msg)
        if ioclass not in (
            IOPRIO_VERYLOW,
            IOPRIO_LOW,
            IOPRIO_NORMAL,
            IOPRIO_HIGH,
        ):
            raise ValueError("%s is not a valid priority" % ioclass)
        cext.proc_io_priority_set(self.pid, ioclass)

    @wrap_exceptions
    def io_counters(self):
        try:
            ret = cext.proc_io_counters(self.pid)
        except OSError as err:
            if not is_permission_err(err):
                raise
            debug("attempting io_counters() fallback (slower)")
            info = self._proc_info()
            ret = (
                info[pinfo_map['io_rcount']],
                info[pinfo_map['io_wcount']],
                info[pinfo_map['io_rbytes']],
                info[pinfo_map['io_wbytes']],
                info[pinfo_map['io_count_others']],
                info[pinfo_map['io_bytes_others']],
            )
        return pio(*ret)

    @wrap_exceptions
    def status(self):
        suspended = cext.proc_is_suspended(self.pid)
        if suspended:
            return _common.STATUS_STOPPED
        else:
            return _common.STATUS_RUNNING

    @wrap_exceptions
    def cpu_affinity_get(self):
        def from_bitmask(x):
            return [i for i in range(64) if (1 << i) & x]

        bitmask = cext.proc_cpu_affinity_get(self.pid)
        return from_bitmask(bitmask)

    @wrap_exceptions
    def cpu_affinity_set(self, value):
        def to_bitmask(ls):
            if not ls:
                raise ValueError("invalid argument %r" % ls)
            out = 0
            for b in ls:
                out |= 2**b
            return out

        # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER
        # is returned for an invalid CPU but this seems not to be true,
        # therefore we check CPUs validy beforehand.
        allcpus = list(range(len(per_cpu_times())))
        for cpu in value:
            if cpu not in allcpus:
                if not isinstance(cpu, (int, long)):
                    raise TypeError(
                        "invalid CPU %r; an integer is required" % cpu
                    )
                else:
                    raise ValueError("invalid CPU %r" % cpu)

        bitmask = to_bitmask(value)
        cext.proc_cpu_affinity_set(self.pid, bitmask)

    @wrap_exceptions
    def num_handles(self):
        try:
            return cext.proc_num_handles(self.pid)
        except OSError as err:
            if is_permission_err(err):
                debug("attempting num_handles() fallback (slower)")
                return self._proc_info()[pinfo_map['num_handles']]
            raise

    @wrap_exceptions
    def num_ctx_switches(self):
        ctx_switches = self._proc_info()[pinfo_map['ctx_switches']]
        # only voluntary ctx switches are supported
        return _common.pctxsw(ctx_switches, 0)
PKok\�ɞ1�� netifaces-0.11.0.dist-info/WHEELnu�[���Wheel-Version: 1.0
Generator: bdist_wheel (0.36.2)
Root-Is-Purelib: false
Tag: cp39-cp39-manylinux_2_5_x86_64
Tag: cp39-cp39-manylinux1_x86_64

PKok\���**"netifaces-0.11.0.dist-info/LICENSEnu�[���Copyright (c) 2007-2018 Alastair Houghton

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
PKok\�zb�

!netifaces-0.11.0.dist-info/RECORDnu�[���netifaces-0.11.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
netifaces-0.11.0.dist-info/LICENSE,sha256=sguJUWS3K5zAFw5sDWCxT5qqzGhiwFVu7UHqo0iINwU,1066
netifaces-0.11.0.dist-info/METADATA,sha256=6Bt05nLw45zo4zoDnKuyNyFePxJdOG25S1chH-5aRxg,8951
netifaces-0.11.0.dist-info/RECORD,,
netifaces-0.11.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
netifaces-0.11.0.dist-info/WHEEL,sha256=mpPt74xeHFyJyXQeJqOMUfs_5y9wKBGl7ZdT5s47bhE,144
netifaces-0.11.0.dist-info/top_level.txt,sha256=PqMTaIuWtSjkdQHX6lH1Lmpv2aqBUYAGqATB8z3A6TQ,10
netifaces-0.11.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
netifaces.cpython-39-x86_64-linux-gnu.so,sha256=9HiqVAHU4w1_WXrDxHO4U-wqaoOZr3Vzjr9rKPgAqgU,67181
PKok\t��/�"�"#netifaces-0.11.0.dist-info/METADATAnu�[���Metadata-Version: 2.1
Name: netifaces
Version: 0.11.0
Summary: Portable network interface information.
Home-page: https://github.com/al45tair/netifaces
Author: Alastair Houghton
Author-email: alastair@alastairs-place.net
License: MIT License
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Topic :: System :: Networking
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
License-File: LICENSE

netifaces 0.10.8
================

+-------------+------------------+
| Linux/macOS | |BuildStatus|    |
+-------------+------------------+
| Windows     | |WinBuildStatus| |
+-------------+------------------+

.. |BuildStatus| image:: https://travis-ci.org/al45tair/netifaces.svg?branch=master
   :target: https://travis-ci.org/al45tair/netifaces
   :alt: Build Status (Linux/Mac)

.. |WinBuildStatus| image:: https://ci.appveyor.com/api/projects/status/3ctn1bl0aigpfjoo/branch/master?svg=true
   :target: https://ci.appveyor.com/project/al45tair/netifaces/branch/master
   :alt: Build Status (Windows)

.. warning::

   netifaces needs a new maintainer.  al45tair is no longer able to maintain it
   or make new releases due to work commitments.

1. What is this?
----------------

It's been annoying me for some time that there's no easy way to get the
address(es) of the machine's network interfaces from Python.  There is
a good reason for this difficulty, which is that it is virtually impossible
to do so in a portable manner.  However, it seems to me that there should
be a package you can easy_install that will take care of working out the
details of doing so on the machine you're using, then you can get on with
writing Python code without concerning yourself with the nitty gritty of
system-dependent low-level networking APIs.

This package attempts to solve that problem.

2. How do I use it?
-------------------

First you need to install it, which you can do by typing::

  tar xvzf netifaces-0.10.8.tar.gz
  cd netifaces-0.10.8
  python setup.py install

**Note that you will need the relevant developer tools for your platform**,
as netifaces is written in C and installing this way will compile the extension.

Once that's done, you'll need to start Python and do something like the
following::

>>> import netifaces

Then if you enter

>>> netifaces.interfaces()
['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']

you'll see the list of interface identifiers for your machine.

You can ask for the addresses of a particular interface by doing

>>> netifaces.ifaddresses('lo0')
{18: [{'addr': ''}], 2: [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}], 30: [{'peer': '::1', 'netmask': 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'addr': '::1'}, {'peer': '', 'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::1%lo0'}]}

Hmmmm.  That result looks a bit cryptic; let's break it apart and explain
what each piece means.  It returned a dictionary, so let's look there first::

  { 18: [...], 2: [...], 30: [...] }

Each of the numbers refers to a particular address family.  In this case, we
have three address families listed; on my system, 18 is ``AF_LINK`` (which means
the link layer interface, e.g. Ethernet), 2 is ``AF_INET`` (normal Internet
addresses), and 30 is ``AF_INET6`` (IPv6).

But wait!  Don't use these numbers in your code.  The numeric values here are
system dependent; fortunately, I thought of that when writing netifaces, so
the module declares a range of values that you might need.  e.g.

>>> netifaces.AF_LINK
18

Again, on your system, the number may be different.

So, what we've established is that the dictionary that's returned has one
entry for each address family for which this interface has an address.  Let's
take a look at the ``AF_INET`` addresses now:

>>> addrs = netifaces.ifaddresses('lo0')
>>> addrs[netifaces.AF_INET]
[{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]

You might be wondering why this value is a list.  The reason is that it's
possible for an interface to have more than one address, even within the
same family.  I'll say that again: *you can have more than one address of
the same type associated with each interface*.

*Asking for "the" address of a particular interface doesn't make sense.*

Right, so, we can see that this particular interface only has one address,
and, because it's a loopback interface, it's point-to-point and therefore
has a *peer* address rather than a broadcast address.

Let's look at a more interesting interface.

>>> addrs = netifaces.ifaddresses('en0')
>>> addrs[netifaces.AF_INET]
[{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]

This interface has two addresses (see, I told you...)  Both of them are
regular IPv4 addresses, although in one case the netmask has been changed
from its default.  The netmask *may not* appear on your system if it's set
to the default for the address range.

Because this interface isn't point-to-point, it also has broadcast addresses.

Now, say we want, instead of the IP addresses, to get the MAC address; that
is, the hardware address of the Ethernet adapter running this interface.  We
can do

>>> addrs[netifaces.AF_LINK]
[{'addr': '00:12:34:56:78:9a'}]

Note that this may not be available on platforms without getifaddrs(), unless
they happen to implement ``SIOCGIFHWADDR``.  Note also that you just get the
address; it's unlikely that you'll see anything else with an ``AF_LINK`` address.
Oh, and don't assume that all ``AF_LINK`` addresses are Ethernet; you might, for
instance, be on a Mac, in which case:

>>> addrs = netifaces.ifaddresses('fw0')
>>> addrs[netifaces.AF_LINK]
[{'addr': '00:12:34:56:78:9a:bc:de'}]

No, that isn't an exceptionally long Ethernet MAC address---it's a FireWire
address.

As of version 0.10.0, you can also obtain a list of gateways on your
machine:

>>> netifaces.gateways()
{2: [('10.0.1.1', 'en0', True), ('10.2.1.1', 'en1', False)], 30: [('fe80::1', 'en0', True)], 'default': { 2: ('10.0.1.1', 'en0'), 30: ('fe80::1', 'en0') }}

This dictionary is keyed on address family---in this case, ``AF_INET``---and
each entry is a list of gateways as ``(address, interface, is_default)`` tuples.
Notice that here we have two separate gateways for IPv4 (``AF_INET``); some
operating systems support configurations like this and can either route packets
based on their source, or based on administratively configured routing tables.

For convenience, we also allow you to index the dictionary with the special
value ``'default'``, which returns a dictionary mapping address families to the
default gateway in each case.  Thus you can get the default IPv4 gateway with

>>> gws = netifaces.gateways()
>>> gws['default'][netifaces.AF_INET]
('10.0.1.1', 'en0')

Do note that there may be no default gateway for any given address family;
this is currently very common for IPv6 and much less common for IPv4 but it
can happen even for ``AF_INET``.

BTW, if you're trying to configure your machine to have multiple gateways for
the same address family, it's a very good idea to check the documentation for
your operating system *very* carefully, as some systems become extremely
confused or route packets in a non-obvious manner.

I'm very interested in hearing from anyone (on any platform) for whom the
``gateways()`` method doesn't produce the expected results.  It's quite
complicated extracting this information from the operating system (whichever
operating system we're talking about), and so I expect there's at least one
system out there where this just won't work.

3. This is great!  What platforms does it work on?
--------------------------------------------------

It gets regular testing on OS X, Linux and Windows.  It has also been used
successfully on Solaris, and it's expected to work properly on other UNIX-like
systems as well.  If you are running something that is not supported, and
wish to contribute a patch, please use Github to send a pull request.

4. What license is this under?
------------------------------

It's an MIT-style license. See `LICENSE <./LICENSE>`_.

5. Why the jump to 0.10.0?
--------------------------

Because someone released a fork of netifaces with the version 0.9.0.
Hopefully skipping the version number should remove any confusion.  In
addition starting with 0.10.0 Python 3 is now supported and other
features/bugfixes have been included as well.  See the CHANGELOG for a
more complete list of changes.


PKok\$netifaces-0.11.0.dist-info/REQUESTEDnu�[���PKok\�.�

(netifaces-0.11.0.dist-info/top_level.txtnu�[���netifaces
PKok\��2#netifaces-0.11.0.dist-info/zip-safenu�[���
PKok\���$netifaces-0.11.0.dist-info/INSTALLERnu�[���pip
PKok\�94��psutil-6.1.0.dist-info/WHEELnu�[���Wheel-Version: 1.0
Generator: bdist_wheel (0.37.1)
Root-Is-Purelib: false
Tag: cp36-abi3-manylinux_2_12_x86_64
Tag: cp36-abi3-manylinux2010_x86_64
Tag: cp36-abi3-manylinux_2_17_x86_64
Tag: cp36-abi3-manylinux2014_x86_64

PKok\٘q�psutil-6.1.0.dist-info/LICENSEnu�[���BSD 3-Clause License

Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither the name of the psutil authors nor the names of its contributors
   may be used to endorse or promote products derived from this software without
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PKok\W����psutil-6.1.0.dist-info/RECORDnu�[���psutil-6.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
psutil-6.1.0.dist-info/LICENSE,sha256=uJwGOzeG4o4MCjjxkx22H-015p3SopZvvs_-4PRsjRA,1548
psutil-6.1.0.dist-info/METADATA,sha256=9ro1bKVP9BN1l8ocnFXMpsbM_WcqDJdsw3BxHQomUug,22295
psutil-6.1.0.dist-info/RECORD,,
psutil-6.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
psutil-6.1.0.dist-info/WHEEL,sha256=rgpVBmjjvbINeGKCkWEGd3f40VHMTsDkQj1Lgil82zE,221
psutil-6.1.0.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7
psutil/__init__.py,sha256=zyBpkEYkWwlvVnnElydLzmm8umVweXlT4HsBzcTBA9c,89154
psutil/__pycache__/__init__.cpython-39.pyc,,
psutil/__pycache__/_common.cpython-39.pyc,,
psutil/__pycache__/_compat.cpython-39.pyc,,
psutil/__pycache__/_psaix.cpython-39.pyc,,
psutil/__pycache__/_psbsd.cpython-39.pyc,,
psutil/__pycache__/_pslinux.cpython-39.pyc,,
psutil/__pycache__/_psosx.cpython-39.pyc,,
psutil/__pycache__/_psposix.cpython-39.pyc,,
psutil/__pycache__/_pssunos.cpython-39.pyc,,
psutil/__pycache__/_pswindows.cpython-39.pyc,,
psutil/_common.py,sha256=KetpFrG7dgXOVqfG9O1XYPlLrGYPnCHUix5i-Kh213s,29739
psutil/_compat.py,sha256=zrxveFAR5_XqDUStcyXmTBk1rWs0jxLIiOjQnj7SwUk,15253
psutil/_psaix.py,sha256=auBiK5gCD4fOjqrjTwckg7wfOHw6vv3f0hIkGvNcBC4,18663
psutil/_psbsd.py,sha256=Yn4F-8jXZdbJ01R5xWfUESXUuhWUKiPa3JL1MiLA7-E,32205
psutil/_pslinux.py,sha256=PNh1dKVJ9rTXWLHAmeOoc00oI-SQ6QeZx0Lnxeh0JnA,88594
psutil/_psosx.py,sha256=js281YWrza5x0_EeYhjLLypDqzmiehZASGpUkxNhKqw,16136
psutil/_psposix.py,sha256=X9rd7WHKQ6mUAn2ihb03MCnzrBtQsrPRkCouExmuagQ,8235
psutil/_pssunos.py,sha256=Jxefif4mydfeOGKsyN7H7L5QVE4QhlhI8YXOX1HVAKI,25479
psutil/_psutil_linux.abi3.so,sha256=UVS0vmhO15bhmHJ-yUC4brnVLWENGD1dChvfRIv1fzI,115320
psutil/_psutil_posix.abi3.so,sha256=bLoKDfoWp8Pmo_QGNDssv7kIOLk2hnF6HZHYlRWatOI,71640
psutil/_pswindows.py,sha256=EPkkDJi0FZUzpkQWfAjk-oK2kvBI8RAhcPEFh3unLFA,38124
psutil/tests/__init__.py,sha256=2A3mFjGilu2GXXJBJaz2KLMime37ulCtgYWzjvrQLag,66696
psutil/tests/__main__.py,sha256=GYT-hlMnWDtybkJ76DqQcjXPr0jnLeZDTe0lVVeDb7o,309
psutil/tests/__pycache__/__init__.cpython-39.pyc,,
psutil/tests/__pycache__/__main__.cpython-39.pyc,,
psutil/tests/__pycache__/test_aix.cpython-39.pyc,,
psutil/tests/__pycache__/test_bsd.cpython-39.pyc,,
psutil/tests/__pycache__/test_connections.cpython-39.pyc,,
psutil/tests/__pycache__/test_contracts.cpython-39.pyc,,
psutil/tests/__pycache__/test_linux.cpython-39.pyc,,
psutil/tests/__pycache__/test_memleaks.cpython-39.pyc,,
psutil/tests/__pycache__/test_misc.cpython-39.pyc,,
psutil/tests/__pycache__/test_osx.cpython-39.pyc,,
psutil/tests/__pycache__/test_posix.cpython-39.pyc,,
psutil/tests/__pycache__/test_process.cpython-39.pyc,,
psutil/tests/__pycache__/test_process_all.cpython-39.pyc,,
psutil/tests/__pycache__/test_sunos.cpython-39.pyc,,
psutil/tests/__pycache__/test_system.cpython-39.pyc,,
psutil/tests/__pycache__/test_testutils.cpython-39.pyc,,
psutil/tests/__pycache__/test_unicode.cpython-39.pyc,,
psutil/tests/__pycache__/test_windows.cpython-39.pyc,,
psutil/tests/test_aix.py,sha256=x-klXNziKeLIj4eF4kPh-mObIlnuoAJWCA9y96JAXoQ,4035
psutil/tests/test_bsd.py,sha256=94Y34BUn0sBw-87NF0IIeU_NanOEwWDImRhkptQ4VYM,20222
psutil/tests/test_connections.py,sha256=gRqGAkbIjidumXVHVzlfZ0yUINAj9sbDeIbAwiGS6K0,21252
psutil/tests/test_contracts.py,sha256=FSFZpNeJumY9Lgerih3079pg4F80TwR7ftNS5nhFhqg,12577
psutil/tests/test_linux.py,sha256=Hng2l3UMYliIOdc3pF0kiWH6FJ0yGdB_WC-jPAPkbDE,91227
psutil/tests/test_memleaks.py,sha256=q6mV6Mtl_GH6HjQs33hrwaX78oSHZ9oojPyDTYLSBRQ,15411
psutil/tests/test_misc.py,sha256=goOFBTKBYJin5INIRttCEbKWOd64l_XenKK689w8zEY,35975
psutil/tests/test_osx.py,sha256=HeEXXZP3wsWdGZKu870nRtw5ndprn3zuqtvr-o9RpRg,6133
psutil/tests/test_posix.py,sha256=O6zAJEES8CrdSg8s3FWiRTv0xmf3B5_D88XAkxiJXYQ,17408
psutil/tests/test_process.py,sha256=tEirr5yZZbfhMtBZ2Ny5w3Xc1zU0L4DXo4eYTuG08go,63086
psutil/tests/test_process_all.py,sha256=SSbBcdjN51FxV9D_ZDsfULWY1xuV0wAlXVo2-8cw_5M,18616
psutil/tests/test_sunos.py,sha256=tf9OOQyidTFA4WAp2eZoewvwXy95MmTD06JURgnH7ig,1192
psutil/tests/test_system.py,sha256=SogWUMyMK_manymW0Jz_atWDLKNbGVl_krMlwP6eu_k,36431
psutil/tests/test_testutils.py,sha256=MQprQYqROcMc_-5e0GT37uukCgmYGhLQfYTx82nqiYg,18585
psutil/tests/test_unicode.py,sha256=OyGLTxCU8WsSGiNYkvZkWtAzl6lZVBt-yixxSyuqXAk,12603
psutil/tests/test_windows.py,sha256=O3Tt5nCaamkdzEcTSjoopp2NoN6tkWQ6Y66GZwSKEqg,34008
PKok\t�c�WWpsutil-6.1.0.dist-info/METADATAnu�[���Metadata-Version: 2.1
Name: psutil
Version: 6.1.0
Summary: Cross-platform lib for process and system monitoring in Python.
Home-page: https://github.com/giampaolo/psutil
Author: Giampaolo Rodola
Author-email: g.rodola@gmail.com
License: BSD-3-Clause
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability
Platform: Platform Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: Microsoft :: Windows :: Windows 7
Classifier: Operating System :: Microsoft :: Windows :: Windows 8
Classifier: Operating System :: Microsoft :: Windows :: Windows 8.1
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2003
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2008
Classifier: Operating System :: Microsoft :: Windows :: Windows Vista
Classifier: Operating System :: Microsoft
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: AIX
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
Classifier: Operating System :: POSIX :: BSD :: NetBSD
Classifier: Operating System :: POSIX :: BSD :: OpenBSD
Classifier: Operating System :: POSIX :: BSD
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: SunOS/Solaris
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Benchmark
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: Topic :: System :: Hardware
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring :: Hardware Watchdog
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Operating System
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*
Description-Content-Type: text/x-rst
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: black ; extra == 'dev'
Requires-Dist: check-manifest ; extra == 'dev'
Requires-Dist: coverage ; extra == 'dev'
Requires-Dist: packaging ; extra == 'dev'
Requires-Dist: pylint ; extra == 'dev'
Requires-Dist: pyperf ; extra == 'dev'
Requires-Dist: pypinfo ; extra == 'dev'
Requires-Dist: pytest-cov ; extra == 'dev'
Requires-Dist: requests ; extra == 'dev'
Requires-Dist: rstcheck ; extra == 'dev'
Requires-Dist: ruff ; extra == 'dev'
Requires-Dist: sphinx ; extra == 'dev'
Requires-Dist: sphinx-rtd-theme ; extra == 'dev'
Requires-Dist: toml-sort ; extra == 'dev'
Requires-Dist: twine ; extra == 'dev'
Requires-Dist: virtualenv ; extra == 'dev'
Requires-Dist: wheel ; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest ; extra == 'test'
Requires-Dist: pytest-xdist ; extra == 'test'
Requires-Dist: setuptools ; extra == 'test'

|  |downloads| |stars| |forks| |contributors| |coverage|
|  |version| |py-versions| |packages| |license|
|  |github-actions-wheels|  |github-actions-bsd| |appveyor| |doc| |twitter| |tidelift|

.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg
    :target: https://pepy.tech/project/psutil
    :alt: Downloads

.. |stars| image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
    :target: https://github.com/giampaolo/psutil/stargazers
    :alt: Github stars

.. |forks| image:: https://img.shields.io/github/forks/giampaolo/psutil.svg
    :target: https://github.com/giampaolo/psutil/network/members
    :alt: Github forks

.. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/psutil.svg
    :target: https://github.com/giampaolo/psutil/graphs/contributors
    :alt: Contributors

.. |github-actions-wheels| image:: https://img.shields.io/github/actions/workflow/status/giampaolo/psutil/.github/workflows/build.yml.svg?label=Linux%2C%20macOS%2C%20Windows
    :target: https://github.com/giampaolo/psutil/actions?query=workflow%3Abuild
    :alt: Linux, macOS, Windows

.. |github-actions-bsd| image:: https://img.shields.io/github/actions/workflow/status/giampaolo/psutil/.github/workflows/bsd.yml.svg?label=FreeBSD,%20NetBSD,%20OpenBSD
    :target: https://github.com/giampaolo/psutil/actions?query=workflow%3Absd-tests
    :alt: FreeBSD, NetBSD, OpenBSD

.. |appveyor| image:: https://img.shields.io/appveyor/build/giampaolo/psutil/master.svg?maxAge=3600&label=Windows%20(py2)
    :target: https://ci.appveyor.com/project/giampaolo/psutil
    :alt: Windows (Appveyor)

.. |coverage| image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master
    :target: https://coveralls.io/github/giampaolo/psutil?branch=master
    :alt: Test coverage (coverall.io)

.. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest
    :target: https://psutil.readthedocs.io/en/latest/
    :alt: Documentation Status

.. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
    :target: https://pypi.org/project/psutil
    :alt: Latest version

.. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg
    :alt: Supported Python versions

.. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg
    :target: https://repology.org/metapackage/python:psutil/versions
    :alt: Binary packages

.. |license| image:: https://img.shields.io/pypi/l/psutil.svg
    :target: https://github.com/giampaolo/psutil/blob/master/LICENSE
    :alt: License

.. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow&style=flat&logo=twitter&logoColor=4FADFF
    :target: https://twitter.com/grodola
    :alt: Twitter Follow

.. |tidelift| image:: https://tidelift.com/badges/github/giampaolo/psutil?style=flat
    :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
    :alt: Tidelift

-----

Quick links
===========

- `Home page <https://github.com/giampaolo/psutil>`_
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `Documentation <http://psutil.readthedocs.io>`_
- `Download <https://pypi.org/project/psutil/#files>`_
- `Forum <http://groups.google.com/group/psutil/topics>`_
- `StackOverflow <https://stackoverflow.com/questions/tagged/psutil>`_
- `Blog <https://gmpy.dev/tags/psutil>`_
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_


Summary
=======

psutil (process and system utilities) is a cross-platform library for
retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network, sensors) in Python.
It is useful mainly for **system monitoring**, **profiling and limiting process
resources** and **management of running processes**.
It implements many functionalities offered by classic UNIX command line tools
such as *ps, top, iotop, lsof, netstat, ifconfig, free* and others.
psutil currently supports the following platforms:

- **Linux**
- **Windows**
- **macOS**
- **FreeBSD, OpenBSD**, **NetBSD**
- **Sun Solaris**
- **AIX**

Supported Python versions are **2.7**, **3.6+** and
`PyPy <http://pypy.org/>`__.

Funding
=======

While psutil is free software and will always be, the project would benefit
immensely from some funding.
Keeping up with bug reports and maintenance has become hardly sustainable for
me alone in terms of time.
If you're a company that's making significant use of psutil you can consider
becoming a sponsor via `GitHub Sponsors <https://github.com/sponsors/giampaolo>`__,
`Open Collective <https://opencollective.com/psutil>`__ or
`PayPal <https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8>`__
and have your logo displayed in here and psutil `doc <https://psutil.readthedocs.io>`__.

Sponsors
========

.. image:: https://github.com/giampaolo/psutil/raw/master/docs/_static/tidelift-logo.png
  :width: 200
  :alt: Alternative text

`Add your logo <https://github.com/sponsors/giampaolo>`__.

Example usages
==============

This represents pretty much the whole psutil API.

CPU
---

.. code-block:: python

    >>> import psutil
    >>>
    >>> psutil.cpu_times()
    scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, guest_nice=0.0)
    >>>
    >>> for x in range(3):
    ...     psutil.cpu_percent(interval=1)
    ...
    4.0
    5.9
    3.8
    >>>
    >>> for x in range(3):
    ...     psutil.cpu_percent(interval=1, percpu=True)
    ...
    [4.0, 6.9, 3.7, 9.2]
    [7.0, 8.5, 2.4, 2.1]
    [1.2, 9.0, 9.9, 7.2]
    >>>
    >>> for x in range(3):
    ...     psutil.cpu_times_percent(interval=1, percpu=False)
    ...
    scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
    scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
    scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
    >>>
    >>> psutil.cpu_count()
    4
    >>> psutil.cpu_count(logical=False)
    2
    >>>
    >>> psutil.cpu_stats()
    scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
    >>>
    >>> psutil.cpu_freq()
    scpufreq(current=931.42925, min=800.0, max=3500.0)
    >>>
    >>> psutil.getloadavg()  # also on Windows (emulated)
    (3.14, 3.89, 4.67)

Memory
------

.. code-block:: python

    >>> psutil.virtual_memory()
    svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
    >>> psutil.swap_memory()
    sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
    >>>

Disks
-----

.. code-block:: python

    >>> psutil.disk_partitions()
    [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
     sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext', opts='rw')]
    >>>
    >>> psutil.disk_usage('/')
    sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
    >>>
    >>> psutil.disk_io_counters(perdisk=False)
    sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
    >>>

Network
-------

.. code-block:: python

    >>> psutil.net_io_counters(pernic=True)
    {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
     'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
    >>>
    >>> psutil.net_connections(kind='tcp')
    [sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
     sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
     ...]
    >>>
    >>> psutil.net_if_addrs()
    {'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
            snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
            snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
     'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
               snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
               snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
    >>>
    >>> psutil.net_if_stats()
    {'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536, flags='up,loopback,running'),
     'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500, flags='up,broadcast,running,multicast')}
    >>>

Sensors
-------

.. code-block:: python

    >>> import psutil
    >>> psutil.sensors_temperatures()
    {'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
     'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
     'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
                  shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]}
    >>>
    >>> psutil.sensors_fans()
    {'asus': [sfan(label='cpu_fan', current=3200)]}
    >>>
    >>> psutil.sensors_battery()
    sbattery(percent=93, secsleft=16628, power_plugged=False)
    >>>

Other system info
-----------------

.. code-block:: python

    >>> import psutil
    >>> psutil.users()
    [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
     suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
    >>>
    >>> psutil.boot_time()
    1365519115.0
    >>>

Process management
------------------

.. code-block:: python

    >>> import psutil
    >>> psutil.pids()
    [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215,
     1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355, 2637, 2774, 3932,
     4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282, 4306, 4311,
     4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433,
     4443, 4445, 4446, 5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054,
     7055, 7071]
    >>>
    >>> p = psutil.Process(7055)
    >>> p
    psutil.Process(pid=7055, name='python3', status='running', started='09:04:44')
    >>> p.pid
    7055
    >>> p.name()
    'python3'
    >>> p.exe()
    '/usr/bin/python3'
    >>> p.cwd()
    '/home/giampaolo'
    >>> p.cmdline()
    ['/usr/bin/python3', 'main.py']
    >>>
    >>> p.ppid()
    7054
    >>> p.parent()
    psutil.Process(pid=4699, name='bash', status='sleeping', started='09:06:44')
    >>> p.parents()
    [psutil.Process(pid=4699, name='bash', started='09:06:44'),
     psutil.Process(pid=4689, name='gnome-terminal-server', status='sleeping', started='0:06:44'),
     psutil.Process(pid=1, name='systemd', status='sleeping', started='05:56:55')]
    >>> p.children(recursive=True)
    [psutil.Process(pid=29835, name='python3', status='sleeping', started='11:45:38'),
     psutil.Process(pid=29836, name='python3', status='waking', started='11:43:39')]
    >>>
    >>> p.status()
    'running'
    >>> p.create_time()
    1267551141.5019531
    >>> p.terminal()
    '/dev/pts/0'
    >>>
    >>> p.username()
    'giampaolo'
    >>> p.uids()
    puids(real=1000, effective=1000, saved=1000)
    >>> p.gids()
    pgids(real=1000, effective=1000, saved=1000)
    >>>
    >>> p.cpu_times()
    pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0)
    >>> p.cpu_percent(interval=1.0)
    12.1
    >>> p.cpu_affinity()
    [0, 1, 2, 3]
    >>> p.cpu_affinity([0, 1])  # set
    >>> p.cpu_num()
    1
    >>>
    >>> p.memory_info()
    pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
    >>> p.memory_full_info()  # "real" USS memory usage (Linux, macOS, Win only)
    pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
    >>> p.memory_percent()
    0.7823
    >>> p.memory_maps()
    [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
     pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
     pmmap_grouped(path='[heap]',  rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
     pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
     ...]
    >>>
    >>> p.io_counters()
    pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
    >>>
    >>> p.open_files()
    [popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768),
     popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)]
    >>>
    >>> p.net_connections(kind='tcp')
    [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
     pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')]
    >>>
    >>> p.threads()
    [pthread(id=5234, user_time=22.5, system_time=9.2891),
     pthread(id=5237, user_time=0.0707, system_time=1.1)]
    >>>
    >>> p.num_threads()
    4
    >>> p.num_fds()
    8
    >>> p.num_ctx_switches()
    pctxsw(voluntary=78, involuntary=19)
    >>>
    >>> p.nice()
    0
    >>> p.nice(10)  # set
    >>>
    >>> p.ionice(psutil.IOPRIO_CLASS_IDLE)  # IO priority (Win and Linux only)
    >>> p.ionice()
    pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
    >>>
    >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5))  # set resource limits (Linux only)
    >>> p.rlimit(psutil.RLIMIT_NOFILE)
    (5, 5)
    >>>
    >>> p.environ()
    {'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
    'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg',
     ...}
    >>>
    >>> p.as_dict()
    {'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
    >>> p.is_running()
    True
    >>> p.suspend()
    >>> p.resume()
    >>>
    >>> p.terminate()
    >>> p.kill()
    >>> p.wait(timeout=3)
    <Exitcode.EX_OK: 0>
    >>>
    >>> psutil.test()
    USER         PID %CPU %MEM     VSZ     RSS TTY        START    TIME  COMMAND
    root           1  0.0  0.0   24584    2240            Jun17   00:00  init
    root           2  0.0  0.0       0       0            Jun17   00:00  kthreadd
    ...
    giampaolo  31475  0.0  0.0   20760    3024 /dev/pts/0 Jun19   00:00  python2.4
    giampaolo  31721  0.0  2.2  773060  181896            00:04   10:30  chrome
    root       31763  0.0  0.0       0       0            00:05   00:00  kworker/0:1
    >>>

Further process APIs
--------------------

.. code-block:: python

    >>> import psutil
    >>> for proc in psutil.process_iter(['pid', 'name']):
    ...     print(proc.info)
    ...
    {'pid': 1, 'name': 'systemd'}
    {'pid': 2, 'name': 'kthreadd'}
    {'pid': 3, 'name': 'ksoftirqd/0'}
    ...
    >>>
    >>> psutil.pid_exists(3)
    True
    >>>
    >>> def on_terminate(proc):
    ...     print("process {} terminated".format(proc))
    ...
    >>> # waits for multiple processes to terminate
    >>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
    >>>

Windows services
----------------

.. code-block:: python

    >>> list(psutil.win_service_iter())
    [<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
     <WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
     <WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
     <WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
     ...]
    >>> s = psutil.win_service_get('alg')
    >>> s.as_dict()
    {'binpath': 'C:\\Windows\\System32\\alg.exe',
     'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
     'display_name': 'Application Layer Gateway Service',
     'name': 'alg',
     'pid': None,
     'start_type': 'manual',
     'status': 'stopped',
     'username': 'NT AUTHORITY\\LocalService'}

Projects using psutil
=====================

Here's some I find particularly interesting:

- https://github.com/google/grr
- https://github.com/facebook/osquery/
- https://github.com/nicolargo/glances
- https://github.com/aristocratos/bpytop
- https://github.com/Jahaja/psdash
- https://github.com/ajenti/ajenti
- https://github.com/home-assistant/home-assistant/

Portings
========

- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Rust: https://github.com/rust-psutil/rust-psutil
- Nim: https://github.com/johnscillieri/psutil-nim



PKok\ psutil-6.1.0.dist-info/REQUESTEDnu�[���PKok\TFG$psutil-6.1.0.dist-info/top_level.txtnu�[���psutil
PKok\��� psutil-6.1.0.dist-info/INSTALLERnu�[���pip
PKok\%M�mm(netifaces.cpython-39-x86_64-linux-gnu.sonuȯ��PKok\�Ï�;�;�psutil/_compat.pynu�[���PKok\͔�������Bpsutil/tests/test_misc.pynu�[���PKok\X���N�Nk�psutil/tests/test_bsd.pynu�[���PKok\�;�3<3<�psutil/tests/test_memleaks.pynu�[���PKok\���H!1!11[psutil/tests/test_contracts.pynu�[���PKok\��c�H�H ��psutil/tests/test_process_all.pynu�[���PKok\Z������psutil/tests/__init__.pynu�[���PKok\V�a�SS x�psutil/tests/test_connections.pynu�[���PKok\�TZn�n��-psutil/tests/test_process.pynu�[���PKok\���O�O��$psutil/tests/test_system.pynu�[���PKok\3�
�� �psutil/tests/test_osx.pynu�[���PKok\
�u55]�psutil/tests/__main__.pynu�[���PKok\��k��0��psutil/tests/__pycache__/test_aix.cpython-39.pycnu�[���PKok\�*ejXjX6'�psutil/tests/__pycache__/test_testutils.cpython-39.pycnu�[���PKok\���Sh�h�0�1psutil/tests/__pycache__/__init__.cpython-39.pycnu�[���PKok\�����\�\5�
psutil/tests/__pycache__/test_memleaks.cpython-39.pycnu�[���PKok\�đ�&>&>8�jpsutil/tests/__pycache__/test_connections.cpython-39.pycnu�[���PKok\����7�72g�psutil/tests/__pycache__/test_posix.cpython-39.pycnu�[���PKok\v�b�?�?8��psutil/tests/__pycache__/test_process_all.cpython-39.pycnu�[���PKok\+��N�N0
"psutil/tests/__pycache__/test_bsd.cpython-39.pycnu�[���PKok\{��
y
y4+qpsutil/tests/__pycache__/test_windows.cpython-39.pycnu�[���PKok\�n�E0��psutil/tests/__pycache__/test_osx.cpython-39.pycnu�[���PKok\�J�>C)C)2		psutil/tests/__pycache__/test_linux.cpython-39.pycnu�[���PKok\ r.�}�}�4�.
psutil/tests/__pycache__/test_process.cpython-39.pycnu�[���PKok\��yZ556��
psutil/tests/__pycache__/test_contracts.cpython-39.pycnu�[���PKok\R4�(||10psutil/tests/__pycache__/test_misc.cpython-39.pycnu�[���PKok\�6�r�r3��psutil/tests/__pycache__/test_system.cpython-39.pycnu�[���PKok\}��}}2�psutil/tests/__pycache__/test_sunos.cpython-39.pycnu�[���PKok\豍BB0�%psutil/tests/__pycache__/__main__.cpython-39.pycnu�[���PKok\ށ�,,4f'psutil/tests/__pycache__/test_unicode.cpython-39.pycnu�[���PKok\7؄؄�Spsutil/tests/test_windows.pynu�[���PKok\�P�
�H�H��psutil/tests/test_testutils.pynu�[���PKok\�c�;1;1�!
psutil/tests/test_unicode.pynu�[���PKok\�μ[d[d^S
psutil/tests/test_linux.pynu�[���PKok\�u����psutil/tests/test_sunos.pynu�[���PKok\0��DD��psutil/tests/test_posix.pynu�[���PKok\�����?psutil/tests/test_aix.pynu�[���PKok\�$�B\B\Jpsutil/__init__.pynu�[���PKok\0T;+ + �mpsutil/_psposix.pynu�[���PKok\t�|�ZZ;�psutil/_pslinux.pynu�[���PKok\�#�!x�x���psutil/_psutil_linux.abi3.sonuȯ��PKok\��G��r�r,S�psutil/__pycache__/_pswindows.cpython-39.pycnu�[���PKok\�U��*�psutil/__pycache__/__init__.cpython-39.pycnu�[���PKok\E��55(psutil/__pycache__/_psosx.cpython-39.pycnu�[���PKok\�DB�g[g[)�Spsutil/__pycache__/_common.cpython-39.pycnu�[���PKok\]2�مG�G*C�psutil/__pycache__/_pssunos.cpython-39.pycnu�[���PKok\1}:p�;�;("�psutil/__pycache__/_psaix.cpython-39.pycnu�[���PKok\+�������*3psutil/__pycache__/_pslinux.cpython-39.pycnu�[���PKok\�Dˤ��*apsutil/__pycache__/_psposix.cpython-39.pycnu�[���PKok\q�-��-�-)�psutil/__pycache__/_compat.cpython-39.pycnu�[���PKok\<�RR(�Epsutil/__pycache__/_psbsd.cpython-39.pycnu�[���PKok\s�L+t+t�psutil/_common.pynu�[���PKok\�*Ǘ�H�H�psutil/_psaix.pynu�[���PKok\,��S??�Upsutil/_psosx.pynu�[���PKok\݄����psutil/_psutil_posix.abi3.sonuȯ��PKok\ػ�هc�c�psutil/_pssunos.pynu�[���PKok\;�`�}�}�psutil/_psbsd.pynu�[���PKok\w�]����psutil/_pswindows.pynu�[���PKok\�ɞ1�� $netifaces-0.11.0.dist-info/WHEELnu�[���PKok\���**"�$netifaces-0.11.0.dist-info/LICENSEnu�[���PKok\�zb�

!{)netifaces-0.11.0.dist-info/RECORDnu�[���PKok\t��/�"�"#�,netifaces-0.11.0.dist-info/METADATAnu�[���PKok\$ Pnetifaces-0.11.0.dist-info/REQUESTEDnu�[���PKok\�.�

(tPnetifaces-0.11.0.dist-info/top_level.txtnu�[���PKok\��2#�Pnetifaces-0.11.0.dist-info/zip-safenu�[���PKok\���$*Qnetifaces-0.11.0.dist-info/INSTALLERnu�[���PKok\�94���Qpsutil-6.1.0.dist-info/WHEELnu�[���PKok\٘q��Rpsutil-6.1.0.dist-info/LICENSEnu�[���PKok\W����Ypsutil-6.1.0.dist-info/RECORDnu�[���PKok\t�c�WW�jpsutil-6.1.0.dist-info/METADATAnu�[���PKok\ @�psutil-6.1.0.dist-info/REQUESTEDnu�[���PKok\TFG$��psutil-6.1.0.dist-info/top_level.txtnu�[���PKok\��� ��psutil-6.1.0.dist-info/INSTALLERnu�[���PKJJ�?�