py2docfx 0.1.20.dev2245077__py3-none-any.whl → 0.1.20.dev2245492__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 (36) 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/venv/venv1/Lib/site-packages/psutil/__init__.py +39 -19
  7. py2docfx/venv/venv1/Lib/site-packages/psutil/_common.py +3 -5
  8. py2docfx/venv/venv1/Lib/site-packages/psutil/_psaix.py +1 -2
  9. py2docfx/venv/venv1/Lib/site-packages/psutil/_psbsd.py +53 -78
  10. py2docfx/venv/venv1/Lib/site-packages/psutil/_pslinux.py +55 -38
  11. py2docfx/venv/venv1/Lib/site-packages/psutil/_psosx.py +40 -12
  12. py2docfx/venv/venv1/Lib/site-packages/psutil/_psposix.py +0 -1
  13. py2docfx/venv/venv1/Lib/site-packages/psutil/_pssunos.py +1 -2
  14. py2docfx/venv/venv1/Lib/site-packages/psutil/_pswindows.py +33 -13
  15. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__init__.py +185 -122
  16. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/__main__.py +2 -3
  17. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_bsd.py +5 -10
  18. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_connections.py +3 -4
  19. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_contracts.py +41 -45
  20. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_linux.py +35 -38
  21. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_memleaks.py +4 -8
  22. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_misc.py +6 -12
  23. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_osx.py +17 -8
  24. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_posix.py +29 -17
  25. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process.py +74 -75
  26. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_process_all.py +11 -13
  27. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_scripts.py +2 -3
  28. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_sudo.py +117 -0
  29. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_system.py +21 -31
  30. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_testutils.py +23 -23
  31. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_unicode.py +15 -8
  32. py2docfx/venv/venv1/Lib/site-packages/psutil/tests/test_windows.py +65 -33
  33. {py2docfx-0.1.20.dev2245077.dist-info → py2docfx-0.1.20.dev2245492.dist-info}/METADATA +1 -1
  34. {py2docfx-0.1.20.dev2245077.dist-info → py2docfx-0.1.20.dev2245492.dist-info}/RECORD +36 -35
  35. {py2docfx-0.1.20.dev2245077.dist-info → py2docfx-0.1.20.dev2245492.dist-info}/WHEEL +0 -0
  36. {py2docfx-0.1.20.dev2245077.dist-info → py2docfx-0.1.20.dev2245492.dist-info}/top_level.txt +0 -0
@@ -54,7 +54,7 @@ def update_package_info(executable: str, pkg: PackageInfo, source_folder: str):
54
54
  for meta_info in metadata:
55
55
  meta_info_array = meta_info.split(":")
56
56
  meta_field = meta_info_array[0].strip().lower()
