py2docfx 0.1.11rc1981066__py3-none-any.whl → 0.1.11rc1996319__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 (126) hide show
  1. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/authorization_code.py +1 -1
  2. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azd_cli.py +20 -14
  3. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_arc.py +1 -1
  4. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_cli.py +36 -14
  5. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/azure_powershell.py +1 -1
  6. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/chained.py +2 -2
  7. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/default.py +4 -3
  8. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/imds.py +2 -2
  9. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/managed_identity.py +1 -1
  10. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/__init__.py +2 -0
  11. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/auth_code_redirect_handler.py +1 -1
  12. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/decorators.py +15 -7
  13. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/interactive.py +1 -1
  14. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/managed_identity_client.py +0 -1
  15. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/msal_client.py +1 -1
  16. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/msal_managed_identity_client.py +2 -1
  17. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/shared_token_cache.py +3 -3
  18. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/utils.py +17 -2
  19. py2docfx/venv/venv1/Lib/site-packages/azure/identity/_version.py +1 -1
  20. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azd_cli.py +14 -11
  21. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/azure_cli.py +30 -12
  22. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/default.py +2 -2
  23. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/imds.py +3 -3
  24. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/managed_identity.py +1 -1
  25. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_internal/decorators.py +15 -7
  26. py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_internal/managed_identity_client.py +1 -1
  27. py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
  28. py2docfx/venv/venv1/Lib/site-packages/google/api/annotations_pb2.py +7 -4
  29. py2docfx/venv/venv1/Lib/site-packages/google/api/auth_pb2.py +6 -3
  30. py2docfx/venv/venv1/Lib/site-packages/google/api/backend_pb2.py +14 -7
  31. py2docfx/venv/venv1/Lib/site-packages/google/api/billing_pb2.py +6 -3
  32. py2docfx/venv/venv1/Lib/site-packages/google/api/client_pb2.py +47 -38
  33. py2docfx/venv/venv1/Lib/site-packages/google/api/config_change_pb2.py +6 -3
  34. py2docfx/venv/venv1/Lib/site-packages/google/api/consumer_pb2.py +6 -3
  35. py2docfx/venv/venv1/Lib/site-packages/google/api/context_pb2.py +6 -3
  36. py2docfx/venv/venv1/Lib/site-packages/google/api/control_pb2.py +6 -4
  37. py2docfx/venv/venv1/Lib/site-packages/google/api/distribution_pb2.py +7 -5
  38. py2docfx/venv/venv1/Lib/site-packages/google/api/documentation_pb2.py +6 -3
  39. py2docfx/venv/venv1/Lib/site-packages/google/api/endpoint_pb2.py +6 -3
  40. py2docfx/venv/venv1/Lib/site-packages/google/api/error_reason_pb2.py +6 -3
  41. py2docfx/venv/venv1/Lib/site-packages/google/api/field_behavior_pb2.py +8 -6
  42. py2docfx/venv/venv1/Lib/site-packages/google/api/field_info_pb2.py +6 -4
  43. py2docfx/venv/venv1/Lib/site-packages/google/api/http_pb2.py +7 -4
  44. py2docfx/venv/venv1/Lib/site-packages/google/api/httpbody_pb2.py +6 -4
  45. py2docfx/venv/venv1/Lib/site-packages/google/api/label_pb2.py +7 -4
  46. py2docfx/venv/venv1/Lib/site-packages/google/api/launch_stage_pb2.py +6 -3
  47. py2docfx/venv/venv1/Lib/site-packages/google/api/log_pb2.py +6 -4
  48. py2docfx/venv/venv1/Lib/site-packages/google/api/logging_pb2.py +6 -3
  49. py2docfx/venv/venv1/Lib/site-packages/google/api/metric_pb2.py +12 -9
  50. py2docfx/venv/venv1/Lib/site-packages/google/api/monitored_resource_pb2.py +15 -10
  51. py2docfx/venv/venv1/Lib/site-packages/google/api/monitoring_pb2.py +6 -3
  52. py2docfx/venv/venv1/Lib/site-packages/google/api/policy_pb2.py +7 -5
  53. py2docfx/venv/venv1/Lib/site-packages/google/api/quota_pb2.py +10 -7
  54. py2docfx/venv/venv1/Lib/site-packages/google/api/resource_pb2.py +7 -5
  55. py2docfx/venv/venv1/Lib/site-packages/google/api/routing_pb2.py +6 -4
  56. py2docfx/venv/venv1/Lib/site-packages/google/api/service_pb2.py +15 -12
  57. py2docfx/venv/venv1/Lib/site-packages/google/api/source_info_pb2.py +6 -4
  58. py2docfx/venv/venv1/Lib/site-packages/google/api/system_parameter_pb2.py +6 -3
  59. py2docfx/venv/venv1/Lib/site-packages/google/api/usage_pb2.py +6 -3
  60. py2docfx/venv/venv1/Lib/site-packages/google/api/visibility_pb2.py +7 -5
  61. py2docfx/venv/venv1/Lib/site-packages/google/cloud/extended_operations_pb2.py +6 -4
  62. py2docfx/venv/venv1/Lib/site-packages/google/cloud/location/locations_pb2.py +18 -13
  63. py2docfx/venv/venv1/Lib/site-packages/google/gapic/metadata/gapic_metadata_pb2.py +31 -26
  64. py2docfx/venv/venv1/Lib/site-packages/google/logging/type/http_request_pb2.py +6 -4
  65. py2docfx/venv/venv1/Lib/site-packages/google/logging/type/log_severity_pb2.py +6 -3
  66. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_grpc.py +2 -1
  67. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_grpc_pb2.py +11 -10
  68. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_pb2.py +20 -17
  69. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_pb2_grpc.py +1 -2
  70. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_proto.py +2 -1
  71. py2docfx/venv/venv1/Lib/site-packages/google/longrunning/operations_proto_pb2.py +22 -19
  72. py2docfx/venv/venv1/Lib/site-packages/google/rpc/code_pb2.py +6 -3
  73. py2docfx/venv/venv1/Lib/site-packages/google/rpc/context/attribute_context_pb2.py +20 -16
  74. py2docfx/venv/venv1/Lib/site-packages/google/rpc/context/audit_context_pb2.py +7 -5
  75. py2docfx/venv/venv1/Lib/site-packages/google/rpc/error_details_pb2.py +21 -19
  76. py2docfx/venv/venv1/Lib/site-packages/google/rpc/http_pb2.py +6 -3
  77. py2docfx/venv/venv1/Lib/site-packages/google/rpc/status_pb2.py +6 -4
  78. py2docfx/venv/venv1/Lib/site-packages/google/type/calendar_period_pb2.py +6 -3
  79. py2docfx/venv/venv1/Lib/site-packages/google/type/color_pb2.py +6 -4
  80. py2docfx/venv/venv1/Lib/site-packages/google/type/date_pb2.py +6 -3
  81. py2docfx/venv/venv1/Lib/site-packages/google/type/datetime_pb2.py +6 -4
  82. py2docfx/venv/venv1/Lib/site-packages/google/type/dayofweek_pb2.py +6 -3
  83. py2docfx/venv/venv1/Lib/site-packages/google/type/decimal_pb2.py +6 -3
  84. py2docfx/venv/venv1/Lib/site-packages/google/type/expr_pb2.py +6 -3
  85. py2docfx/venv/venv1/Lib/site-packages/google/type/fraction_pb2.py +6 -3
  86. py2docfx/venv/venv1/Lib/site-packages/google/type/interval_pb2.py +6 -4
  87. py2docfx/venv/venv1/Lib/site-packages/google/type/latlng_pb2.py +6 -3
  88. py2docfx/venv/venv1/Lib/site-packages/google/type/localized_text_pb2.py +6 -3
  89. py2docfx/venv/venv1/Lib/site-packages/google/type/money_pb2.py +6 -3
  90. py2docfx/venv/venv1/Lib/site-packages/google/type/month_pb2.py +6 -3
  91. py2docfx/venv/venv1/Lib/site-packages/google/type/phone_number_pb2.py +6 -3
  92. py2docfx/venv/venv1/Lib/site-packages/google/type/postal_address_pb2.py +6 -3
  93. py2docfx/venv/venv1/Lib/site-packages/google/type/quaternion_pb2.py +6 -3
  94. py2docfx/venv/venv1/Lib/site-packages/google/type/timeofday_pb2.py +6 -3
  95. py2docfx/venv/venv1/Lib/site-packages/psutil/__init__.py +122 -201
  96. py2docfx/venv/venv1/Lib/site-packages/psutil/_common.py +84 -128
  97. py2docfx/venv/venv1/Lib/site-packages/psutil/_psaix.py +24 -38
  98. py2docfx/venv/venv1/Lib/site-packages/psutil/_psbsd.py +44 -58
  99. py2docfx/venv/venv1/Lib/site-packages/psutil/_pslinux.py +170 -254
  100. py2docfx/venv/venv1/Lib/site-packages/psutil/_psosx.py +8 -16
  101. py2docfx/venv/venv1/Lib/site-packages/psutil/_psposix.py +13 -49
  102. py2docfx/venv/venv1/Lib/site-packages/psutil/_pssunos.py +41 -60
  103. py2docfx/venv/venv1/Lib/site-packages/psutil/_pswindows.py +75 -145
  104. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__init__.py +105 -193
  105. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_aix.py +2 -2
  106. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_bsd.py +27 -26
  107. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_connections.py +16 -17
  108. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_contracts.py +5 -19
  109. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_linux.py +153 -211
  110. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_memleaks.py +0 -6
  111. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_misc.py +22 -207
  112. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_osx.py +9 -4
  113. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_posix.py +8 -15
  114. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process.py +104 -184
  115. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process_all.py +28 -36
  116. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_scripts.py +240 -0
  117. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_sunos.py +1 -1
  118. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_system.py +44 -50
  119. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_testutils.py +23 -33
  120. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_unicode.py +8 -67
  121. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_windows.py +32 -52
  122. {py2docfx-0.1.11rc1981066.dist-info → py2docfx-0.1.11rc1996319.dist-info}/METADATA +1 -1
  123. {py2docfx-0.1.11rc1981066.dist-info → py2docfx-0.1.11rc1996319.dist-info}/RECORD +125 -125
  124. py2docfx/venv/venv1/Lib/site-packages/psutil/_compat.py +0 -477
  125. {py2docfx-0.1.11rc1981066.dist-info → py2docfx-0.1.11rc1996319.dist-info}/WHEEL +0 -0
  126. {py2docfx-0.1.11rc1981066.dist-info → py2docfx-0.1.11rc1996319.dist-info}/top_level.txt +0 -0
