py2docfx 0.1.20rc2196756__py3-none-any.whl → 0.1.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. py2docfx/convert_prepare/get_source.py +1 -1
  2. py2docfx/convert_prepare/package_info.py +37 -27
  3. py2docfx/convert_prepare/tests/test_get_source.py +3 -1
  4. py2docfx/convert_prepare/tests/test_package_info.py +159 -1
  5. py2docfx/docfx_yaml/build_finished.py +1 -1
  6. py2docfx/docfx_yaml/logger.py +42 -28
  7. py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/api.py +3 -2
  8. py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/legacy.py +17 -1
  9. py2docfx/venv/basevenv/Lib/site-packages/charset_normalizer/version.py +1 -1
  10. py2docfx/venv/basevenv/Lib/site-packages/requests/__version__.py +2 -2
  11. py2docfx/venv/basevenv/Lib/site-packages/requests/adapters.py +17 -40
  12. py2docfx/venv/basevenv/Lib/site-packages/requests/sessions.py +1 -1
  13. py2docfx/venv/venv1/Lib/site-packages/azure/core/_version.py +1 -1
  14. py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication.py +21 -9
  15. py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_authentication_async.py +21 -9
  16. py2docfx/venv/venv1/Lib/site-packages/azure/core/pipeline/policies/_retry.py +1 -1
  17. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_bearer_token_provider.py +1 -1
  18. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/authorization_code.py +1 -1
  19. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azd_cli.py +82 -17
  20. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_cli.py +28 -5
  21. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_powershell.py +28 -4
  22. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/broker.py +79 -0
  23. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/chained.py +9 -3
  24. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/default.py +153 -53
  25. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/imds.py +25 -1
  26. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/shared_cache.py +12 -5
  27. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/vscode.py +163 -144
  28. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/workload_identity.py +23 -12
  29. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/__init__.py +4 -0
  30. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/interactive.py +14 -2
  31. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/pipeline.py +4 -2
  32. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/utils.py +96 -0
  33. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_version.py +1 -1
  34. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_bearer_token_provider.py +3 -3
  35. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/authorization_code.py +1 -1
  36. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azd_cli.py +32 -13
  37. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_cli.py +26 -5
  38. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_powershell.py +13 -2
  39. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/chained.py +1 -1
  40. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/default.py +120 -55
  41. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/imds.py +27 -1
  42. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/on_behalf_of.py +1 -1
  43. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/shared_cache.py +12 -5
  44. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/vscode.py +15 -67
  45. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/workload_identity.py +17 -13
  46. py2docfx/venv/venv1/Lib/site-packages/cffi/__init__.py +2 -2
  47. py2docfx/venv/venv1/Lib/site-packages/cffi/cparser.py +1 -1
  48. py2docfx/venv/venv1/Lib/site-packages/cffi/recompiler.py +5 -5
  49. py2docfx/venv/venv1/Lib/site-packages/cffi/setuptools_ext.py +13 -0
  50. py2docfx/venv/venv1/Lib/site-packages/cffi/vengine_cpy.py +3 -0
  51. py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/api.py +3 -2
  52. py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/legacy.py +17 -1
  53. py2docfx/venv/venv1/Lib/site-packages/charset_normalizer/version.py +1 -1
  54. py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
  55. py2docfx/venv/venv1/Lib/site-packages/cryptography/__init__.py +0 -13
  56. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/_oid.py +8 -0
  57. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/__init__.py +10 -0
  58. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/asn1/asn1.py +116 -0
  59. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py +3 -9
  60. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi +32 -0
  61. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi +23 -0
  62. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi +1 -13
  63. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py +16 -0
  64. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py +16 -1
  65. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py +0 -2
  66. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +8 -0
  67. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +0 -47
  68. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py +6 -91
  69. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py +1 -3
  70. py2docfx/venv/venv1/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py +1 -1
  71. py2docfx/venv/venv1/Lib/site-packages/cryptography/utils.py +0 -2
  72. py2docfx/venv/venv1/Lib/site-packages/cryptography/x509/name.py +2 -3
  73. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/__init__.py +1 -1
  74. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any_pb2.py +2 -2
  75. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/api_pb2.py +12 -8
  76. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py +2 -2
  77. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor.py +398 -246
  78. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pb2.py +74 -72
  79. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pool.py +5 -4
  80. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration_pb2.py +2 -2
  81. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/empty_pb2.py +2 -2
  82. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/field_mask_pb2.py +2 -2
  83. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/api_implementation.py +0 -6
  84. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/extension_dict.py +3 -3
  85. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/field_mask.py +3 -3
  86. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_edition_defaults.py +1 -1
  87. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/python_message.py +10 -2
  88. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/internal/type_checkers.py +47 -5
  89. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/json_format.py +55 -32
  90. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/runtime_version.py +6 -26
  91. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/source_context_pb2.py +2 -2
  92. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/struct_pb2.py +2 -2
  93. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/text_format.py +30 -19
  94. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp_pb2.py +2 -2
  95. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/type_pb2.py +2 -2
  96. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/wrappers_pb2.py +2 -2
  97. py2docfx/venv/venv1/Lib/site-packages/psutil/__init__.py +39 -19
  98. py2docfx/venv/venv1/Lib/site-packages/psutil/_common.py +3 -5
  99. py2docfx/venv/venv1/Lib/site-packages/psutil/_psaix.py +1 -2
  100. py2docfx/venv/venv1/Lib/site-packages/psutil/_psbsd.py +53 -78
  101. py2docfx/venv/venv1/Lib/site-packages/psutil/_pslinux.py +55 -38
  102. py2docfx/venv/venv1/Lib/site-packages/psutil/_psosx.py +40 -12
  103. py2docfx/venv/venv1/Lib/site-packages/psutil/_psposix.py +0 -1
  104. py2docfx/venv/venv1/Lib/site-packages/psutil/_pssunos.py +1 -2
  105. py2docfx/venv/venv1/Lib/site-packages/psutil/_pswindows.py +33 -13
  106. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__init__.py +185 -122
  107. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__main__.py +2 -3
  108. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_bsd.py +5 -10
  109. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_connections.py +3 -4
  110. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_contracts.py +41 -45
  111. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_linux.py +35 -38
  112. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_memleaks.py +4 -8
  113. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_misc.py +6 -12
  114. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_osx.py +17 -8
  115. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_posix.py +29 -17
  116. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process.py +74 -75
  117. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process_all.py +11 -13
  118. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_scripts.py +2 -3
  119. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_sudo.py +117 -0
  120. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_system.py +21 -31
  121. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_testutils.py +23 -23
  122. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_unicode.py +15 -8
  123. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_windows.py +65 -33
  124. py2docfx/venv/venv1/Lib/site-packages/pycparser/__init__.py +1 -1
  125. py2docfx/venv/venv1/Lib/site-packages/pycparser/c_generator.py +1 -1
  126. py2docfx/venv/venv1/Lib/site-packages/pycparser/c_lexer.py +14 -0
  127. py2docfx/venv/venv1/Lib/site-packages/pycparser/c_parser.py +30 -7
  128. py2docfx/venv/venv1/Lib/site-packages/pycparser/lextab.py +1 -1
  129. py2docfx/venv/venv1/Lib/site-packages/pycparser/yacctab.py +132 -127
  130. py2docfx/venv/venv1/Lib/site-packages/requests/__version__.py +2 -2
  131. py2docfx/venv/venv1/Lib/site-packages/requests/adapters.py +17 -40
  132. py2docfx/venv/venv1/Lib/site-packages/requests/sessions.py +1 -1
  133. py2docfx/venv/venv1/Lib/site-packages/typing_extensions.py +91 -18
  134. {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/METADATA +1 -1
  135. {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/RECORD +137 -135
  136. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/linux_vscode_adapter.py +0 -100
  137. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/macos_vscode_adapter.py +0 -34
  138. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/win_vscode_adapter.py +0 -77
  139. {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/WHEEL +0 -0
  140. {py2docfx-0.1.20rc2196756.dist-info → py2docfx-0.1.21.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,6 @@ from ._common import memoize
16
16
  from ._common import sdiskusage
17
17
  from ._common import usage_percent
18
18
 
19
-
20
19
  if MACOS:
21
20
  from . import _psutil_osx
22
21
 
@@ -30,7 +30,6 @@ from ._common import sockfam_to_enum
30
30
  from ._common import socktype_to_enum
31
31
  from ._common import usage_percent
32
32
 
33
-
34
33
  __extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]
35
34
 
36
35
 
@@ -311,7 +310,7 @@ def boot_time():
311
310
  def users():
312
311
  """Return currently connected users as a list of namedtuples."""
313
312
  retlist = []
314
- rawlist = cext.users()
313
+ rawlist = cext_posix.users()
315
314
  localhost = (':0.0', ':0')
316
315
  for item in rawlist:
317
316
  user, tty, hostname, tstamp, user_process, pid = item
@@ -10,6 +10,7 @@ import functools
10
10
  import os
11
11
  import signal
12
12
  import sys
13
+ import threading
13
14
  import time
14
15
  from collections import namedtuple
15
16
 
@@ -33,7 +34,6 @@ from ._psutil_windows import IDLE_PRIORITY_CLASS
33
34
  from ._psutil_windows import NORMAL_PRIORITY_CLASS
34
35
  from ._psutil_windows import REALTIME_PRIORITY_CLASS
35
36
 
36
-
37
37
  try:
38
38
  from . import _psutil_windows as cext
39
39
  except ImportError as err:
@@ -184,12 +184,21 @@ pio = namedtuple('pio', ['read_count', 'write_count',
184
184
  @functools.lru_cache(maxsize=512)
185
185
  def convert_dos_path(s):
186
186
  r"""Convert paths using native DOS format like:
187
- "\Device\HarddiskVolume1\Windows\systemew\file.txt"
187
+ "\Device\HarddiskVolume1\Windows\systemew\file.txt" or
188
+ "\??\C:\Windows\systemew\file.txt"
188
189
  into:
189
190
  "C:\Windows\systemew\file.txt".
190
191
  """
192
+ if s.startswith('\\\\'):
193
+ return s
191
194
  rawdrive = '\\'.join(s.split('\\')[:3])
192
- driveletter = cext.QueryDosDevice(rawdrive)
195
+ if rawdrive in {"\\??\\UNC", "\\Device\\Mup"}:
196
+ rawdrive = '\\'.join(s.split('\\')[:5])
197
+ driveletter = '\\\\' + '\\'.join(s.split('\\')[3:5])
198
+ elif rawdrive.startswith('\\??\\'):
199
+ driveletter = s.split('\\')[2]
200
+ else:
201
+ driveletter = cext.QueryDosDevice(rawdrive)
193
202
  remainder = s[len(rawdrive) :]
194
203
  return os.path.join(driveletter, remainder)
195
204
 
@@ -322,22 +331,31 @@ def cpu_freq():
322
331
  return [_common.scpufreq(float(curr), min_, float(max_))]
323
332
 
324
333
 
325
- _loadavg_inititialized = False
334
+ _loadavg_initialized = False
335
+ _lock = threading.Lock()
336
+
337
+
338
+ def _getloadavg_impl():
339
+ # Drop to 2 decimal points which is what Linux does
340
+ raw_loads = cext.getloadavg()
341
+ return tuple(round(load, 2) for load in raw_loads)
326
342
 
327
343
 
328
344
  def getloadavg():
329
345
  """Return the number of processes in the system run queue averaged
330
346
  over the last 1, 5, and 15 minutes respectively as a tuple.
331
347
  """
332
- global _loadavg_inititialized
348
+ global _loadavg_initialized
333
349
 
334
- if not _loadavg_inititialized:
335
- cext.init_loadavg_counter()
336
- _loadavg_inititialized = True
350
+ if _loadavg_initialized:
351
+ return _getloadavg_impl()
337
352
 
338
- # Drop to 2 decimal points which is what Linux does
339
- raw_loads = cext.getloadavg()
340
- return tuple(round(load, 2) for load in raw_loads)
353
+ with _lock:
354
+ if not _loadavg_initialized:
355
+ cext.init_loadavg_counter()
356
+ _loadavg_initialized = True
357
+
358
+ return _getloadavg_impl()
341
359
 
342
360
 
343
361
  # =====================================================================
@@ -426,12 +444,14 @@ _last_btime = 0
426
444
 
427
445
 
428
446
  def boot_time():
429
- """The system boot time expressed in seconds since the epoch."""
447
+ """The system boot time expressed in seconds since the epoch. This
448
+ also includes the time spent during hybernate / suspend.
449
+ """
430
450
  # This dirty hack is to adjust the precision of the returned
431
451
  # value which may have a 1 second fluctuation, see:
432
452
  # https://github.com/giampaolo/psutil/issues/1007
433
453
  global _last_btime
434
- ret = float(cext.boot_time())
454
+ ret = time.time() - cext.uptime()
435
455
  if abs(ret - _last_btime) <= 1:
436
456
  return _last_btime
437
457
  else:
@@ -4,7 +4,6 @@
4
4
 
5
5
  """Test utilities."""
6
6
 
7
-
8
7
  import atexit
9
8
  import contextlib
10
9
  import ctypes
@@ -30,13 +29,13 @@ import tempfile
30
29
  import textwrap
31
30
  import threading
32
31
  import time
32
+ import traceback
33
33
  import unittest
34
34
  import warnings
35
35
  from socket import AF_INET
36
36
  from socket import AF_INET6
37
37
  from socket import SOCK_STREAM
38
38
 
39
-
40
39
  try:
41
40
  import pytest
42
41
  except ImportError:
@@ -57,7 +56,6 @@ from psutil._common import memoize
57
56
  from psutil._common import print_color
58
57
  from psutil._common import supports_ipv6
59
58
 
60
-
61
59
  if POSIX:
62
60
  from psutil._psposix import wait_pid
63
61
 
@@ -75,7 +73,7 @@ __all__ = [
75
73
  "HAS_SENSORS_TEMPERATURES", "HAS_NET_CONNECTIONS_UNIX", "MACOS_11PLUS",
76
74
  "MACOS_12PLUS", "COVERAGE", 'AARCH64', "PYTEST_PARALLEL",
77
75
  # subprocesses
78
- 'pyrun', 'terminate', 'reap_children', 'spawn_testproc', 'spawn_zombie',
76
+ 'pyrun', 'terminate', 'reap_children', 'spawn_subproc', 'spawn_zombie',
79
77
  'spawn_children_pair',
80
78
  # threads
81
79
  'ThreadTask',
@@ -116,7 +114,9 @@ COVERAGE = 'COVERAGE_RUN' in os.environ
116
114
  PYTEST_PARALLEL = "PYTEST_XDIST_WORKER" in os.environ # `make test-parallel`
117
115
  # are we a 64 bit process?
118
116
  IS_64BIT = sys.maxsize > 2**32
119
- AARCH64 = platform.machine() == "aarch64"
117
+ # apparently they're the same
118
+ AARCH64 = platform.machine().lower() in {"aarch64", "arm64"}
119
+ RISCV64 = platform.machine() == "riscv64"
120
120
 
121
121
 
122
122
  @memoize
@@ -190,7 +190,6 @@ HERE = os.path.realpath(os.path.dirname(__file__))
190
190
  # --- support
191
191
 
192
192
  HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity")
193
- HAS_CPU_FREQ = hasattr(psutil, "cpu_freq")
194
193
  HAS_ENVIRON = hasattr(psutil.Process, "environ")
195
194
  HAS_GETLOADAVG = hasattr(psutil, "getloadavg")
196
195
  HAS_IONICE = hasattr(psutil.Process, "ionice")
@@ -201,15 +200,23 @@ HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num")
201
200
  HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters")
202
201
  HAS_RLIMIT = hasattr(psutil.Process, "rlimit")
203
202
  HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery")
204
- try:
205
- HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery())
206
- except Exception: # noqa: BLE001
207
- HAS_BATTERY = False
208
203
  HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans")
209
204
  HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures")
210
205
  HAS_THREADS = hasattr(psutil.Process, "threads")
211
206
  SKIP_SYSCONS = (MACOS or AIX) and os.getuid() != 0
212
207
 
208
+ try:
209
+ HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery())
210
+ except Exception: # noqa: BLE001
211
+ atexit.register(functools.partial(print, traceback.format_exc()))
212
+ HAS_BATTERY = False
213
+ try:
214
+ HAS_CPU_FREQ = hasattr(psutil, "cpu_freq") and bool(psutil.cpu_freq())
215
+ except Exception: # noqa: BLE001
216
+ atexit.register(functools.partial(print, traceback.format_exc()))
217
+ HAS_CPU_FREQ = False
218
+
219
+
213
220
  # --- misc
214
221
 
215
222
 
@@ -270,6 +277,110 @@ _subprocesses_started = set()
270
277
  _pids_started = set()
271
278
 
272
279
 
280
+ # ===================================================================
281
+ # --- fake pytest
282
+ # ===================================================================
283
+
284
+
285
+ class fake_pytest:
286
+ """A class that mimics some basic pytest APIs. This is meant for
287
+ when unit tests are run in production, where pytest may not be
288
+ installed. Still, the user can test psutil installation via:
289
+
290
+ $ python3 -m psutil.tests
291
+ """
292
+
293
+ @staticmethod
294
+ def _warn_on_exit():
295
+ def _warn_on_exit():
296
+ warnings.warn(
297
+ "Fake pytest module was used. Test results may be inaccurate.",
298
+ UserWarning,
299
+ stacklevel=1,
300
+ )
301
+
302
+ atexit.register(_warn_on_exit)
303
+
304
+ @staticmethod
305
+ def main(*args, **kw): # noqa: ARG004
306
+ """Mimics pytest.main(). It has the same effect as running
307
+ `python3 -m unittest -v` from the project root directory.
308
+ """
309
+ suite = unittest.TestLoader().discover(HERE)
310
+ unittest.TextTestRunner(verbosity=2).run(suite)
311
+ return suite
312
+
313
+ @staticmethod
314
+ def raises(exc, match=None):
315
+ """Mimics `pytest.raises`."""
316
+
317
+ class ExceptionInfo:
318
+ _exc = None
319
+
320
+ @property
321
+ def value(self):
322
+ return self._exc
323
+
324
+ @contextlib.contextmanager
325
+ def context(exc, match=None):
326
+ einfo = ExceptionInfo()
327
+ try:
328
+ yield einfo
329
+ except exc as err:
330
+ if match and not re.search(match, str(err)):
331
+ msg = f'"{match}" does not match "{err}"'
332
+ raise AssertionError(msg)
333
+ einfo._exc = err
334
+ else:
335
+ raise AssertionError(f"{exc!r} not raised")
336
+
337
+ return context(exc, match=match)
338
+
339
+ @staticmethod
340
+ def warns(warning, match=None):
341
+ """Mimics `pytest.warns`."""
342
+ if match:
343
+ return unittest.TestCase().assertWarnsRegex(warning, match)
344
+ return unittest.TestCase().assertWarns(warning)
345
+
346
+ @staticmethod
347
+ def skip(reason=""):
348
+ """Mimics `unittest.SkipTest`."""
349
+ raise unittest.SkipTest(reason)
350
+
351
+ @staticmethod
352
+ def fail(reason=""):
353
+ """Mimics `pytest.fail`."""
354
+ return unittest.TestCase().fail(reason)
355
+
356
+ class mark:
357
+
358
+ @staticmethod
359
+ def skipif(condition, reason=""):
360
+ """Mimics `@pytest.mark.skipif` decorator."""
361
+ return unittest.skipIf(condition, reason)
362
+
363
+ class xdist_group:
364
+ """Mimics `@pytest.mark.xdist_group` decorator (no-op)."""
365
+
366
+ def __init__(self, name=None):
367
+ pass
368
+
369
+ def __call__(self, cls_or_meth):
370
+ return cls_or_meth
371
+
372
+
373
+ # to make pytest.fail() exception catchable
374
+ fake_pytest.fail.Exception = AssertionError
375
+
376
+
377
+ if pytest is None:
378
+ pytest = fake_pytest
379
+ # monkey patch future `import pytest` statements
380
+ sys.modules["pytest"] = fake_pytest
381
+ fake_pytest._warn_on_exit()
382
+
383
+
273
384
  # ===================================================================
274
385
  # --- threads
275
386
  # ===================================================================
@@ -336,7 +447,7 @@ def _reap_children_on_err(fun):
336
447
 
337
448
 
338
449
  @_reap_children_on_err
339
- def spawn_testproc(cmd=None, **kwds):
450
+ def spawn_subproc(cmd=None, **kwds):
340
451
  """Create a python subprocess which does nothing for some secs and
341
452
  return it as a subprocess.Popen instance.
342
453
  If "cmd" is specified that is used instead of python.
@@ -469,7 +580,7 @@ def pyrun(src, **kwds):
469
580
  try:
470
581
  with open(srcfile, "w") as f:
471
582
  f.write(src)
472
- subp = spawn_testproc([PYTHON_EXE, f.name], **kwds)
583
+ subp = spawn_subproc([PYTHON_EXE, f.name], **kwds)
473
584
  wait_for_pid(subp.pid)
474
585
  return (subp, srcfile)
475
586
  except Exception:
@@ -750,7 +861,7 @@ def wait_for_file(fname, delete=True, empty=False):
750
861
 
751
862
 
752
863
  @retry(
753
- exception=AssertionError,
864
+ exception=(AssertionError, pytest.fail.Exception),
754
865
  logfun=None,
755
866
  timeout=GLOBAL_TIMEOUT,
756
867
  interval=0.001,
@@ -876,103 +987,43 @@ def get_testfn(suffix="", dir=None):
876
987
  # ===================================================================
877
988
 
878
989
 
879
- class fake_pytest:
880
- """A class that mimics some basic pytest APIs. This is meant for
881
- when unit tests are run in production, where pytest may not be
882
- installed. Still, the user can test psutil installation via:
883
-
884
- $ python3 -m psutil.tests
885
- """
886
-
887
- @staticmethod
888
- def main(*args, **kw): # noqa: ARG004
889
- """Mimics pytest.main(). It has the same effect as running
890
- `python3 -m unittest -v` from the project root directory.
891
- """
892
- suite = unittest.TestLoader().discover(HERE)
893
- unittest.TextTestRunner(verbosity=2).run(suite)
894
- warnings.warn(
895
- "Fake pytest module was used. Test results may be inaccurate.",
896
- UserWarning,
897
- stacklevel=1,
898
- )
899
- return suite
900
-
901
- @staticmethod
902
- def raises(exc, match=None):
903
- """Mimics `pytest.raises`."""
904
-
905
- class ExceptionInfo:
906
- _exc = None
907
-
908
- @property
909
- def value(self):
910
- return self._exc
911
-
912
- @contextlib.contextmanager
913
- def context(exc, match=None):
914
- einfo = ExceptionInfo()
915
- try:
916
- yield einfo
917
- except exc as err:
918
- if match and not re.search(match, str(err)):
919
- msg = f'"{match}" does not match "{err}"'
920
- raise AssertionError(msg)
921
- einfo._exc = err
922
- else:
923
- raise AssertionError(f"{exc!r} not raised")
924
-
925
- return context(exc, match=match)
926
-
927
- @staticmethod
928
- def warns(warning, match=None):
929
- """Mimics `pytest.warns`."""
930
- if match:
931
- return unittest.TestCase().assertWarnsRegex(warning, match)
932
- return unittest.TestCase().assertWarns(warning)
933
-
934
- @staticmethod
935
- def skip(reason=""):
936
- """Mimics `unittest.SkipTest`."""
937
- raise unittest.SkipTest(reason)
938
-
939
- class mark:
940
-
941
- @staticmethod
942
- def skipif(condition, reason=""):
943
- """Mimics `@pytest.mark.skipif` decorator."""
944
- return unittest.skipIf(condition, reason)
945
-
946
- class xdist_group:
947
- """Mimics `@pytest.mark.xdist_group` decorator (no-op)."""
948
-
949
- def __init__(self, name=None):
950
- pass
951
-
952
- def __call__(self, cls_or_meth):
953
- return cls_or_meth
954
-
955
-
956
- if pytest is None:
957
- pytest = fake_pytest
958
-
959
-
960
990
  class PsutilTestCase(unittest.TestCase):
961
991
  """Test class providing auto-cleanup wrappers on top of process
962
992
  test utilities. All test classes should derive from this one, even
963
993
  if we use pytest.
964
994
  """
965
995
 
996
+ # Print a full path representation of the single unit test being
997
+ # run, similar to pytest output. Used only when running tests with
998
+ # the unittest runner.
999
+ def __str__(self):
1000
+ fqmod = self.__class__.__module__
1001
+ if not fqmod.startswith('psutil.'):
1002
+ fqmod = 'psutil.tests.' + fqmod
1003
+ return "{}.{}.{}".format(
1004
+ fqmod,
1005
+ self.__class__.__name__,
1006
+ self._testMethodName,
1007
+ )
1008
+
966
1009
  def get_testfn(self, suffix="", dir=None):
967
1010
  fname = get_testfn(suffix=suffix, dir=dir)
968
1011
  self.addCleanup(safe_rmpath, fname)
969
1012
  return fname
970
1013
 
971
- def spawn_testproc(self, *args, **kwds):
972
- sproc = spawn_testproc(*args, **kwds)
1014
+ def spawn_subproc(self, *args, **kwds):
1015
+ sproc = spawn_subproc(*args, **kwds)
973
1016
  self.addCleanup(terminate, sproc)
974
1017
  return sproc
975
1018
 
1019
+ def spawn_psproc(self, *args, **kwargs):
1020
+ sproc = self.spawn_subproc(*args, **kwargs)
1021
+ try:
1022
+ return psutil.Process(sproc.pid)
1023
+ except psutil.NoSuchProcess:
1024
+ self.assert_pid_gone(sproc.pid)
1025
+ raise
1026
+
976
1027
  def spawn_children_pair(self):
977
1028
  child1, child2 = spawn_children_pair()
978
1029
  self.addCleanup(terminate, child2)
@@ -1004,23 +1055,23 @@ class PsutilTestCase(unittest.TestCase):
1004
1055
  str(exc)
1005
1056
  repr(exc)
1006
1057
 
1007
- def assertPidGone(self, pid):
1058
+ def assert_pid_gone(self, pid):
1008
1059
  with pytest.raises(psutil.NoSuchProcess) as cm:
1009
1060
  try:
1010
1061
  psutil.Process(pid)
1011
1062
  except psutil.ZombieProcess:
1012
- raise AssertionError("wasn't supposed to raise ZombieProcess")
1063
+ raise pytest.fail("wasn't supposed to raise ZombieProcess")
1013
1064
  assert cm.value.pid == pid
1014
1065
  assert cm.value.name is None
1015
1066
  assert not psutil.pid_exists(pid), pid
1016
1067
  assert pid not in psutil.pids()
1017
1068
  assert pid not in [x.pid for x in psutil.process_iter()]
1018
1069
 
1019
- def assertProcessGone(self, proc):
1020
- self.assertPidGone(proc.pid)
1070
+ def assert_proc_gone(self, proc):
1071
+ self.assert_pid_gone(proc.pid)
1021
1072
  ns = process_namespace(proc)
1022
1073
  for fun, name in ns.iter(ns.all, clear_cache=True):
1023
- with self.subTest(proc=proc, name=name):
1074
+ with self.subTest(proc=str(proc), name=name):
1024
1075
  try:
1025
1076
  ret = fun()
1026
1077
  except psutil.ZombieProcess:
@@ -1035,13 +1086,15 @@ class PsutilTestCase(unittest.TestCase):
1035
1086
  raise AssertionError(msg)
1036
1087
  proc.wait(timeout=0) # assert not raise TimeoutExpired
1037
1088
 
1038
- def assertProcessZombie(self, proc):
1089
+ def assert_proc_zombie(self, proc):
1039
1090
  # A zombie process should always be instantiable.
1040
1091
  clone = psutil.Process(proc.pid)
1041
- # Cloned zombie on Open/NetBSD has null creation time, see:
1092
+ # Cloned zombie on Open/NetBSD/illumos/Solaris has null creation
1093
+ # time, see:
1042
1094
  # https://github.com/giampaolo/psutil/issues/2287
1095
+ # https://github.com/giampaolo/psutil/issues/2593
1043
1096
  assert proc == clone
1044
- if not (OPENBSD or NETBSD):
1097
+ if not (OPENBSD or NETBSD or SUNOS):
1045
1098
  assert hash(proc) == hash(clone)
1046
1099
  # Its status always be querable.
1047
1100
  assert proc.status() == psutil.STATUS_ZOMBIE
@@ -1058,7 +1111,7 @@ class PsutilTestCase(unittest.TestCase):
1058
1111
  # Call all methods.
1059
1112
  ns = process_namespace(proc)
1060
1113
  for fun, name in ns.iter(ns.all, clear_cache=True):
1061
- with self.subTest(proc=proc, name=name):
1114
+ with self.subTest(proc=str(proc), name=name):
1062
1115
  try:
1063
1116
  fun()
1064
1117
  except (psutil.ZombieProcess, psutil.AccessDenied) as exc:
@@ -1089,16 +1142,16 @@ class PsutilTestCase(unittest.TestCase):
1089
1142
  # Its parent should 'see' it (edit: not true on BSD and MACOS).
1090
1143
  # descendants = [x.pid for x in psutil.Process().children(
1091
1144
  # recursive=True)]
1092
- # self.assertIn(proc.pid, descendants)
1145
+ # assert proc.pid in descendants
1093
1146
 
1094
1147
  # __eq__ can't be relied upon because creation time may not be
1095
1148
  # querable.
1096
- # self.assertEqual(proc, psutil.Process(proc.pid))
1149
+ # assert proc == psutil.Process(proc.pid)
1097
1150
 
1098
1151
  # XXX should we also assume ppid() to be usable? Note: this
1099
1152
  # would be an important use case as the only way to get
1100
1153
  # rid of a zombie is to kill its parent.
1101
- # self.assertEqual(proc.ppid(), os.getpid())
1154
+ # assert proc == ppid(), os.getpid()
1102
1155
 
1103
1156
 
1104
1157
  @pytest.mark.skipif(PYPY, reason="unreliable on PYPY")
@@ -1180,13 +1233,13 @@ class TestMemoryLeak(PsutilTestCase):
1180
1233
  f"negative diff {diff!r} (gc probably collected a"
1181
1234
  " resource from a previous test)"
1182
1235
  )
1183
- raise self.fail(msg)
1236
+ raise pytest.fail(msg)
1184
1237
  if diff > 0:
1185
1238
  type_ = "fd" if POSIX else "handle"
1186
1239
  if diff > 1:
1187
1240
  type_ += "s"
1188
1241
  msg = f"{diff} unclosed {type_} after calling {fun!r}"
1189
- raise self.fail(msg)
1242
+ raise pytest.fail(msg)
1190
1243
 
1191
1244
  def _call_ntimes(self, fun, times):
1192
1245
  """Get 2 distinct memory samples, before and after having
@@ -1227,7 +1280,7 @@ class TestMemoryLeak(PsutilTestCase):
1227
1280
  self._log(msg)
1228
1281
  times += increase
1229
1282
  prev_mem = mem
1230
- raise self.fail(". ".join(messages))
1283
+ raise pytest.fail(". ".join(messages))
1231
1284
 
1232
1285
  # ---
1233
1286
 
@@ -1262,7 +1315,12 @@ class TestMemoryLeak(PsutilTestCase):
1262
1315
  """
1263
1316
 
1264
1317
  def call():
1265
- self.assertRaises(exc, fun)
1318
+ try:
1319
+ fun()
1320
+ except exc:
1321
+ pass
1322
+ else:
1323
+ raise pytest.fail(f"{fun} did not raise {exc}")
1266
1324
 
1267
1325
  self.execute(call, **kwargs)
1268
1326
 
@@ -1355,25 +1413,27 @@ def print_sysinfo():
1355
1413
  bytes2human(swap.used),
1356
1414
  bytes2human(swap.total),
1357
1415
  )
1416
+
1417
+ # constants
1418
+ constants = sorted(
1419
+ [k for k, v in globals().items() if k.isupper() and v is True]
1420
+ )
1421
+ info['constants'] = "\n ".join(constants)
1422
+
1423
+ # processes
1358
1424
  info['pids'] = len(psutil.pids())
1359
1425
  pinfo = psutil.Process().as_dict()
1360
1426
  pinfo.pop('memory_maps', None)
1427
+ pinfo["environ"] = {k: os.environ[k] for k in sorted(os.environ)}
1361
1428
  info['proc'] = pprint.pformat(pinfo)
1362
1429
 
1430
+ # print
1363
1431
  print("=" * 70, file=sys.stderr) # noqa: T201
1364
1432
  for k, v in info.items():
1365
1433
  print("{:<17} {}".format(k + ":", v), file=sys.stderr) # noqa: T201
1366
1434
  print("=" * 70, file=sys.stderr) # noqa: T201
1367
1435
  sys.stdout.flush()
1368
1436
 
1369
- # if WINDOWS:
1370
- # os.system("tasklist")
1371
- # elif shutil.which("ps"):
1372
- # os.system("ps aux")
1373
- # print("=" * 70, file=sys.stderr)
1374
-
1375
- sys.stdout.flush()
1376
-
1377
1437
 
1378
1438
  def is_win_secure_system_proc(pid):
1379
1439
  # see: https://github.com/giampaolo/psutil/issues/2338
@@ -1569,7 +1629,7 @@ class system_namespace:
1569
1629
  ('virtual_memory', (), {}),
1570
1630
  ]
1571
1631
  if HAS_CPU_FREQ:
1572
- if MACOS and platform.machine() == 'arm64': # skipped due to #1892
1632
+ if MACOS and AARCH64: # skipped due to #1892
1573
1633
  pass
1574
1634
  else:
1575
1635
  getters += [('cpu_freq', (), {'percpu': True})]
@@ -1618,7 +1678,10 @@ def retry_on_failure(retries=NO_RETRIES):
1618
1678
  print(f"{exc!r}, retrying", file=sys.stderr) # noqa: T201
1619
1679
 
1620
1680
  return retry(
1621
- exception=AssertionError, timeout=None, retries=retries, logfun=logfun
1681
+ exception=(AssertionError, pytest.fail.Exception),
1682
+ timeout=None,
1683
+ retries=retries,
1684
+ logfun=logfun,
1622
1685
  )
1623
1686
 
1624
1687
 
@@ -3,10 +3,9 @@
3
3
  # found in the LICENSE file.
4
4
 
5
5
  """Run unit tests. This is invoked by:
6
- $ python -m psutil.tests.
6
+ $ python3 -m psutil.tests.
7
7
  """
8
8
 
9
9
  from psutil.tests import pytest
10
10
 
11
-
12
- pytest.main(["-v", "-s", "--tb=short"])
11
+ pytest.main()