57
- if meta_field in attrs:
57
+ if meta_field in attrs and not hasattr(pkg, meta_field):
58
58
  setattr(
59
59
  pkg,
60
60
  meta_field,
@@ -13,7 +13,7 @@ class PackageInfo:
13
13
  path: Source
14
14
  def __init__(self) -> None:
15
15
  pass
16
-
16
+
17
17
  @classmethod
18
18
  def report_error(cls, name, value, condition=None):
19
19
  py2docfx_logger = get_logger(__name__)
@@ -53,6 +53,7 @@ class PackageInfo:
53
53
 
54
54
  package_info.version = package_info_dict.get("version", None)
55
55
  package_info.extra_index_url = package_info_dict.get("extra_index_url", None)
56
+ package_info.extras = package_info_dict.get("extras", [])
56
57
 
57
58
  if package_info.install_type == cls.InstallType.SOURCE_CODE:
58
59
  package_info.url = package_info_dict.get("url", None)
@@ -93,56 +94,65 @@ class PackageInfo:
93
94
  return package_info
94
95
 
95
96
  def get_combined_name_version(self):
96
- if not self.version:
97
- return self.name
98
- elif re.match("^(<|>|<=|>=|==).+$", self.version.strip()):
99
- return self.name.strip() + self.version.strip()
100
- else:
101
- return f"{self.name.strip()}=={self.version.strip()}"
97
+ base_name = (
98
+ f"{self.name}[{','.join(extras)}]"
99
+ if (extras := getattr(self, "extras", []))
100
+ else self.name
101
+ )
102
102
 
103
- def get_install_command(self) -> (str, []):
104
- packageInstallName = ""
105
- pipInstallExtraOptions = []
103
+ version = getattr(self, "version", None)
104
+ if not version:
105
+ return base_name
106
+ elif re.match("^(<|>|<=|>=|==).+$", version.strip()):
107
+ return base_name.strip() + version.strip()
108
+ else:
109
+ return f"{base_name.strip()}=={version.strip()}"
106
110
 
111
+ def get_install_command(self) -> tuple[str, list]:
107
112
  if self.install_type == self.InstallType.DIST_FILE:
108
- if hasattr(self, "location") and self.location:
109
- packageInstallName = self.location
110
- else:
113
+ if not hasattr(self, "location") or not self.location:
111
114
  self.__class__.report_error(
112
115
  "location", "None", condition="When install_type is dist_file"
113
116
  )
117
+ return (
118
+ f"{self.location}[{','.join(extras)}]"
119
+ if (extras := getattr(self, "extras", None))
120
+ else self.location,
121
+ [],
122
+ )
114
123
 
115
- elif self.install_type == self.InstallType.PYPI:
124
+ if self.install_type == self.InstallType.PYPI:
116
125
  if not hasattr(self, "name") or not self.name:
117
126
  self.__class__.report_error(
118
127
  "name", "None", condition="When install_type is pypi"
119
128
  )
120
- if hasattr(self, "version") and self.version:
121
- packageInstallName = self.get_combined_name_version()
122
- else:
123
- packageInstallName = self.name
129
+ pipInstallExtraOptions = []
130
+ if not hasattr(self, "version") or self.version is None:
124
131
  pipInstallExtraOptions.append("--upgrade")
125
-
126
132
  if hasattr(self, "extra_index_url") and self.extra_index_url:
127
133
  pipInstallExtraOptions.extend(
128
134
  ["--extra-index-url", self.extra_index_url]
129
135
  )
136
+ return (self.get_combined_name_version(), pipInstallExtraOptions)
130
137
 
131
- elif self.install_type == self.InstallType.SOURCE_CODE:
132
- if hasattr(self, "path") and self.path.source_folder:
133
- packageInstallName = self.path.source_folder
134
- else:
138
+ if self.install_type == self.InstallType.SOURCE_CODE:
139
+ if not hasattr(self, "path") or not self.path.source_folder:
135
140
  self.__class__.report_error(
136
141
  "path.source_folder",
137
142
  "None",
138
143
  condition="When install_type is source_code",
139
144
  )
140
- else:
141
- self.__class__.report_error("install_type", self.install_type)
145
+ return (
146
+ f"{self.path.source_folder}[{','.join(extras)}]"
147
+ if (extras := getattr(self, "extras", None))
148
+ else self.path.source_folder,
149
+ [],
150
+ )
151
+
152
+ self.__class__.report_error("install_type", self.install_type)
142
153
 
143
- return (packageInstallName, pipInstallExtraOptions)
144
154
 
145
- def get_exluded_command(self) -> []:
155
+ def get_exluded_command(self) -> list:
146
156
  py2docfx_logger = get_logger(__name__)
147
157
  if hasattr(self, "path"):
148
158
  code_location = self.path.source_folder
@@ -50,8 +50,10 @@ def test_update_package_info(init_package_info):
50
50
  assert package.name == "dummy_package"
51
51
  assert package.version == "3.1.0"
52
52
 
53
- # case of metadata
53
+ # case of metadata, unly use metadata file as a fallback
54
54
  package = init_package_info
55
+ del package.name
56
+ del package.version
55
57
  get_source.update_package_info(sys.executable, package, os.path.join(base_path, "mock-2"))
56
58
  assert package.name == "mock_package"
57
59
  assert package.version == "2.2.0"
@@ -80,4 +80,162 @@ def test_get_exclude_command_check_extra_exclude(tmp_path):
80
80
  ]