@@ -4,15 +4,16 @@
4
4
 
5
5
  """Linux platform implementation."""
6
6
 
7
- from __future__ import division
8
7
 
9
8
  import base64
10
9
  import collections
10
+ import enum
11
11
  import errno
12
12
  import functools
13
13
  import glob
14
14
  import os
15
15
  import re
16
+ import resource
16
17
  import socket
17
18
  import struct
18
19
  import sys
@@ -24,6 +25,7 @@ from . import _common
24
25
  from . import _psposix
25
26
  from . import _psutil_linux as cext
26
27
  from . import _psutil_posix as cext_posix
28
+ from ._common import ENCODING
27
29
  from ._common import NIC_DUPLEX_FULL
28
30
  from ._common import NIC_DUPLEX_HALF
29
31
  from ._common import NIC_DUPLEX_UNKNOWN
@@ -44,18 +46,6 @@ from ._common import parse_environ_block
44
46
  from ._common import path_exists_strict
45
47
  from ._common import supports_ipv6
46
48
  from ._common import usage_percent
47
- from ._compat import PY3
48
- from ._compat import FileNotFoundError
49
- from ._compat import PermissionError
50
- from ._compat import ProcessLookupError
51
- from ._compat import b
52
- from ._compat import basestring
53
-
54
-
55
- if PY3:
56
- import enum
57
- else:
58
- enum = None
59
49
 
60
50
 
61
51
  # fmt: off
@@ -69,6 +59,11 @@ __extra__all__ = [
69
59
  "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
70
60
  "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING",
71
61
  ]
62
+
63
+ if hasattr(resource, "prlimit"):
64
+ __extra__all__.extend(
65
+ [x for x in dir(cext) if x.startswith('RLIM') and x.isupper()]
66
+ )
72
67
  # fmt: on
73
68
 
74
69
 
@@ -78,8 +73,8 @@ __extra__all__ = [
78
73
 
79
74
 
80
75
  POWER_SUPPLY_PATH = "/sys/class/power_supply"
81
- HAS_PROC_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid())
82
- HAS_PROC_SMAPS_ROLLUP = os.path.exists('/proc/%s/smaps_rollup' % os.getpid())
76
+ HAS_PROC_SMAPS = os.path.exists(f"/proc/{os.getpid()}/smaps")
77
+ HAS_PROC_SMAPS_ROLLUP = os.path.exists(f"/proc/{os.getpid()}/smaps_rollup")
83
78
  HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get")
84
79
  HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get")
85
80
 
@@ -102,29 +97,21 @@ LITTLE_ENDIAN = sys.byteorder == 'little'
102
97
  # * https://lkml.org/lkml/2015/8/17/234
103
98
  DISK_SECTOR_SIZE = 512
104
99
 
105
- if enum is None:
106
- AF_LINK = socket.AF_PACKET
107
- else:
108
- AddressFamily = enum.IntEnum(
109
- 'AddressFamily', {'AF_LINK': int(socket.AF_PACKET)}
110
- )
111
- AF_LINK = AddressFamily.AF_LINK
100
+ AddressFamily = enum.IntEnum(
101
+ 'AddressFamily', {'AF_LINK': int(socket.AF_PACKET)}
102
+ )
103
+ AF_LINK = AddressFamily.AF_LINK
104
+
112
105
 
113
106
  # ioprio_* constants http://linux.die.net/man/2/ioprio_get
114
- if enum is None:
107
+ class IOPriority(enum.IntEnum):
115
108
  IOPRIO_CLASS_NONE = 0
116
109
  IOPRIO_CLASS_RT = 1
117
110
  IOPRIO_CLASS_BE = 2
118
111
  IOPRIO_CLASS_IDLE = 3
119
- else:
120
112
 
121
- class IOPriority(enum.IntEnum):
122
- IOPRIO_CLASS_NONE = 0
123
- IOPRIO_CLASS_RT = 1
124
- IOPRIO_CLASS_BE = 2
125
- IOPRIO_CLASS_IDLE = 3
126
113
 
127
- globals().update(IOPriority.__members__)
114
+ globals().update(IOPriority.__members__)
128
115
 
129
116
  # See:
130
117
  # https://github.com/torvalds/linux/blame/master/fs/proc/array.c
