machineconfig 5.91__py3-none-any.whl → 5.93__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.
Potentially problematic release.
This version of machineconfig might be problematic. Click here for more details.
- machineconfig/utils/procs.py +36 -43
- {machineconfig-5.91.dist-info → machineconfig-5.93.dist-info}/METADATA +1 -1
- {machineconfig-5.91.dist-info → machineconfig-5.93.dist-info}/RECORD +6 -6
- {machineconfig-5.91.dist-info → machineconfig-5.93.dist-info}/WHEEL +0 -0
- {machineconfig-5.91.dist-info → machineconfig-5.93.dist-info}/entry_points.txt +0 -0
- {machineconfig-5.91.dist-info → machineconfig-5.93.dist-info}/top_level.txt +0 -0
machineconfig/utils/procs.py
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import psutil
|
|
4
4
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
5
|
-
from zoneinfo import ZoneInfo
|
|
6
5
|
from machineconfig.utils.options import choose_from_options
|
|
7
|
-
from typing import Optional,
|
|
6
|
+
from typing import Optional, TypedDict, List, Dict
|
|
8
7
|
from rich.console import Console
|
|
9
8
|
from rich.panel import Panel
|
|
10
|
-
from datetime import datetime
|
|
9
|
+
from datetime import datetime
|
|
11
10
|
from machineconfig.utils.accessories import pprint
|
|
12
11
|
|
|
13
12
|
console = Console()
|
|
@@ -15,11 +14,29 @@ console = Console()
|
|
|
15
14
|
BOX_WIDTH = 78 # width for box drawing
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
class ProcessInfo(TypedDict):
|
|
18
|
+
"""TypedDict for process information."""
|
|
19
|
+
command: str
|
|
20
|
+
pid: int
|
|
21
|
+
name: str
|
|
22
|
+
username: str
|
|
23
|
+
cpu_percent: float
|
|
24
|
+
memory_usage_mb: float
|
|
25
|
+
status: str
|
|
26
|
+
create_time: datetime
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class FileAccessInfo(TypedDict):
|
|
30
|
+
"""TypedDict for file access information."""
|
|
31
|
+
pid: int
|
|
32
|
+
files: List[str]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_processes_accessing_file(path: str) -> List[FileAccessInfo]:
|
|
19
36
|
# header for searching processes
|
|
20
37
|
title = "🔍 SEARCHING FOR PROCESSES ACCESSING FILE"
|
|
21
38
|
console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
|
|
22
|
-
res:
|
|
39
|
+
res: Dict[int, List[str]] = {}
|
|
23
40
|
|
|
24
41
|
with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
|
|
25
42
|
progress.add_task("🔎 Scanning processes...", total=None)
|
|
@@ -34,7 +51,7 @@ def get_processes_accessing_file(path: str):
|
|
|
34
51
|
res[proc.pid] = tmp
|
|
35
52
|
|
|
36
53
|
# Convert to list of dictionaries for consistent data structure
|
|
37
|
-
result_data = [{"pid": pid, "files": files} for pid, files in res.items()]
|
|
54
|
+
result_data: List[FileAccessInfo] = [{"pid": pid, "files": files} for pid, files in res.items()]
|
|
38
55
|
console.print(Panel(f"✅ Found {len(res)} processes accessing the specified file", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
|
|
39
56
|
return result_data
|
|
40
57
|
|
|
@@ -57,15 +74,13 @@ class ProcessManager:
|
|
|
57
74
|
# header for initializing process manager
|
|
58
75
|
title = "📊 INITIALIZING PROCESS MANAGER"
|
|
59
76
|
console.print(Panel(title, title="[bold blue]Process Info[/bold blue]", border_style="blue"))
|
|
60
|
-
process_info = []
|
|
77
|
+
process_info: List[ProcessInfo] = []
|
|
61
78
|
with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}")) as progress:
|
|
62
79
|
progress.add_task("🔍 Reading system processes...", total=None)
|
|
63
80
|
for proc in psutil.process_iter():
|
|
64
81
|
try:
|
|
65
82
|
mem_usage_mb = proc.memory_info().rss / (1024 * 1024)
|
|
66
|
-
|
|
67
|
-
create_time_utc = datetime.fromtimestamp(proc.create_time(), tz=timezone.utc)
|
|
68
|
-
create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
|
|
83
|
+
create_time = datetime.fromtimestamp(proc.create_time(), tz=None)
|
|
69
84
|
|
|
70
85
|
process_info.append(
|
|
71
86
|
{
|
|
@@ -75,7 +90,7 @@ class ProcessManager:
|
|
|
75
90
|
"cpu_percent": proc.cpu_percent(),
|
|
76
91
|
"memory_usage_mb": mem_usage_mb,
|
|
77
92
|
"status": proc.status(),
|
|
78
|
-
"create_time":
|
|
93
|
+
"create_time": create_time,
|
|
79
94
|
"command": " ".join(proc.cmdline()),
|
|
80
95
|
}
|
|
81
96
|
)
|
|
@@ -93,8 +108,8 @@ class ProcessManager:
|
|
|
93
108
|
return ""
|
|
94
109
|
|
|
95
110
|
# Create header
|
|
96
|
-
_headers = ["PID", "Name", "Username", "CPU%", "Memory(MB)", "Status", "Create Time"
|
|
97
|
-
header_line = f"{'PID':<8} {'Name':<20} {'Username':<12} {'CPU%':<8} {'Memory(MB)':<12} {'Status':<12} {'Create Time':<20}
|
|
111
|
+
_headers = ["Command", "PID", "Name", "Username", "CPU%", "Memory(MB)", "Status", "Create Time"]
|
|
112
|
+
header_line = f"{'Command':<50} {'PID':<8} {'Name':<20} {'Username':<12} {'CPU%':<8} {'Memory(MB)':<12} {'Status':<12} {'Create Time':<20}"
|
|
98
113
|
separator = "-" * len(header_line)
|
|
99
114
|
|
|
100
115
|
lines = [header_line, separator]
|
|
@@ -105,7 +120,7 @@ class ProcessManager:
|
|
|
105
120
|
# Truncate command if too long
|
|
106
121
|
command = process["command"][:47] + "..." if len(process["command"]) > 50 else process["command"]
|
|
107
122
|
|
|
108
|
-
line = f"{process['pid']:<8} {process['name'][:19]:<20} {process['username'][:11]:<12} {process['cpu_percent']:<8.1f} {process['memory_usage_mb']:<12.2f} {process['status'][:11]:<12} {create_time_str:<20}
|
|
123
|
+
line = f"{command:<50} {process['pid']:<8} {process['name'][:19]:<20} {process['username'][:11]:<12} {process['cpu_percent']:<8.1f} {process['memory_usage_mb']:<12.2f} {process['status'][:11]:<12} {create_time_str:<20}"
|
|
109
124
|
lines.append(line)
|
|
110
125
|
|
|
111
126
|
return "\n".join(lines)
|
|
@@ -129,7 +144,7 @@ class ProcessManager:
|
|
|
129
144
|
print(f"PID: {process['pid']}, Name: {process['name']}, Memory: {process['memory_usage_mb']:.2f}MB")
|
|
130
145
|
|
|
131
146
|
for idx, process in enumerate(selected_processes):
|
|
132
|
-
pprint(process, f"📌 Process {idx}")
|
|
147
|
+
pprint(dict(process), f"📌 Process {idx}")
|
|
133
148
|
|
|
134
149
|
kill_all = input("\n⚠️ Confirm killing ALL selected processes? y/[n] ").lower() == "y"
|
|
135
150
|
if kill_all:
|
|
@@ -141,7 +156,7 @@ class ProcessManager:
|
|
|
141
156
|
indices = [int(val) for val in kill_by_index.split(" ")]
|
|
142
157
|
target_processes = [selected_processes[i] for i in indices]
|
|
143
158
|
for idx2, process in enumerate(target_processes):
|
|
144
|
-
pprint(process, f"🎯 Target Process {idx2}")
|
|
159
|
+
pprint(dict(process), f"🎯 Target Process {idx2}")
|
|
145
160
|
_ = self.kill(pids=[p["pid"] for p in target_processes]) if input("\n⚠️ Confirm termination? y/[n] ").lower() == "y" else None
|
|
146
161
|
console.print(Panel("🔔 No processes were terminated.", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
|
|
147
162
|
|
|
@@ -188,7 +203,7 @@ class ProcessManager:
|
|
|
188
203
|
try:
|
|
189
204
|
proc = psutil.Process(pid)
|
|
190
205
|
proc_name = proc.name()
|
|
191
|
-
proc_lifetime = get_age(proc.create_time())
|
|
206
|
+
proc_lifetime = get_age(datetime.fromtimestamp(proc.create_time(), tz=None))
|
|
192
207
|
proc.kill()
|
|
193
208
|
print(f'💀 Killed process with PID {pid} and name "{proc_name}". It lived {proc_lifetime}. RIP 🪦💐')
|
|
194
209
|
killed_count += 1
|
|
@@ -208,32 +223,10 @@ class ProcessManager:
|
|
|
208
223
|
console.print(Panel(f"✅ Termination complete: {killed_count} processes terminated", title="[bold blue]Process Info[/bold blue]", border_style="blue"))
|
|
209
224
|
|
|
210
225
|
|
|
211
|
-
def get_age(create_time:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
# Handle timestampz
|
|
216
|
-
create_time_utc = datetime.fromtimestamp(create_time, tz=timezone.utc)
|
|
217
|
-
create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
|
|
218
|
-
else:
|
|
219
|
-
# Already a datetime object
|
|
220
|
-
create_time_local = create_time
|
|
221
|
-
|
|
222
|
-
now_local = datetime.now(tz=ZoneInfo("Australia/Adelaide"))
|
|
223
|
-
age = now_local - create_time_local
|
|
224
|
-
return str(age)
|
|
225
|
-
except Exception as e:
|
|
226
|
-
try:
|
|
227
|
-
# Fallback without timezone
|
|
228
|
-
if isinstance(create_time, (int, float)):
|
|
229
|
-
create_time_dt = datetime.fromtimestamp(create_time)
|
|
230
|
-
else:
|
|
231
|
-
create_time_dt = create_time.replace(tzinfo=None) if create_time.tzinfo else create_time
|
|
232
|
-
now_dt = datetime.now()
|
|
233
|
-
age = now_dt - create_time_dt
|
|
234
|
-
return str(age)
|
|
235
|
-
except Exception as ee:
|
|
236
|
-
return f"unknown due to {ee} and {e}"
|
|
226
|
+
def get_age(create_time: datetime) -> str:
|
|
227
|
+
dtm_now = datetime.now()
|
|
228
|
+
delta = dtm_now - create_time
|
|
229
|
+
return str(delta).split(".")[0] # remove microseconds
|
|
237
230
|
|
|
238
231
|
|
|
239
232
|
def main():
|
|
@@ -392,7 +392,7 @@ machineconfig/utils/notifications.py,sha256=tuXIudcip0tEioG-bm8BbLr3FMDve4f6Bktl
|
|
|
392
392
|
machineconfig/utils/options.py,sha256=vUO4Kej-vDOv64wHr2HNDyu6PATURpjd7xp6N8OOoJg,7083
|
|
393
393
|
machineconfig/utils/path_extended.py,sha256=4RhL0twcIG2kJxmC4r_YzaiTxrYkSRbdh9SO5ObMABw,53122
|
|
394
394
|
machineconfig/utils/path_helper.py,sha256=0e3Xh3BAEv27oqcezNeVLHJllGmLEgLH4T1l90m-650,8014
|
|
395
|
-
machineconfig/utils/procs.py,sha256=
|
|
395
|
+
machineconfig/utils/procs.py,sha256=rw8LR8MjGgvtrpcgxb3hudq2B9fkkpYUXe9x5-FgHuc,10694
|
|
396
396
|
machineconfig/utils/scheduler.py,sha256=jZ_1yghqA3-aINPRmE_76gboqJc0UElroR7urNOfXKs,14940
|
|
397
397
|
machineconfig/utils/scheduling.py,sha256=RF1iXJpqf4Dg18jdZWtBixz97KAHC6VKYqTFSpdLWuc,11188
|
|
398
398
|
machineconfig/utils/source_of_truth.py,sha256=ZAnCRltiM07ig--P6g9_6nEAvNFC4X4ERFTVcvpIYsE,764
|
|
@@ -421,8 +421,8 @@ machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoS
|
|
|
421
421
|
machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
|
|
422
422
|
machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
|
|
423
423
|
machineconfig/utils/ssh_utils/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
424
|
-
machineconfig-5.
|
|
425
|
-
machineconfig-5.
|
|
426
|
-
machineconfig-5.
|
|
427
|
-
machineconfig-5.
|
|
428
|
-
machineconfig-5.
|
|
424
|
+
machineconfig-5.93.dist-info/METADATA,sha256=ppdZOK8vxv-rB6t3fOorFFUKn6JRjcHuLtiNDldb-HQ,3012
|
|
425
|
+
machineconfig-5.93.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
426
|
+
machineconfig-5.93.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
|
|
427
|
+
machineconfig-5.93.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
|
|
428
|
+
machineconfig-5.93.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|