81
81
  def form_exclude_path(raletive_path):
82
82
  return os.path.join(source_folder, raletive_path)
83
- assert exclude_path == [form_exclude_path(path) for path in expected_exclude_path]
83
+ assert exclude_path == [form_exclude_path(path) for path in expected_exclude_path]
84
+
85
+
86
+ def test_get_combined_name_version_with_extras():
87
+ """Test get_combined_name_version with extras"""
88
+ # Test package with extras but no version
89
+ test_data = {
90
+ "package_info": {
91
+ "install_type": "pypi",
92
+ "name": "test-package",
93
+ "extras": ["dev", "test"],
94
+ },
95
+ }
96
+ pkg = PackageInfo.parse_from(test_data)
97
+ assert pkg.get_combined_name_version() == "test-package[dev,test]"
98
+
99
+ # Test package with extras and version
100
+ test_data_with_version = {
101
+ "package_info": {
102
+ "install_type": "pypi",
103
+ "name": "test-package",
104
+ "version": "1.0.0",
105
+ "extras": ["dev", "test"],
106
+ },
107
+ }
108
+ pkg_with_version = PackageInfo.parse_from(test_data_with_version)
109
+ assert (
110
+ pkg_with_version.get_combined_name_version() == "test-package[dev,test]==1.0.0"
111
+ )
112
+
113
+ # Test package with extras and version operator
114
+ test_data_with_operator = {
115
+ "package_info": {
116
+ "install_type": "pypi",
117
+ "name": "test-package",
118
+ "version": ">=1.0.0",
119
+ "extras": ["dev"],
120
+ },
121
+ }
122
+ pkg_with_operator = PackageInfo.parse_from(test_data_with_operator)
123
+ assert pkg_with_operator.get_combined_name_version() == "test-package[dev]>=1.0.0"
124
+
125
+
126
+ def test_install_command_pypi_with_extras():
127
+ """Test get_install_command for PYPI packages with extras"""
128
+ # Test PYPI package with extras and version
129
+ test_data = {
130
+ "package_info": {
131
+ "install_type": "pypi",
132
+ "name": "test-package",
133
+ "version": "1.0.0",
134
+ "extras": ["dev", "test"],
135
+ },
136
+ }
137
+ pkg = PackageInfo.parse_from(test_data)
138
+ install_command = pkg.get_install_command()
139
+ assert install_command[0] == "test-package[dev,test]==1.0.0"
140
+ assert install_command[1] == []
141
+
142
+ # Test PYPI package with extras but no version (should get --upgrade)
143
+ test_data_no_version = {
144
+ "package_info": {
145
+ "install_type": "pypi",
146
+ "name": "test-package",
147
+ "extras": ["dev"],
148
+ },
149
+ }
150
+ pkg_no_version = PackageInfo.parse_from(test_data_no_version)
151
+ install_command = pkg_no_version.get_install_command()
152
+ assert install_command[0] == "test-package[dev]"
153
+ assert install_command[1] == ["--upgrade"]
154
+
155
+
156
+ def test_install_command_source_code_with_extras(tmp_path):
157
+ """Test get_install_command for SOURCE_CODE packages with extras"""
158
+ source_folder = os.path.join(tmp_path, "source_folder")
159
+ yaml_output_folder = os.path.join(tmp_path, "yaml_output_folder")
160
+
161
+ test_data = {
162
+ "package_info": {
163
+ "install_type": "source_code",
164
+ "name": "test-package",
165
+ "url": "https://github.com/test/test-package.git",
166
+ "extras": ["dev", "test"],
167
+ },
168
+ }
169
+ pkg = PackageInfo.parse_from(test_data)
170
+ pkg.path = Source(
171
+ source_folder=source_folder,
172
+ yaml_output_folder=yaml_output_folder,
173
+ package_name="test-package",
174
+ )
175
+
176
+ install_command = pkg.get_install_command()
177
+ assert install_command[0] == f"{source_folder}[dev,test]"
178
+ assert install_command[1] == []
179
+
180
+
181
+ def test_install_command_dist_file_with_extras():
182
+ """Test get_install_command for DIST_FILE packages with extras"""
183
+ test_data = {
184
+ "package_info": {
185
+ "install_type": "dist_file",
186
+ "location": "/path/to/package.whl",
187
+ "extras": ["dev"],
188
+ },
189
+ }
190
+ pkg = PackageInfo.parse_from(test_data)
191
+ install_command = pkg.get_install_command()
192
+ assert install_command[0] == "/path/to/package.whl[dev]"
193
+ assert install_command[1] == []
194
+
195
+
196
+ def test_install_command_without_extras():
197
+ """Test that packages without extras work as before"""
198
+ # Test PYPI package without extras
199
+ test_data = {
200
+ "package_info": {
201
+ "install_type": "pypi",
202
+ "name": "test-package",
203
+ "version": "1.0.0",
204
+ }
205
+ }
206
+ pkg = PackageInfo.parse_from(test_data)
207
+ install_command = pkg.get_install_command()
208
+ assert install_command[0] == "test-package==1.0.0"
209
+ assert install_command[1] == []
210
+
211
+
212
+ def test_install_command_empty_extras():
213
+ """Test that packages with empty extras list work correctly"""
214
+ test_data = {
215
+ "package_info": {
216
+ "install_type": "pypi",
217
+ "name": "test-package",
218
+ "version": "1.0.0",
219
+ "extras": [],
220
+ },
221
+ }
222
+ pkg = PackageInfo.parse_from(test_data)
223
+ install_command = pkg.get_install_command()
224
+ assert install_command[0] == "test-package==1.0.0"
225
+ assert install_command[1] == []
226
+
227
+
228
+ def test_install_command_single_extra():
229
+ """Test package with single extra"""
230
+ test_data = {
231
+ "package_info": {
232
+ "install_type": "pypi",
233
+ "name": "test-package",
234
+ "version": "1.0.0",
235
+ "extras": ["dev"],
236
+ },
237
+ }
238
+ pkg = PackageInfo.parse_from(test_data)
239
+ install_command = pkg.get_install_command()
240
+ assert install_command[0] == "test-package[dev]==1.0.0"
241
+ assert install_command[1] == []
@@ -277,7 +277,7 @@ def build_finished(app, exception):
277
277
  obj['kind'] = 'import'