@@ -211,7 +198,7 @@ pcputimes = namedtuple('pcputimes',
211
198
 
212
199
  def readlink(path):
213
200
  """Wrapper around os.readlink()."""
214
- assert isinstance(path, basestring), path
201
+ assert isinstance(path, str), path
215
202
  path = os.readlink(path)
216
203
  # readlink() might return paths containing null bytes ('\x00')
217
204
  # resulting in "TypeError: must be encoded string without NULL
@@ -255,9 +242,9 @@ def is_storage_device(name):
255
242
  name = name.replace('/', '!')
256
243
  including_virtual = True
257
244
  if including_virtual:
258
- path = "/sys/block/%s" % name
245
+ path = f"/sys/block/{name}"
259
246
  else:
260
- path = "/sys/block/%s/device" % name
247
+ path = f"/sys/block/{name}/device"
261
248
  return os.access(path, os.F_OK)
262
249
 
263
250
 
@@ -270,7 +257,7 @@ def set_scputimes_ntuple(procfs_path):
270
257
  Used by cpu_times() function.
271
258
  """
272
259
  global scputimes
273
- with open_binary('%s/stat' % procfs_path) as f:
260
+ with open_binary(f"{procfs_path}/stat") as f:
274
261
  values = f.readline().split()[1:]
275
262
  fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq']
276
263
  vlen = len(values)
@@ -290,62 +277,10 @@ try:
290
277
  set_scputimes_ntuple("/proc")
291
278
  except Exception as err: # noqa: BLE001
292
279
  # Don't want to crash at import time.
293
- debug("ignoring exception on import: %r" % err)
280
+ debug(f"ignoring exception on import: {err!r}")
294
281
  scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0)
295
282
 
296
283
 
297
- # =====================================================================
298
- # --- prlimit
299
- # =====================================================================
300
-
301
- # Backport of resource.prlimit() for Python 2. Originally this was done
302
- # in C, but CentOS-6 which we use to create manylinux wheels is too old
303
- # and does not support prlimit() syscall. As such the resulting wheel
304
- # would not include prlimit(), even when installed on newer systems.
305
- # This is the only part of psutil using ctypes.
306
-
307
- prlimit = None
308
- try:
309
- from resource import prlimit # python >= 3.4
310
- except ImportError:
311
- import ctypes
312
-
313
- libc = ctypes.CDLL(None, use_errno=True)
314
-
315
- if hasattr(libc, "prlimit"):
316
-
317
- def prlimit(pid, resource_, limits=None):
318
- class StructRlimit(ctypes.Structure):
319
- _fields_ = [
320
- ('rlim_cur', ctypes.c_longlong),
321
- ('rlim_max', ctypes.c_longlong),
322
- ]
323
-
324
- current = StructRlimit()
325
- if limits is None:
326
- # get
327
- ret = libc.prlimit(pid, resource_, None, ctypes.byref(current))
328
- else:
329
- # set
330
- new = StructRlimit()
331
- new.rlim_cur = limits[0]
332
- new.rlim_max = limits[1]
333
- ret = libc.prlimit(
334
- pid, resource_, ctypes.byref(new), ctypes.byref(current)
335
- )
336
-
337
- if ret != 0:
338
- errno_ = ctypes.get_errno()
339
- raise OSError(errno_, os.strerror(errno_))
340
- return (current.rlim_cur, current.rlim_max)
341
-
342
-
343
- if prlimit is not None:
344
- __extra__all__.extend(
345
- [x for x in dir(cext) if x.startswith('RLIM') and x.isupper()]
346
- )
347
-
348
-
349
284
  # =====================================================================
350
285
  # --- system memory
351
286
  # =====================================================================
@@ -389,14 +324,13 @@ def calculate_avail_vmem(mems):
389
324
  slab_reclaimable = mems[b'SReclaimable:']
390
325
  except KeyError as err:
391
326
  debug(
392
- "%s is missing from /proc/meminfo; using an approximation for "
393
- "calculating available memory"
394
- % err.args[0]
327
+ f"{err.args[0]} is missing from /proc/meminfo; using an"
328
+ " approximation for calculating available memory"
395
329
  )
396
330
  return fallback
397
331
  try:
398
- f = open_binary('%s/zoneinfo' % get_procfs_path())
399
- except IOError:
332
+ f = open_binary(f"{get_procfs_path()}/zoneinfo")
333
+ except OSError:
400
334
  return fallback # kernel 2.6.13
401
335
 
402
336
  watermark_low = 0
@@ -425,7 +359,7 @@ def virtual_memory():
425
359
  """
426
360
  missing_fields = []
427
361
  mems = {}
428
- with open_binary('%s/meminfo' % get_procfs_path()) as f:
362
+ with open_binary(f"{get_procfs_path()}/meminfo") as f:
429
363
  for line in f:
430
364
  fields = line.split()
431
365
  mems[fields[0]] = int(fields[1]) * 1024
@@ -527,7 +461,7 @@ def virtual_memory():
527
461
 
528
462
  # Warn about missing metrics which are set to 0.
529
463
  if missing_fields:
530
- msg = "%s memory stats couldn't be determined and %s set to 0" % (
464
+ msg = "{} memory stats couldn't be determined and {} set to 0".format(
531
465
  ", ".join(missing_fields),
532
466
  "was" if len(missing_fields) == 1 else "were",
533
467
  )
@@ -551,7 +485,7 @@ def virtual_memory():
551
485
  def swap_memory():
552
486
  """Return swap memory metrics."""
553
487
  mems = {}
554
- with open_binary('%s/meminfo' % get_procfs_path()) as f:
488
+ with open_binary(f"{get_procfs_path()}/meminfo") as f:
555
489
  for line in f:
556
490
  fields = line.split()
557
491
  mems[fields[0]] = int(fields[1]) * 1024
@@ -571,12 +505,12 @@ def swap_memory():
571
505
  percent = usage_percent(used, total, round_=1)
572
506
  # get pgin/pgouts
573
507
  try:
574
- f = open_binary("%s/vmstat" % get_procfs_path())
575
- except IOError as err:
508
+ f = open_binary(f"{get_procfs_path()}/vmstat")
509
+ except OSError as err:
576
510
  # see https://github.com/giampaolo/psutil/issues/722
577
511
  msg = (
578
512
  "'sin' and 'sout' swap memory stats couldn't "
579
- + "be determined and were set to 0 (%s)" % str(err)
513
+ f"be determined and were set to 0 ({err})"
580
514
  )
581
515
  warnings.warn(msg, RuntimeWarning, stacklevel=2)
582
516
  sin = sout = 0
@@ -617,7 +551,7 @@ def cpu_times():
617
551
  """
618
552
  procfs_path = get_procfs_path()
619
553
  set_scputimes_ntuple(procfs_path)
620
- with open_binary('%s/stat' % procfs_path) as f:
554
+ with open_binary(f"{procfs_path}/stat") as f:
621
555
  values = f.readline().split()
622
556
  fields = values[1 : len(scputimes._fields) + 1]
623
557
  fields = [float(x) / CLOCK_TICKS for x in fields]
@@ -631,7 +565,7 @@ def per_cpu_times():
631
565
  procfs_path = get_procfs_path()
632
566
  set_scputimes_ntuple(procfs_path)
633
567
  cpus = []
634
- with open_binary('%s/stat' % procfs_path) as f:
568
+ with open_binary(f"{procfs_path}/stat") as f:
635
569
  # get rid of the first line which refers to system wide CPU stats
636
570
  f.readline()
637
571
  for line in f:
@@ -651,7 +585,7 @@ def cpu_count_logical():
651
585
  except ValueError:
652
586
  # as a second fallback we try to parse /proc/cpuinfo
653
587
  num = 0
654
- with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
588
+ with open_binary(f"{get_procfs_path()}/cpuinfo") as f:
655
589
  for line in f:
656
590
  if line.lower().startswith(b'processor'):
657
591
  num += 1
@@ -661,7 +595,7 @@ def cpu_count_logical():
661
595
  # try to parse /proc/stat as a last resort
662
596
  if num == 0:
663
597
  search = re.compile(r'cpu\d')
664
- with open_text('%s/stat' % get_procfs_path()) as f:
598
+ with open_text(f"{get_procfs_path()}/stat") as f:
665
599
  for line in f:
666
600
  line = line.split(' ')[0]
667
601
  if search.match(line):
@@ -694,7 +628,7 @@ def cpu_count_cores():
694
628
  # Method #2
695
629
  mapping = {}
696
630
  current_info = {}
697
- with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
631
+ with open_binary(f"{get_procfs_path()}/cpuinfo") as f:
698
632
  for line in f:
699
633
  line = line.strip().lower()
700
634
  if not line:
@@ -717,7 +651,7 @@ def cpu_count_cores():
717
651
 
718
652
  def cpu_stats():
719
653
  """Return various CPU stats as a named tuple."""
720
- with open_binary('%s/stat' % get_procfs_path()) as f:
654
+ with open_binary(f"{get_procfs_path()}/stat") as f:
721
655
  ctx_switches = None
722
656
  interrupts = None
723
657
  soft_interrupts = None
@@ -742,12 +676,12 @@ def cpu_stats():
742
676
 
743
677
  def _cpu_get_cpuinfo_freq():
744
678
  """Return current CPU frequency from cpuinfo if available."""
745
- ret = []
746
- with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
747
- for line in f:
748
- if line.lower().startswith(b'cpu mhz'):
749
- ret.append(float(line.split(b':', 1)[1]))
750
- return ret
679
+ with open_binary(f"{get_procfs_path()}/cpuinfo") as f:
680
+ return [
681
+ float(line.split(b':', 1)[1])
682
+ for line in f
683
+ if line.lower().startswith(b'cpu mhz')
684
+ ]
751
685
 
752
686
 
753
687
  if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or os.path.exists(
@@ -778,9 +712,7 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or os.path.exists(
778
712
  # https://github.com/giampaolo/psutil/issues/1071
779
713
  curr = bcat(pjoin(path, "cpuinfo_cur_freq"), fallback=None)
780
714
  if curr is None:
781
- online_path = (
782
- "/sys/devices/system/cpu/cpu{}/online".format(i)
783
- )
715
+ online_path = f"/sys/devices/system/cpu/cpu{i}/online"
784
716
  # if cpu core is offline, set to all zeroes
785
717
  if cat(online_path, fallback=None) == "0\n":
786
718
  ret.append(_common.scpufreq(0.0, 0.0, 0.0))
@@ -851,12 +783,12 @@ class NetConnections:
851
783
 
852
784
  def get_proc_inodes(self, pid):
853
785
  inodes = defaultdict(list)
854
- for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)):
786
+ for fd in os.listdir(f"{self._procfs_path}/{pid}/fd"):
855
787
  try:
856
- inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd))
788
+ inode = readlink(f"{self._procfs_path}/{pid}/fd/{fd}")
857
789
  except (FileNotFoundError, ProcessLookupError):
858
790
  # ENOENT == file which is gone in the meantime;
859
- # os.stat('/proc/%s' % self.pid) will be done later
791
+ # os.stat(f"/proc/{self.pid}") will be done later
860
792
  # to force NSP (if it's the case)
861
793
  continue
862
794
  except OSError as err:
@@ -914,8 +846,7 @@ class NetConnections:
914
846
  # no end-points connected
915
847
  if not port:
916
848
  return ()
917
- if PY3:
918
- ip = ip.encode('ascii')
849
+ ip = ip.encode('ascii')
919
850
  if family == socket.AF_INET:
920
851
  # see: https://github.com/giampaolo/psutil/issues/201
921
852
  if LITTLE_ENDIAN:
@@ -939,9 +870,8 @@ class NetConnections:
939
870
  except ValueError:
940
871
  # see: https://github.com/giampaolo/psutil/issues/623
941
872
  if not supports_ipv6():
942
- raise _Ipv6UnsupportedError
943
- else:
944
- raise
873
+ raise _Ipv6UnsupportedError from None
874
+ raise
945
875
  return _common.addr(ip, port)
946
876
 
947
877
  @staticmethod
@@ -958,10 +888,11 @@ class NetConnections:
958
888
  line.split()[:10]
959
889
  )
960
890
  except ValueError:
961
- raise RuntimeError(
962
- "error while parsing %s; malformed line %s %r"
963
- % (file, lineno, line)
891
+ msg = (
892
+ f"error while parsing {file}; malformed line"
893
+ f" {lineno} {line!r}"
964
894
  )
895
+ raise RuntimeError(msg) from None
965
896
  if inode in inodes:
966
897
  # # We assume inet sockets are unique, so we error
967
898
  # # out if there are multiple references to the
@@ -999,11 +930,11 @@ class NetConnections:
999
930
  if ' ' not in line:
1000
931
  # see: https://github.com/giampaolo/psutil/issues/766
1001
932
  continue
1002
- raise RuntimeError(
1003
- "error while parsing %s; malformed line %r"
1004
- % (file, line)
933
+ msg = (
934
+ f"error while parsing {file}; malformed line {line!r}"
1005
935
  )
1006
- if inode in inodes: # noqa
936
+ raise RuntimeError(msg) # noqa: B904
937
+ if inode in inodes: # noqa: SIM108
1007
938
  # With UNIX sockets we can have a single inode
1008
939
  # referencing many file descriptors.
1009
940
  pairs = inodes[inode]
@@ -1023,11 +954,6 @@ class NetConnections:
1023
954
  yield (fd, family, type_, path, raddr, status, pid)
1024
955
 
1025
956
  def retrieve(self, kind, pid=None):
1026
- if kind not in self.tmap:
1027
- raise ValueError(
1028
- "invalid %r kind argument; choose between %s"
1029
- % (kind, ', '.join([repr(x) for x in self.tmap]))
1030
- )
1031
957
  self._procfs_path = get_procfs_path()
1032
958
  if pid is not None:
1033
959
  inodes = self.get_proc_inodes(pid)
@@ -1038,7 +964,7 @@ class NetConnections:
1038
964
  inodes = self.get_all_inodes()
1039
965
  ret = set()
1040
966
  for proto_name, family, type_ in self.tmap[kind]:
1041
- path = "%s/net/%s" % (self._procfs_path, proto_name)
967
+ path = f"{self._procfs_path}/net/{proto_name}"
1042
968
  if family in {socket.AF_INET, socket.AF_INET6}:
1043
969
  ls = self.process_inet(
1044
970
  path, family, type_, inodes, filter_pid=pid
@@ -1070,7 +996,7 @@ def net_io_counters():
1070
996
  """Return network I/O statistics for every network interface
1071
997
  installed on the system as a dict of raw tuples.
1072
998
  """
1073
- with open_text("%s/net/dev" % get_procfs_path()) as f:
999
+ with open_text(f"{get_procfs_path()}/net/dev") as f:
1074
1000
  lines = f.readlines()
1075
1001
  retdict = {}
1076
1002
  for line in lines[2:]:
@@ -1131,8 +1057,7 @@ def net_if_stats():
1131
1057
  # https://github.com/giampaolo/psutil/issues/1279
1132
1058
  if err.errno != errno.ENODEV:
1133
1059
  raise
1134
- else:
1135
- debug(err)
1060
+ debug(err)
1136
1061
  else:
1137
1062
  output_flags = ','.join(flags)
1138
1063
  isup = 'running' in flags
@@ -1172,7 +1097,7 @@ def disk_io_counters(perdisk=False):
1172
1097
  # See:
1173
1098
  # https://www.kernel.org/doc/Documentation/iostats.txt
1174
1099
  # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
1175
- with open_text("%s/diskstats" % get_procfs_path()) as f:
1100
+ with open_text(f"{get_procfs_path()}/diskstats") as f:
1176
1101
  lines = f.readlines()
1177
1102
  for line in lines:
1178
1103
  fields = line.split()
@@ -1195,7 +1120,8 @@ def disk_io_counters(perdisk=False):
1195
1120
  reads, rbytes, writes, wbytes = map(int, fields[3:])
1196
1121
  rtime = wtime = reads_merged = writes_merged = busy_time = 0
1197
1122
  else:
1198
- raise ValueError("not sure how to interpret line %r" % line)
1123
+ msg = f"not sure how to interpret line {line!r}"
1124
+ raise ValueError(msg)
1199
1125
  yield (name, reads, writes, rbytes, wbytes, rtime, wtime,
1200
1126
  reads_merged, writes_merged, busy_time)
1201
1127
  # fmt: on
@@ -1215,16 +1141,16 @@ def disk_io_counters(perdisk=False):
1215
1141
  wtime, reads_merged, writes_merged, busy_time)
1216
1142
  # fmt: on
1217
1143
 
1218
- if os.path.exists('%s/diskstats' % get_procfs_path()):
1144
+ if os.path.exists(f"{get_procfs_path()}/diskstats"):
1219
1145
  gen = read_procfs()
1220
1146
  elif os.path.exists('/sys/block'):
1221
1147
  gen = read_sysfs()
1222
1148
  else:
1223
- raise NotImplementedError(
1224
- "%s/diskstats nor /sys/block filesystem are available on this "
1225
- "system"
1226
- % get_procfs_path()
1149
+ msg = (
1150
+ f"{get_procfs_path()}/diskstats nor /sys/block are available on"
1151
+ " this system"
1227
1152
  )
1153
+ raise NotImplementedError(msg)
1228
1154
 
1229
1155
  retdict = {}
1230
1156
  for entry in gen:
@@ -1270,7 +1196,7 @@ class RootFsDeviceFinder:
1270
1196
  self.minor = os.minor(dev)
1271
1197
 
1272
1198
  def ask_proc_partitions(self):
1273
- with open_text("%s/partitions" % get_procfs_path()) as f:
1199
+ with open_text(f"{get_procfs_path()}/partitions") as f:
1274
1200
  for line in f.readlines()[2:]:
1275
1201
  fields = line.split()
1276
1202
  if len(fields) < 4: # just for extra safety
@@ -1280,19 +1206,19 @@ class RootFsDeviceFinder:
1280
1206
  name = fields[3]
1281
1207
  if major == self.major and minor == self.minor:
1282
1208
  if name: # just for extra safety
1283
- return "/dev/%s" % name
1209
+ return f"/dev/{name}"
1284
1210
 
1285
1211
  def ask_sys_dev_block(self):
1286
- path = "/sys/dev/block/%s:%s/uevent" % (self.major, self.minor)
1212
+ path = f"/sys/dev/block/{self.major}:{self.minor}/uevent"
1287
1213
  with open_text(path) as f:
1288
1214
  for line in f:
1289
1215
  if line.startswith("DEVNAME="):
1290
1216
  name = line.strip().rpartition("DEVNAME=")[2]
1291
1217
  if name: # just for extra safety
1292
- return "/dev/%s" % name
1218
+ return f"/dev/{name}"
1293
1219
 
1294
1220
  def ask_sys_class_block(self):
1295
- needle = "%s:%s" % (self.major, self.minor)
1221
+ needle = f"{self.major}:{self.minor}"
1296
1222
  files = glob.iglob("/sys/class/block/*/dev")
1297
1223
  for file in files:
1298
1224
  try:
@@ -1304,24 +1230,24 @@ class RootFsDeviceFinder:
1304
1230
  data = f.read().strip()
1305
1231
  if data == needle:
1306
1232
  name = os.path.basename(os.path.dirname(file))
1307
- return "/dev/%s" % name
1233
+ return f"/dev/{name}"
1308
1234
 
1309
1235
  def find(self):
1310
1236
  path = None
1311
1237
  if path is None:
1312
1238
  try:
1313
1239
  path = self.ask_proc_partitions()
1314
- except (IOError, OSError) as err:
1240
+ except OSError as err:
1315
1241
  debug(err)
1316
1242
  if path is None:
1317
1243
  try:
1318
1244
  path = self.ask_sys_dev_block()
1319
- except (IOError, OSError) as err:
1245
+ except OSError as err:
1320
1246
  debug(err)
1321
1247
  if path is None:
1322
1248
  try:
1323
1249
  path = self.ask_sys_class_block()
1324
- except (IOError, OSError) as err:
1250
+ except OSError as err:
1325
1251
  debug(err)
1326
1252
  # We use exists() because the "/dev/*" part of the path is hard
1327
1253
  # coded, so we want to be sure.
@@ -1334,7 +1260,7 @@ def disk_partitions(all=False):
1334
1260
  fstypes = set()
1335
1261
  procfs_path = get_procfs_path()
1336
1262
  if not all:
1337
- with open_text("%s/filesystems" % procfs_path) as f:
1263
+ with open_text(f"{procfs_path}/filesystems") as f:
1338
1264
  for line in f:
1339
1265
  line = line.strip()
1340
1266
  if not line.startswith("nodev"):
@@ -1349,7 +1275,7 @@ def disk_partitions(all=False):
1349
1275
  if procfs_path == "/proc" and os.path.isfile('/etc/mtab'):
1350
1276
  mounts_path = os.path.realpath("/etc/mtab")
1351
1277
  else:
1352
- mounts_path = os.path.realpath("%s/self/mounts" % procfs_path)
1278
+ mounts_path = os.path.realpath(f"{procfs_path}/self/mounts")
1353
1279
 
1354
1280
  retlist = []
1355
1281
  partitions = cext.disk_partitions(mounts_path)
@@ -1392,7 +1318,7 @@ def sensors_temperatures():
1392
1318
  # https://github.com/giampaolo/psutil/issues/971
1393
1319
  # https://github.com/nicolargo/glances/issues/1060
1394
1320
  basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*'))
1395
- basenames = sorted(set([x.split('_')[0] for x in basenames]))
1321
+ basenames = sorted({x.split('_')[0] for x in basenames})
1396
1322
 
1397
1323
  # Only add the coretemp hwmon entries if they're not already in
1398
1324
  # /sys/class/hwmon/
@@ -1401,7 +1327,7 @@ def sensors_temperatures():
1401
1327
  basenames2 = glob.glob(
1402
1328
  '/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*'
1403
1329
  )
1404
- repl = re.compile('/sys/devices/platform/coretemp.*/hwmon/')
1330
+ repl = re.compile(r"/sys/devices/platform/coretemp.*/hwmon/")
1405
1331
  for name in basenames2:
1406
1332
  altname = repl.sub('/sys/class/hwmon/', name)
1407
1333
  if altname not in basenames:
@@ -1413,7 +1339,7 @@ def sensors_temperatures():
1413
1339
  current = float(bcat(path)) / 1000.0
1414
1340
  path = os.path.join(os.path.dirname(base), 'name')
1415
1341
  unit_name = cat(path).strip()
1416
- except (IOError, OSError, ValueError):
1342
+ except (OSError, ValueError):
1417
1343
  # A lot of things can go wrong here, so let's just skip the
1418
1344
  # whole entry. Sure thing is Linux's /sys/class/hwmon really
1419
1345
  # is a stinky broken mess.
@@ -1452,15 +1378,15 @@ def sensors_temperatures():
1452
1378
  current = float(bcat(path)) / 1000.0
1453
1379
  path = os.path.join(base, 'type')
1454
1380
  unit_name = cat(path).strip()
1455
- except (IOError, OSError, ValueError) as err:
1381
+ except (OSError, ValueError) as err:
1456
1382
  debug(err)
1457
1383
  continue
1458
1384
 
1459
1385
  trip_paths = glob.glob(base + '/trip_point*')
1460
- trip_points = set([
1386
+ trip_points = {
1461
1387
  '_'.join(os.path.basename(p).split('_')[0:3])
1462
1388
  for p in trip_paths
1463
- ])
1389
+ }
1464
1390
  critical = None
1465
1391
  high = None
1466
1392
  for trip_point in trip_points:
@@ -1508,11 +1434,11 @@ def sensors_fans():
1508
1434
  # https://github.com/giampaolo/psutil/issues/971
1509
1435
  basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*')
1510
1436
 
1511
- basenames = sorted(set([x.split('_')[0] for x in basenames]))
1437
+ basenames = sorted({x.split("_")[0] for x in basenames})
1512
1438
  for base in basenames:
1513
1439
  try:
1514
1440
  current = int(bcat(base + '_input'))
1515
- except (IOError, OSError) as err:
1441
+ except OSError as err:
1516
1442
  debug(err)
1517
1443
  continue
1518
1444
  unit_name = cat(os.path.join(os.path.dirname(base), 'name')).strip()
@@ -1554,7 +1480,7 @@ def sensors_battery():
1554
1480
  # Get the first available battery. Usually this is "BAT0", except
1555
1481
  # some rare exceptions:
1556
1482
  # https://github.com/giampaolo/psutil/issues/1238
1557
- root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0])
1483
+ root = os.path.join(POWER_SUPPLY_PATH, min(bats))
1558
1484
 
1559
1485
  # Base metrics.
1560
1486
  energy_now = multi_bcat(root + "/energy_now", root + "/charge_now")
@@ -1631,14 +1557,15 @@ def users():
1631
1557
  def boot_time():
1632
1558
  """Return the system boot time expressed in seconds since the epoch."""
1633
1559
  global BOOT_TIME
1634
- path = '%s/stat' % get_procfs_path()
1560
+ path = f"{get_procfs_path()}/stat"
1635
1561
  with open_binary(path) as f:
1636
1562
  for line in f:
1637
1563
  if line.startswith(b'btime'):
1638
1564
  ret = float(line.strip().split()[1])
1639
1565
  BOOT_TIME = ret
1640
1566
  return ret
1641
- raise RuntimeError("line 'btime' not found in %s" % path)
1567
+ msg = f"line 'btime' not found in {path}"
1568
+ raise RuntimeError(msg)
1642
1569
 
1643
1570
 
1644
1571
  # =====================================================================
@@ -1648,7 +1575,8 @@ def boot_time():
1648
1575
 
1649
1576
  def pids():
1650
1577
  """Returns a list of PIDs currently running on the system."""
1651
- return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()]
1578
+ path = get_procfs_path().encode(ENCODING)
1579
+ return [int(x) for x in os.listdir(path) if x.isdigit()]
1652
1580
 
1653
1581
 
1654
1582
  def pid_exists(pid):
@@ -1670,7 +1598,7 @@ def pid_exists(pid):
1670
1598
  # Note: already checked that this is faster than using a
1671
1599
  # regular expr. Also (a lot) faster than doing
1672
1600
  # 'return pid in pids()'
1673
- path = "%s/%s/status" % (get_procfs_path(), pid)
1601
+ path = f"{get_procfs_path()}/{pid}/status"
1674
1602
  with open_binary(path) as f:
1675
1603
  for line in f:
1676
1604
  if line.startswith(b"Tgid:"):
@@ -1678,8 +1606,9 @@ def pid_exists(pid):
1678
1606
  # If tgid and pid are the same then we're
1679
1607
  # dealing with a process PID.
1680
1608
  return tgid == pid
1681
- raise ValueError("'Tgid' line not found in %s" % path)
1682
- except (EnvironmentError, ValueError):
1609
+ msg = f"'Tgid' line not found in {path}"
1610
+ raise ValueError(msg)
1611
+ except (OSError, ValueError):
1683
1612
  return pid in pids()
1684
1613
 
1685
1614
 
@@ -1691,7 +1620,7 @@ def ppid_map():
1691
1620
  procfs_path = get_procfs_path()
1692
1621
  for pid in pids():
1693
1622
  try:
1694
- with open_binary("%s/%s/stat" % (procfs_path, pid)) as f:
1623
+ with open_binary(f"{procfs_path}/{pid}/stat") as f:
1695
1624
  data = f.read()
1696
1625
  except (FileNotFoundError, ProcessLookupError):
1697
1626
  # Note: we should be able to access /stat for all processes
@@ -1706,28 +1635,27 @@ def ppid_map():
1706
1635
 
1707
1636
 
1708
1637
  def wrap_exceptions(fun):
1709
- """Decorator which translates bare OSError and IOError exceptions
1638
+ """Decorator which translates bare OSError and OSError exceptions
1710
1639
  into NoSuchProcess and AccessDenied.
1711
1640
  """
1712
1641
 
1713
1642
  @functools.wraps(fun)
1714
1643
  def wrapper(self, *args, **kwargs):
1644
+ pid, name = self.pid, self._name
1715
1645
  try:
1716
1646
  return fun(self, *args, **kwargs)
1717
- except PermissionError:
1718
- raise AccessDenied(self.pid, self._name)
1719
- except ProcessLookupError:
1647
+ except PermissionError as err:
1648
+ raise AccessDenied(pid, name) from err
1649
+ except ProcessLookupError as err:
1720
1650
  self._raise_if_zombie()
1721
- raise NoSuchProcess(self.pid, self._name)
1722
- except FileNotFoundError:
1651
+ raise NoSuchProcess(pid, name) from err
1652
+ except FileNotFoundError as err:
1723
1653
  self._raise_if_zombie()
1724
1654
  # /proc/PID directory may still exist, but the files within
1725
1655
  # it may not, indicating the process is gone, see:
1726
1656
  # https://github.com/giampaolo/psutil/issues/2418
1727
- if not os.path.exists(
1728
- "%s/%s/stat" % (self._procfs_path, self.pid)
1729
- ):
1730
- raise NoSuchProcess(self.pid, self._name)
1657
+ if not os.path.exists(f"{self._procfs_path}/{pid}/stat"):
1658
+ raise NoSuchProcess(pid, name) from err
1731
1659
  raise
1732
1660
 
1733
1661
  return wrapper
@@ -1752,8 +1680,8 @@ class Process:
1752
1680
  # it's empty. Instead of returning a "null" value we'll raise an
1753
1681
  # exception.
1754
1682
  try:
1755
- data = bcat("%s/%s/stat" % (self._procfs_path, self.pid))
1756
- except (IOError, OSError):
1683
+ data = bcat(f"{self._procfs_path}/{self.pid}/stat")
1684
+ except OSError:
1757
1685
  return False
1758
1686
  else:
1759
1687
  rpar = data.rfind(b')')
@@ -1768,7 +1696,7 @@ class Process:
1768
1696
  """Raise NSP if the process disappeared on us."""
1769
1697
  # For those C function who do not raise NSP, possibly returning
1770
1698
  # incorrect or incomplete result.
1771
- os.stat('%s/%s' % (self._procfs_path, self.pid))
1699
+ os.stat(f"{self._procfs_path}/{self.pid}")
1772
1700
 
1773
1701
  @wrap_exceptions
1774
1702
  @memoize_when_activated
@@ -1781,7 +1709,7 @@ class Process:
1781
1709
  The return value is cached in case oneshot() ctx manager is
1782
1710
  in use.
1783
1711
  """
1784
- data = bcat("%s/%s/stat" % (self._procfs_path, self.pid))
1712
+ data = bcat(f"{self._procfs_path}/{self.pid}/stat")
1785
1713
  # Process name is between parentheses. It can contain spaces and
1786
1714
  # other parentheses. This is taken into account by looking for
1787
1715
  # the first occurrence of "(" and the last occurrence of ")".
@@ -1816,13 +1744,13 @@ class Process:
1816
1744
  The return value is cached in case oneshot() ctx manager is
1817
1745
  in use.
1818
1746
  """
1819
- with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f:
1747
+ with open_binary(f"{self._procfs_path}/{self.pid}/status") as f:
1820
1748
  return f.read()
1821
1749
 
1822
1750
  @wrap_exceptions
1823
1751
  @memoize_when_activated
1824
1752
  def _read_smaps_file(self):
1825
- with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid)) as f:
1753
+ with open_binary(f"{self._procfs_path}/{self.pid}/smaps") as f:
1826
1754
  return f.read().strip()
1827
1755
 
1828
1756
  def oneshot_enter(self):
@@ -1837,28 +1765,25 @@ class Process:
1837
1765
 
1838
1766
  @wrap_exceptions
1839
1767
  def name(self):
1840
- name = self._parse_stat_file()['name']
1841
- if PY3:
1842
- name = decode(name)
1843
1768
  # XXX - gets changed later and probably needs refactoring
1844
- return name
1769
+ return decode(self._parse_stat_file()['name'])
1845
1770
 
1846
1771
  @wrap_exceptions
1847
1772
  def exe(self):
1848
1773
  try:
1849
- return readlink("%s/%s/exe" % (self._procfs_path, self.pid))
1774
+ return readlink(f"{self._procfs_path}/{self.pid}/exe")
1850
1775
  except (FileNotFoundError, ProcessLookupError):
1851
1776
  self._raise_if_zombie()
1852
1777
  # no such file error; might be raised also if the
1853
1778
  # path actually exists for system processes with
1854
1779
  # low pids (about 0-20)
1855
- if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
1780
+ if os.path.lexists(f"{self._procfs_path}/{self.pid}"):
1856
1781
  return ""
1857
1782
  raise
1858
1783
 
1859
1784
  @wrap_exceptions
1860
1785
  def cmdline(self):