278
278
  package_obj = obj
279
279
 
280
- if (obj['type'] == 'class' and obj['inheritance']):
280
+ if (obj['type'] == 'class' and 'inheritance' in obj):
281
281
  convert_class_to_enum_if_needed(obj)
282
282
 
283
283
  is_root = insert_node_to_toc_tree_return_is_root_package(toc_yaml, uid, project_name, toc_node_map)
@@ -30,7 +30,6 @@ import sys
30
30
  import threading
31
31
  import time
32
32
 
33
-
34
33
  try:
35
34
  import pwd
36
35
  except ImportError:
@@ -86,7 +85,6 @@ from ._common import debug
86
85
  from ._common import memoize_when_activated
87
86
  from ._common import wrap_numbers as _wrap_numbers
88
87
 
89
-
90
88
  if LINUX:
91
89
  # This is public API and it will be retrieved from _pslinux.py
92
90
  # via sys.modules.
@@ -207,7 +205,7 @@ if hasattr(_psplatform.Process, "rlimit"):
207
205
  AF_LINK = _psplatform.AF_LINK
208
206
 
209
207
  __author__ = "Giampaolo Rodola'"
210
- __version__ = "7.0.0"
208
+ __version__ = "7.1.0"
211
209
  version_info = tuple(int(num) for num in __version__.split('.'))
212
210
 
213
211
  _timer = getattr(time, 'monotonic', time.time)
@@ -377,7 +375,11 @@ class Process:
377
375
  won't reuse the same PID after such a short period of time
378
376
  (0.01 secs). Technically this is inherently racy, but
379
377
  practically it should be good enough.