1861
- with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f:
1786
+ with open_text(f"{self._procfs_path}/{self.pid}/cmdline") as f:
1862
1787
  data = f.read()
1863
1788
  if not data:
1864
1789
  # may happen in case of zombie process
@@ -1884,7 +1809,7 @@ class Process:
1884
1809
 
1885
1810
  @wrap_exceptions
1886
1811
  def environ(self):
1887
- with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f:
1812
+ with open_text(f"{self._procfs_path}/{self.pid}/environ") as f:
1888
1813
  data = f.read()
1889
1814
  return parse_environ_block(data)
1890
1815
 
@@ -1898,11 +1823,11 @@ class Process:
1898
1823
  return None
1899
1824
 
1900
1825
  # May not be available on old kernels.
1901
- if os.path.exists('/proc/%s/io' % os.getpid()):
1826
+ if os.path.exists(f"/proc/{os.getpid()}/io"):
1902
1827
 
1903
1828
  @wrap_exceptions
1904
1829
  def io_counters(self):
1905
- fname = "%s/%s/io" % (self._procfs_path, self.pid)
1830
+ fname = f"{self._procfs_path}/{self.pid}/io"
1906
1831
  fields = {}
1907
1832
  with open_binary(fname) as f:
1908
1833
  for line in f:
@@ -1917,7 +1842,8 @@ class Process:
1917
1842
  else:
1918
1843
  fields[name] = int(value)
1919
1844
  if not fields:
1920
- raise RuntimeError("%s file was empty" % fname)
1845
+ msg = f"{fname} file was empty"
1846
+ raise RuntimeError(msg)
1921
1847
  try:
1922
1848
  return pio(
1923
1849
  fields[b'syscr'], # read syscalls
@@ -1928,10 +1854,11 @@ class Process:
1928
1854
  fields[b'wchar'], # write chars
1929
1855
  )
1930
1856
  except KeyError as err:
1931
- raise ValueError(
1932
- "%r field was not found in %s; found fields are %r"
1933
- % (err.args[0], fname, fields)
1857
+ msg = (
1858
+ f"{err.args[0]!r} field was not found in {fname}; found"
1859
+ f" fields are {fields!r}"
1934
1860
  )
1861
+ raise ValueError(msg) from None
1935
1862
 
1936
1863
  @wrap_exceptions
1937
1864
  def cpu_times(self):
@@ -1976,7 +1903,7 @@ class Process:
1976
1903
  # | data | data + stack | drs | DATA |
1977
1904
  # | dirty | dirty pages (unused in Linux 2.6) | dt | |
1978
1905
  # ============================================================
1979
- with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f:
1906
+ with open_binary(f"{self._procfs_path}/{self.pid}/statm") as f:
1980
1907
  vms, rss, shared, text, lib, data, dirty = (
1981
1908
  int(x) * PAGESIZE for x in f.readline().split()[:7]
1982
1909
  )
@@ -1995,7 +1922,7 @@ class Process:
1995
1922
  # compared to /proc/pid/smaps_rollup.
1996
1923
  uss = pss = swap = 0
1997
1924
  with open_binary(
1998
- "{}/{}/smaps_rollup".format(self._procfs_path, self.pid)
1925
+ f"{self._procfs_path}/{self.pid}/smaps_rollup"
1999
1926
  ) as f:
2000
1927
  for line in f:
2001
1928
  if line.startswith(b"Private_"):
@@ -2020,8 +1947,6 @@ class Process:
2020
1947
 
2021
1948
  # Note: using 3 regexes is faster than reading the file
2022
1949
  # line by line.
2023
- # XXX: on Python 3 the 2 regexes are 30% slower than on
2024
- # Python 2 though. Figure out why.
2025
1950
  #
2026
1951
  # You might be tempted to calculate USS by subtracting
2027
1952
  # the "shared" value from the "resident" value in
@@ -2059,7 +1984,7 @@ class Process:
2059
1984
  def memory_maps(self):
2060
1985
  """Return process's mapped memory regions as a list of named
2061
1986
  tuples. Fields are explained in 'man proc'; here is an updated
2062
- (Apr 2012) version: http://goo.gl/fmebo.
1987
+ (Apr 2012) version: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt?id=b76437579d1344b612cf1851ae610c636cec7db0.
2063
1988
 
2064
1989
  /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if
2065
1990
  CONFIG_MMU kernel configuration option is not enabled.
@@ -2080,11 +2005,8 @@ class Process:
2080
2005
  if fields[0].startswith(b'VmFlags:'):
2081
2006
  # see issue #369
2082
2007
  continue
2083
- else:
2084
- raise ValueError(
2085
- "don't know how to interpret line %r"
2086
- % line
2087
- )
2008
+ msg = f"don't know how to interpret line {line!r}"
2009
+ raise ValueError(msg) from None
2088
2010
  yield (current_block.pop(), data)
2089
2011
 
2090
2012
  data = self._read_smaps_file()
@@ -2106,8 +2028,7 @@ class Process:
2106
2028
  if not path:
2107
2029
  path = '[anon]'
2108
2030
  else:
2109
- if PY3:
2110
- path = decode(path)
2031
+ path = decode(path)
2111
2032
  path = path.strip()
2112
2033
  if path.endswith(' (deleted)') and not path_exists_strict(
2113
2034
  path
@@ -2133,7 +2054,7 @@ class Process:
2133
2054
 
2134
2055
  @wrap_exceptions
2135
2056
  def cwd(self):
2136
- return readlink("%s/%s/cwd" % (self._procfs_path, self.pid))
2057
+ return readlink(f"{self._procfs_path}/{self.pid}/cwd")
2137
2058
 
2138
2059
  @wrap_exceptions
2139
2060
  def num_ctx_switches(
@@ -2142,34 +2063,29 @@ class Process:
2142
2063
  data = self._read_status_file()
2143
2064
  ctxsw = _ctxsw_re.findall(data)
2144
2065
  if not ctxsw:
2145
- raise NotImplementedError(
2146
- "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'"
2147
- "lines were not found in %s/%s/status; the kernel is "
2148
- "probably older than 2.6.23" % (self._procfs_path, self.pid)
2066
+ msg = (
2067
+ "'voluntary_ctxt_switches' and"
2068
+ " 'nonvoluntary_ctxt_switches'lines were not found in"
2069
+ f" {self._procfs_path}/{self.pid}/status; the kernel is"
2070
+ " probably older than 2.6.23"
2149
2071
  )
2150
- else:
2151
- return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1]))
2072
+ raise NotImplementedError(msg)
2073
+ return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1]))
2152
2074
 
2153
2075
  @wrap_exceptions
2154
2076
  def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')):
2155
- # Note: on Python 3 using a re is faster than iterating over file
2156
- # line by line. On Python 2 is the exact opposite, and iterating
2157
- # over a file on Python 3 is slower than on Python 2.
2077
+ # Using a re is faster than iterating over file line by line.
2158
2078
  data = self._read_status_file()
2159
2079
  return int(_num_threads_re.findall(data)[0])
2160
2080
 
2161
2081
  @wrap_exceptions
2162
2082
  def threads(self):
2163
- thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid))
2083
+ thread_ids = os.listdir(f"{self._procfs_path}/{self.pid}/task")
2164
2084
  thread_ids.sort()
2165
2085
  retlist = []
2166
2086
  hit_enoent = False
2167
2087
  for thread_id in thread_ids:
2168
- fname = "%s/%s/task/%s/stat" % (
2169
- self._procfs_path,
2170
- self.pid,
2171
- thread_id,
2172
- )
2088
+ fname = f"{self._procfs_path}/{self.pid}/task/{thread_id}/stat"
2173
2089
  try:
2174
2090
  with open_binary(fname) as f:
2175
2091
  st = f.read().strip()
@@ -2191,7 +2107,7 @@ class Process:
2191
2107
 
2192
2108
  @wrap_exceptions
2193
2109
  def nice_get(self):
2194
- # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f:
2110
+ # with open_text(f"{self._procfs_path}/{self.pid}/stat") as f:
2195
2111
  # data = f.read()
2196
2112
  # return int(data.split()[18])
2197
2113
 
@@ -2230,15 +2146,17 @@ class Process:
2230
2146
  all_cpus = tuple(range(len(per_cpu_times())))
2231
2147
  for cpu in cpus:
2232
2148
  if cpu not in all_cpus:
2233
- raise ValueError(
2234
- "invalid CPU number %r; choose between %s"
2235
- % (cpu, eligible_cpus)
2149
+ msg = (
2150
+ f"invalid CPU {cpu!r}; choose between"
2151
+ f" {eligible_cpus!r}"
2236
2152
  )
2153
+ raise ValueError(msg) from None
2237
2154
  if cpu not in eligible_cpus:
2238
- raise ValueError(
2239
- "CPU number %r is not eligible; choose "
2240
- "between %s" % (cpu, eligible_cpus)
2155
+ msg = (
2156
+ f"CPU number {cpu} is not eligible; choose"
2157
+ f" between {eligible_cpus}"
2241
2158
  )
2159
+ raise ValueError(msg) from err
2242
2160
  raise
2243
2161
 
2244
2162
  # only starting from kernel 2.6.13
@@ -2247,22 +2165,25 @@ class Process:
2247
2165
  @wrap_exceptions
2248
2166
  def ionice_get(self):
2249
2167
  ioclass, value = cext.proc_ioprio_get(self.pid)
2250
- if enum is not None:
2251
- ioclass = IOPriority(ioclass)
2168
+ ioclass = IOPriority(ioclass)
2252
2169
  return _common.pionice(ioclass, value)
2253
2170
 
2254
2171
  @wrap_exceptions
2255
2172
  def ionice_set(self, ioclass, value):
2256
2173
  if value is None:
2257
2174
  value = 0
2258
- if value and ioclass in {IOPRIO_CLASS_IDLE, IOPRIO_CLASS_NONE}:
2259
- raise ValueError("%r ioclass accepts no value" % ioclass)
2175
+ if value and ioclass in {
2176
+ IOPriority.IOPRIO_CLASS_IDLE,
2177
+ IOPriority.IOPRIO_CLASS_NONE,
2178
+ }:
2179
+ msg = f"{ioclass!r} ioclass accepts no value"
2180
+ raise ValueError(msg)
2260
2181
  if value < 0 or value > 7:
2261
2182
  msg = "value not in 0-7 range"
2262
2183
  raise ValueError(msg)
2263
2184
  return cext.proc_ioprio_set(self.pid, ioclass, value)
2264
2185
 
2265
- if prlimit is not None:
2186
+ if hasattr(resource, "prlimit"):
2266
2187
 
2267
2188
  @wrap_exceptions
2268
2189
  def rlimit(self, resource_, limits=None):
@@ -2275,16 +2196,16 @@ class Process:
2275
2196
  try:
2276
2197
  if limits is None:
2277
2198
  # get
2278
- return prlimit(self.pid, resource_)
2199
+ return resource.prlimit(self.pid, resource_)
2279
2200
  else:
2280
2201
  # set
2281
2202
  if len(limits) != 2:
2282
2203
  msg = (
2283
2204
  "second argument must be a (soft, hard) "
2284
- + "tuple, got %s" % repr(limits)
2205
+ f"tuple, got {limits!r}"
2285
2206
  )
2286
2207
  raise ValueError(msg)
2287
- prlimit(self.pid, resource_, limits)
2208
+ resource.prlimit(self.pid, resource_, limits)
2288
2209
  except OSError as err:
2289
2210
  if err.errno == errno.ENOSYS:
2290
2211
  # I saw this happening on Travis:
@@ -2295,18 +2216,17 @@ class Process:
2295
2216
  @wrap_exceptions
2296
2217
  def status(self):
2297
2218
  letter = self._parse_stat_file()['status']
2298
- if PY3:
2299
- letter = letter.decode()
2219
+ letter = letter.decode()
2300
2220
  # XXX is '?' legit? (we're not supposed to return it anyway)
2301
2221
  return PROC_STATUSES.get(letter, '?')
2302
2222
 
2303
2223
  @wrap_exceptions
2304
2224
  def open_files(self):
2305
2225
  retlist = []
2306
- files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))
2226
+ files = os.listdir(f"{self._procfs_path}/{self.pid}/fd")
2307
2227
  hit_enoent = False
2308
2228
  for fd in files:
2309
- file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd)
2229
+ file = f"{self._procfs_path}/{self.pid}/fd/{fd}"
2310
2230
  try:
2311
2231
  path = readlink(file)
2312
2232
  except (FileNotFoundError, ProcessLookupError):
@@ -2329,11 +2249,7 @@ class Process:
2329
2249
  # absolute path though.
2330
2250
  if path.startswith('/') and isfile_strict(path):
2331
2251
  # Get file position and flags.
2332
- file = "%s/%s/fdinfo/%s" % (
2333
- self._procfs_path,
2334
- self.pid,
2335
- fd,
2336
- )
2252
+ file = f"{self._procfs_path}/{self.pid}/fdinfo/{fd}"
2337
2253
  try:
2338
2254
  with open_binary(file) as f:
2339
2255
  pos = int(f.readline().split()[1])
@@ -2360,7 +2276,7 @@ class Process:
2360
2276
 
2361
2277
  @wrap_exceptions
2362
2278
  def num_fds(self):
2363
- return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)))
2279
+ return len(os.listdir(f"{self._procfs_path}/{self.pid}/fd"))
2364
2280
 
2365
2281
  @wrap_exceptions
2366
2282
  def ppid(self):