378
+
379
+ NOTE: unreliable on FreeBSD and OpenBSD as ctime is subject to
380
+ system clock updates.
380
381
  """
382
+
381
383
  if WINDOWS:
382
384
  # Use create_time() fast method in order to speedup
383
385
  # `process_iter()`. This means we'll get AccessDenied for
@@ -386,6 +388,11 @@ class Process:
386
388
  # https://github.com/giampaolo/psutil/issues/2366#issuecomment-2381646555
387
389
  self._create_time = self._proc.create_time(fast_only=True)
388
390
  return (self.pid, self._create_time)
391
+ elif LINUX or NETBSD or OSX:
392
+ # Use 'monotonic' process starttime since boot to form unique
393
+ # process identity, since it is stable over changes to system
394
+ # time.
395
+ return (self.pid, self._proc.create_time(monotonic=True))
389
396
  else:
390
397
  return (self.pid, self.create_time())
391
398
 
@@ -426,12 +433,12 @@ class Process:
426
433
  # on PID and creation time.
427
434
  if not isinstance(other, Process):
428
435
  return NotImplemented
429
- if OPENBSD or NETBSD: # pragma: no cover
430
- # Zombie processes on Open/NetBSD have a creation time of
431
- # 0.0. This covers the case when a process started normally
432
- # (so it has a ctime), then it turned into a zombie. It's
433
- # important to do this because is_running() depends on
434
- # __eq__.
436
+ if OPENBSD or NETBSD or SUNOS: # pragma: no cover
437
+ # Zombie processes on Open/NetBSD/illumos/Solaris have a
438
+ # creation time of 0.0. This covers the case when a process
439
+ # started normally (so it has a ctime), then it turned into a
440
+ # zombie. It's important to do this because is_running()
441
+ # depends on __eq__.
435
442
  pid1, ident1 = self._ident
436
443
  pid2, ident2 = other._ident
437
444
  if pid1 == pid2:
@@ -593,10 +600,13 @@ class Process:
593
600
  return None
594
601
  ppid = self.ppid()
595
602
  if ppid is not None:
596
- ctime = self.create_time()
603
+ # Get a fresh (non-cached) ctime in case the system clock
604
+ # was updated. TODO: use a monotonic ctime on platforms
605
+ # where it's supported.
606
+ proc_ctime = Process(self.pid).create_time()
597
607
  try:
598
608
  parent = Process(ppid)
599
- if parent.create_time() <= ctime:
609
+ if parent.create_time() <= proc_ctime:
600
610
  return parent
601
611
  # ...else ppid has been reused by another process
602
612
  except NoSuchProcess:
@@ -765,8 +775,11 @@ class Process:
765
775
 
766
776
  def create_time(self):
767
777
  """The process creation time as a floating point number
768
- expressed in seconds since the epoch.
769
- The return value is cached after first call.
778
+ expressed in seconds since the epoch (seconds since January 1,
779
+ 1970, at midnight UTC). The return value, which is cached after
780
+ first call, is based on the system clock, which means it may be
781
+ affected by changes such as manual adjustments or time
782
+ synchronization (e.g. NTP).
770
783
  """
771
784
  if self._create_time is None:
772
785
  self._create_time = self._proc.create_time()
@@ -964,6 +977,10 @@ class Process:
964
977
  """
965
978
  self._raise_if_pid_reused()
966
979
  ppid_map = _ppid_map()
980
+ # Get a fresh (non-cached) ctime in case the system clock was
981
+ # updated. TODO: use a monotonic ctime on platforms where it's
982
+ # supported.
983
+ proc_ctime = Process(self.pid).create_time()
967
984
  ret = []
968
985
  if not recursive:
969
986
  for pid, ppid in ppid_map.items():
@@ -972,7 +989,7 @@ class Process:
972
989
  child = Process(pid)
973
990
  # if child happens to be older than its parent
974
991
  # (self) it means child's PID has been reused
975
- if self.create_time() <= child.create_time():
992
+ if proc_ctime <= child.create_time():
976
993
  ret.append(child)
977
994
  except (NoSuchProcess, ZombieProcess):
978
995
  pass
@@ -998,7 +1015,7 @@ class Process:
998
1015
  child = Process(child_pid)
999
1016
  # if child happens to be older than its parent
1000
1017
  # (self) it means child's PID has been reused
1001
- intime = self.create_time() <= child.create_time()
1018
+ intime = proc_ctime <= child.create_time()
1002
1019
  if intime:
1003
1020
  ret.append(child)
1004
1021
  stack.append(child_pid)
@@ -1484,7 +1501,7 @@ def process_iter(attrs=None, ad_value=None):
1484
1501
 
1485
1502
  Every new Process instance is only created once and then cached
1486
1503
  into an internal table which is updated every time this is used.
1487
- Cache can optionally be cleared via `process_iter.clear_cache()`.
1504
+ Cache can optionally be cleared via `process_iter.cache_clear()`.
1488
1505
 
1489
1506
  The sorting order in which processes are yielded is based on
1490
1507
  their PIDs.
@@ -2352,9 +2369,12 @@ if hasattr(_psplatform, "sensors_battery"):
2352
2369
 
2353
2370
 
2354
2371
  def boot_time():
2355
- """Return the system boot time expressed in seconds since the epoch."""
2356
- # Note: we are not caching this because it is subject to
2357
- # system clock updates.
2372
+ """Return the system boot time expressed in seconds since the epoch
2373
+ (seconds since January 1, 1970, at midnight UTC). The returned
2374
+ value is based on the system clock, which means it may be affected
2375
+ by changes such as manual adjustments or time synchronization (e.g.
2376
+ NTP).
2377
+ """
2358
2378
  return _psplatform.boot_time()
2359
2379
 
2360
2380
 
@@ -22,7 +22,6 @@ from socket import AF_INET
22
22
  from socket import SOCK_DGRAM
23
23
  from socket import SOCK_STREAM
24
24
 
25
-
26
25
  try:
27
26
  from socket import AF_INET6
28
27
  except ImportError:
@@ -409,7 +408,7 @@ def memoize(fun):
409
408
  except KeyError:
410
409
  try:
411
410
  ret = cache[key] = fun(*args, **kwargs)
412
- except Exception as err: # noqa: BLE001
411
+ except Exception as err:
413
412
  raise err from None
414
413
  return ret
415
414
 
@@ -458,14 +457,14 @@ def memoize_when_activated(fun):
458
457
  # case 2: we never entered oneshot() ctx
459
458
  try:
460
459
  return fun(self)
461
- except Exception as err: # noqa: BLE001
460
+ except Exception as err:
462
461
  raise err from None
463
462
  except KeyError:
464
463
  # case 3: we entered oneshot() ctx but there's no cache
465
464
  # for this entry yet
466
465
  try:
467
466
  ret = fun(self)
468
- except Exception as err: # noqa: BLE001
467
+ except Exception as err:
469
468
  raise err from None
470
469
  try:
471
470
  self._cache[fun] = ret
@@ -523,7 +522,6 @@ def path_exists_strict(path):
523
522
  return True
524
523
 
525
524
 
526
- @memoize
527
525
  def supports_ipv6():
528
526
  """Return True if IPv6 is supported on this platform."""
529
527
  if not socket.has_ipv6 or AF_INET6 is None:
@@ -29,7 +29,6 @@ from ._common import get_procfs_path
29
29
  from ._common import memoize_when_activated
30
30
  from ._common import usage_percent
31
31
 
32
-
33
32
  __extra__all__ = ["PROCFS_PATH"]
34
33
 
35
34
 
@@ -279,7 +278,7 @@ def boot_time():
279
278
  def users():
280
279
  """Return currently connected users as a list of namedtuples."""
281
280
  retlist = []
282
- rawlist = cext.users()
281
+ rawlist = cext_posix.users()
283
282
  localhost = (':0.0', ':0')
284
283
  for item in rawlist:
285
284
  user, tty, hostname, tstamp, user_process, pid = item