helper-cli 0.1.16__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.
@@ -4,14 +4,18 @@ import subprocess
4
4
  import sys
5
5
  from datetime import datetime
6
6
 
7
+
7
8
  def run_command(cmd):
8
9
  """Run a shell command and return its output"""
9
10
  try:
10
- result = subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT).strip()
11
+ result = subprocess.check_output(
12
+ cmd, shell=True, text=True, stderr=subprocess.STDOUT
13
+ ).strip()
11
14
  return result if result else "N/A"
12
15
  except subprocess.CalledProcessError as e:
13
16
  return f"Error: {e.output}" if e.output else "Command failed"
14
17
 
18
+
15
19
  def format_bytes(size_bytes):
16
20
  """Convert bytes to human readable format"""
17
21
  if not isinstance(size_bytes, (int, float)):
@@ -19,53 +23,54 @@ def format_bytes(size_bytes):
19
23
  size_bytes = float(size_bytes)
20
24
  except (ValueError, TypeError):
21
25
  return str(size_bytes)
22
-
23
- for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:
24
- if size_bytes < 1024.0 or unit == 'PB':
26
+
27
+ for unit in ["B", "KB", "MB", "GB", "TB", "PB"]:
28
+ if size_bytes < 1024.0 or unit == "PB":
25
29
  return f"{size_bytes:.1f} {unit}"
26
30
  size_bytes /= 1024.0
27
31
  return f"{size_bytes:.1f} PB"
28
32
 
33
+
29
34
  def parse_vm_stat(output):
30
35
  """Parse macOS vm_stat output and return human readable memory info"""
31
- if not output or 'Mach Virtual Memory Statistics' not in output:
36
+ if not output or "Mach Virtual Memory Statistics" not in output:
32
37
  return "Memory information not available"
33
-
38
+
34
39
  # Get physical memory using sysctl
35
40
  try:
36
- total_memory = int(run_command('sysctl -n hw.memsize'))
41
+ total_memory = int(run_command("sysctl -n hw.memsize"))
37
42
  except (ValueError, subprocess.CalledProcessError):
38
43
  return "Error: Could not determine total physical memory"
39
-
40
- lines = output.split('\n')
44
+
45
+ lines = output.split("\n")
41
46
  mem_info = {}
42
-
47
+
43
48
  for line in lines[1:]: # Skip header
44
- if ':' in line:
45
- key, value = line.split(':', 1)
46
- key = key.strip().strip('.')
49
+ if ":" in line:
50
+ key, value = line.split(":", 1)
51
+ key = key.strip().strip(".")
47
52
  try:
48
53
  # Convert pages to bytes (1 page = 4KB on macOS)
49
- pages = int(value.strip().strip('.'))
54
+ pages = int(value.strip().strip("."))
50
55
  mem_info[key] = pages * 4096 # 4KB per page
51
56
  except (ValueError, AttributeError):
52
57
  mem_info[key] = value.strip()
53
-
58
+
54
59
  # Calculate memory usage
55
- wired_memory = mem_info.get('Pages wired down', 0)
56
- active_memory = mem_info.get('Pages active', 0)
57
- inactive_memory = mem_info.get('Pages inactive', 0)
58
- free_memory = mem_info.get('Pages free', 0)
59
-
60
+ wired_memory = mem_info.get("Pages wired down", 0)
61
+ active_memory = mem_info.get("Pages active", 0)
62
+ inactive_memory = mem_info.get("Pages inactive", 0)
63
+ free_memory = mem_info.get("Pages free", 0)
64
+
60
65
  # Calculate used memory (wired + active)
61
66
  used_memory = wired_memory + active_memory
62
-
67
+
63
68
  # Calculate app memory (active + inactive)
64
69
  app_memory = active_memory + inactive_memory
65
-
70
+
66
71
  # Calculate cached files (inactive memory can be purged by the OS)
67
72
  cached_files = inactive_memory
68
-
73
+
69
74
  return (
70
75
  f"Total: {format_bytes(total_memory)}\n"
71
76
  f"Used: {format_bytes(used_memory)} (Apps: {format_bytes(app_memory)}, Wired: {format_bytes(wired_memory)})\n"
@@ -74,137 +79,167 @@ def parse_vm_stat(output):
74
79
  f"Usage: {used_memory/total_memory*100:.1f}%"
75
80
  )
76
81
 
82
+
77
83
  def parse_df_output(output):
78
84
  """Parse df output and format sizes"""
79
85
  if not output:
80
86
  return "Disk information not available"
81
-
82
- lines = output.split('\n')
87
+
88
+ lines = output.split("\n")
83
89
  if not lines:
84
90
  return output
85
-
91
+
86
92
  # Keep the header
87
93
  result = [lines[0]]
88
-
94
+
89
95
  # Process each line
90
96
  for line in lines[1:]:
91
97
  if not line.strip():
92
98
  continue
93
-
99
+
94
100
  parts = line.split()
95
101
  if len(parts) >= 5:
96
102
  # Format size columns (assuming standard df -h output)
97
- parts[1] = format_bytes(parts[1].upper().replace('G', 'GB').replace('M', 'MB')
98
- .replace('K', 'KB').replace('B', '').replace('I', '').strip())
99
- parts[2] = format_bytes(parts[2].upper().replace('G', 'GB').replace('M', 'MB')
100
- .replace('K', 'KB').replace('B', '').replace('I', '').strip())
101
- parts[3] = format_bytes(parts[3].upper().replace('G', 'GB').replace('M', 'MB')
102
- .replace('K', 'KB').replace('B', '').replace('I', '').strip())
103
-
103
+ parts[1] = format_bytes(
104
+ parts[1]
105
+ .upper()
106
+ .replace("G", "GB")
107
+ .replace("M", "MB")
108
+ .replace("K", "KB")
109
+ .replace("B", "")
110
+ .replace("I", "")
111
+ .strip()
112
+ )
113
+ parts[2] = format_bytes(
114
+ parts[2]
115
+ .upper()
116
+ .replace("G", "GB")
117
+ .replace("M", "MB")
118
+ .replace("K", "KB")
119
+ .replace("B", "")
120
+ .replace("I", "")
121
+ .strip()
122
+ )
123
+ parts[3] = format_bytes(
124
+ parts[3]
125
+ .upper()
126
+ .replace("G", "GB")
127
+ .replace("M", "MB")
128
+ .replace("K", "KB")
129
+ .replace("B", "")
130
+ .replace("I", "")
131
+ .strip()
132
+ )
133
+
104
134
  # Reconstruct the line with formatted sizes
105
- result.append(' '.join(parts))
135
+ result.append(" ".join(parts))
106
136
  else:
107
137
  result.append(line)
108
-
109
- return '\n'.join(result)
138
+
139
+ return "\n".join(result)
140
+
110
141
 
111
142
  def get_os_specific_info():
112
143
  """Get OS-specific system information"""
113
144
  system = platform.system().lower()
114
-
115
- if system == 'darwin': # macOS
145
+
146
+ if system == "darwin": # macOS
116
147
  return {
117
- 'cpu': 'sysctl -n machdep.cpu.brand_string',
118
- 'cpu_cores': 'sysctl -n hw.ncpu',
119
- 'memory': 'vm_stat',
120
- 'disks': 'df -h',
121
- 'os_version': 'sw_vers',
122
- 'hostname': 'hostname',
123
- 'uptime': 'uptime'
148
+ "cpu": "sysctl -n machdep.cpu.brand_string",
149
+ "cpu_cores": "sysctl -n hw.ncpu",
150
+ "memory": "vm_stat",
151
+ "disks": "df -h",
152
+ "os_version": "sw_vers",
153
+ "hostname": "hostname",
154
+ "uptime": "uptime",
124
155
  }
125
- elif system == 'linux':
156
+ elif system == "linux":
126
157
  return {
127
- 'cpu': 'cat /proc/cpuinfo | grep "model name" | head -n 1 | cut -d":" -f2',
128
- 'cpu_cores': 'nproc',
129
- 'memory': 'free -h',
130
- 'disks': 'df -h',
131
- 'os_version': 'cat /etc/os-release',
132
- 'hostname': 'hostname',
133
- 'uptime': 'uptime'
158
+ "cpu": 'cat /proc/cpuinfo | grep "model name" | head -n 1 | cut -d":" -f2',
159
+ "cpu_cores": "nproc",
160
+ "memory": "free -h",
161
+ "disks": "df -h",
162
+ "os_version": "cat /etc/os-release",
163
+ "hostname": "hostname",
164
+ "uptime": "uptime",
134
165
  }
135
- elif system == 'windows':
166
+ elif system == "windows":
136
167
  return {
137
- 'cpu': 'wmic cpu get name',
138
- 'cpu_cores': 'wmic cpu get NumberOfCores',
139
- 'memory': 'wmic OS get TotalVisibleMemorySize,FreePhysicalMemory /Value',
140
- 'disks': 'wmic logicaldisk get size,freespace,caption',
141
- 'os_version': 'systeminfo | findstr /B /C:"OS Name" /C:"OS Version"',
142
- 'hostname': 'hostname',
143
- 'uptime': 'wmic os get lastbootuptime'
168
+ "cpu": "wmic cpu get name",
169
+ "cpu_cores": "wmic cpu get NumberOfCores",
170
+ "memory": "wmic OS get TotalVisibleMemorySize,FreePhysicalMemory /Value",
171
+ "disks": "wmic logicaldisk get size,freespace,caption",
172
+ "os_version": 'systeminfo | findstr /B /C:"OS Name" /C:"OS Version"',
173
+ "hostname": "hostname",
174
+ "uptime": "wmic os get lastbootuptime",
144
175
  }
145
176
  else:
146
177
  return None
147
178
 
179
+
148
180
  def format_uptime(uptime_str, system):
149
181
  """Format uptime string based on OS"""
150
- if system == 'darwin' or system == 'linux':
182
+ if system == "darwin" or system == "linux":
151
183
  # Example: ' 8:53 up 1 day, 3:45, 2 users, load averages: 2.22 2.41 2.35'
152
- parts = uptime_str.split(',')
153
- if 'up' in parts[0]:
154
- return 'Uptime: ' + parts[0].split('up', 1)[1].strip()
184
+ parts = uptime_str.split(",")
185
+ if "up" in parts[0]:
186
+ return "Uptime: " + parts[0].split("up", 1)[1].strip()
155
187
  return uptime_str
156
188
 
189
+
157
190
  @click.command()
158
191
  def system_info():
159
192
  """Display system information including CPU, RAM, and disk usage"""
160
193
  system = platform.system().lower()
161
194
  commands = get_os_specific_info()
162
-
195
+
163
196
  if not commands:
164
197
  click.echo("Unsupported operating system")
165
198
  return
166
-
199
+
167
200
  # System Information
168
- click.echo("="*40 + " System Information " + "="*40)
201
+ click.echo("=" * 40 + " System Information " + "=" * 40)
169
202
  click.echo(f"System: {platform.system()} {platform.release()}")
170
203
  click.echo(f"Node Name: {run_command(commands['hostname'])}")
171
204
  click.echo(f"Machine: {platform.machine()}")
172
- click.echo(f"Processor: {platform.processor() or run_command(commands['cpu']).strip()}")
173
-
205
+ click.echo(
206
+ f"Processor: {platform.processor() or run_command(commands['cpu']).strip()}"
207
+ )
208
+
174
209
  # OS Version
175
- click.echo("\n" + "="*40 + " OS Version " + "="*40)
176
- click.echo(run_command(commands['os_version']))
177
-
210
+ click.echo("\n" + "=" * 40 + " OS Version " + "=" * 40)
211
+ click.echo(run_command(commands["os_version"]))
212
+
178
213
  # Uptime
179
- click.echo("\n" + "="*40 + " Uptime " + "="*40)
180
- uptime = run_command(commands['uptime'])
214
+ click.echo("\n" + "=" * 40 + " Uptime " + "=" * 40)
215
+ uptime = run_command(commands["uptime"])
181
216
  click.echo(format_uptime(uptime, system))
182
-
217
+
183
218
  # CPU Information
184
- click.echo("\n" + "="*40 + " CPU Info " + "="*40)
185
- cpu_cores = run_command(commands['cpu_cores']).strip()
219
+ click.echo("\n" + "=" * 40 + " CPU Info " + "=" * 40)
220
+ cpu_cores = run_command(commands["cpu_cores"]).strip()
186
221
  click.echo(f"CPU Cores: {cpu_cores}")
187
-
188
- if system == 'darwin' or system == 'linux':
189
- cpu_info = run_command(commands['cpu']).strip()
222
+
223
+ if system == "darwin" or system == "linux":
224
+ cpu_info = run_command(commands["cpu"]).strip()
190
225
  click.echo(f"CPU: {cpu_info}")
191
-
226
+
192
227
  # CPU Usage (simplified for cross-platform)
193
- if system == 'darwin':
194
- load_avg = run_command('sysctl -n vm.loadavg').strip()
228
+ if system == "darwin":
229
+ load_avg = run_command("sysctl -n vm.loadavg").strip()
195
230
  click.echo(f"Load Average: {load_avg}")
196
- elif system == 'linux':
197
- load_avg = run_command('cat /proc/loadavg').strip()
231
+ elif system == "linux":
232
+ load_avg = run_command("cat /proc/loadavg").strip()
198
233
  click.echo(f"Load Average: {load_avg}")
199
-
234
+
200
235
  # Memory Information
201
- click.echo("\n" + "="*40 + " Memory Information " + "="*40)
202
- if system == 'darwin':
203
- mem_info = run_command('vm_stat')
236
+ click.echo("\n" + "=" * 40 + " Memory Information " + "=" * 40)
237
+ if system == "darwin":
238
+ mem_info = run_command("vm_stat")
204
239
  click.echo(parse_vm_stat(mem_info))
205
- elif system == 'linux':
206
- mem_info = run_command('free -b') # Get bytes for consistent formatting
207
- lines = mem_info.split('\n')
240
+ elif system == "linux":
241
+ mem_info = run_command("free -b") # Get bytes for consistent formatting
242
+ lines = mem_info.split("\n")
208
243
  if len(lines) > 1:
209
244
  headers = lines[0].split()
210
245
  values = lines[1].split()
@@ -218,12 +253,19 @@ def system_info():
218
253
  f"Free: {format_bytes(free)}\n"
219
254
  f"Usage: {used/total*100:.1f}%"
220
255
  )
221
- elif system == 'windows':
222
- mem_info = run_command('wmic OS get TotalVisibleMemorySize,FreePhysicalMemory /Value')
223
- if 'TotalVisibleMemorySize' in mem_info and 'FreePhysicalMemory' in mem_info:
256
+ elif system == "windows":
257
+ mem_info = run_command(
258
+ "wmic OS get TotalVisibleMemorySize,FreePhysicalMemory /Value"
259
+ )
260
+ if "TotalVisibleMemorySize" in mem_info and "FreePhysicalMemory" in mem_info:
224
261
  try:
225
- total = int(mem_info.split('TotalVisibleMemorySize=')[1].split('\n')[0]) * 1024 # KB to bytes
226
- free = int(mem_info.split('FreePhysicalMemory=')[1].split('\n')[0]) * 1024 # KB to bytes
262
+ total = (
263
+ int(mem_info.split("TotalVisibleMemorySize=")[1].split("\n")[0])
264
+ * 1024
265
+ ) # KB to bytes
266
+ free = (
267
+ int(mem_info.split("FreePhysicalMemory=")[1].split("\n")[0]) * 1024
268
+ ) # KB to bytes
227
269
  used = total - free
228
270
  click.echo(
229
271
  f"Total: {format_bytes(total)}\n"
@@ -235,15 +277,18 @@ def system_info():
235
277
  click.echo(mem_info)
236
278
  else:
237
279
  click.echo(mem_info)
238
-
280
+
239
281
  # Disk Information
240
- click.echo("\n" + "="*40 + " Disk Information " + "="*40)
241
- if system == 'windows':
242
- disks = run_command('wmic logicaldisk get size,freespace,caption')
243
- if 'Caption' in disks:
244
- lines = disks.split('\n')
245
- result = ["{:<5} {:<15} {:<15} {:<15} {:<10}".format(
246
- "Drive", "Total Space", "Free Space", "Used Space", "% Used")]
282
+ click.echo("\n" + "=" * 40 + " Disk Information " + "=" * 40)
283
+ if system == "windows":
284
+ disks = run_command("wmic logicaldisk get size,freespace,caption")
285
+ if "Caption" in disks:
286
+ lines = disks.split("\n")
287
+ result = [
288
+ "{:<5} {:<15} {:<15} {:<15} {:<10}".format(
289
+ "Drive", "Total Space", "Free Space", "Used Space", "% Used"
290
+ )
291
+ ]
247
292
  for line in lines[1:]:
248
293
  parts = line.strip().split()
249
294
  if len(parts) >= 3:
@@ -259,18 +304,23 @@ def system_info():
259
304
  format_bytes(size),
260
305
  format_bytes(free),
261
306
  format_bytes(used),
262
- pct_used
307
+ pct_used,
263
308
  )
264
309
  )
265
310
  except (ValueError, IndexError):
266
311
  continue
267
- click.echo('\n'.join(result))
312
+ click.echo("\n".join(result))
268
313
  else:
269
314
  click.echo(disks)
270
315
  else:
271
- disks = run_command('df -h' if system != 'windows' else 'wmic logicaldisk get size,freespace,caption')
316
+ disks = run_command(
317
+ "df -h"
318
+ if system != "windows"
319
+ else "wmic logicaldisk get size,freespace,caption"
320
+ )
272
321
  click.echo(parse_df_output(disks))
273
322
 
323
+
274
324
  # Add aliases for the command
275
325
  sysinfo = system_info
276
326
  si = system_info
@@ -0,0 +1,130 @@
1
+ """
2
+ Virtual environment management commands for the helper CLI.
3
+
4
+ This module provides commands to manage Python virtual environments,
5
+ including activating and deactivating them from the command line.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+
11
+ import click
12
+
13
+
14
+ def find_virtualenv(path=None):
15
+ """Find virtual environment in the given path or current directory.
16
+
17
+ Args:
18
+ path (str, optional): Path to search for virtual environment.
19
+ Defaults to current directory.
20
+
21
+ Returns:
22
+ str: Path to the activate script if found, None otherwise.
23
+ """
24
+ if path is None:
25
+ path = os.getcwd()
26
+
27
+ # Check common virtual environment directories
28
+ venv_dirs = ["venv", ".venv"]
29
+ for venv_dir in venv_dirs:
30
+ activate_script = os.path.join(path, venv_dir, "bin", "activate")
31
+ if os.path.exists(activate_script):
32
+ return activate_script
33
+
34
+ # If not found in current directory, try parent directories
35
+ parent = os.path.dirname(path)
36
+ if parent != path: # Prevent infinite recursion
37
+ return find_virtualenv(parent)
38
+
39
+ return None
40
+
41
+
42
+ def source_virtualenv(venv_path=None):
43
+ """Source a virtual environment.
44
+
45
+ Args:
46
+ venv_path (str, optional): Path to the virtual environment.
47
+ If None, search in current and parent directories.
48
+ """
49
+ if venv_path is None:
50
+ activate_script = find_virtualenv()
51
+ if not activate_script:
52
+ click.echo(
53
+ "Error: No virtual environment found in current or parent directories.",
54
+ err=True,
55
+ )
56
+ click.echo(
57
+ "Please specify the path to the virtual environment or "
58
+ "create one with 'python -m venv venv'"
59
+ )
60
+ sys.exit(1)
61
+ else:
62
+ # If path is provided, check if it's a directory or activate script
63
+ if os.path.isdir(venv_path):
64
+ # If it's a directory, look for bin/activate
65
+ activate_script = os.path.join(venv_path, "bin", "activate")
66
+ if not os.path.exists(activate_script):
67
+ click.echo(f"Error: No activate script found in {venv_path}", err=True)
68
+ sys.exit(1)
69
+ elif os.path.isfile(venv_path):
70
+ # If it's a file, use it directly
71
+ activate_script = venv_path
72
+ else:
73
+ click.echo(f"Error: {venv_path} is not a valid file or directory", err=True)
74
+ sys.exit(1)
75
+
76
+ # Get the absolute path to the activate script
77
+ activate_script = os.path.abspath(activate_script)
78
+
79
+ # Print the command to source the virtual environment
80
+ # The user needs to run this with 'eval $(h venv source [path])' or
81
+ # 'source <(h venv source [path])'
82
+ click.echo(f'source "{activate_script}"')
83
+ venv_dir = os.path.dirname(os.path.dirname(activate_script))
84
+ click.echo(f"# Virtual environment activated: {venv_dir}", err=True)
85
+
86
+
87
+ def deactivate_virtualenv():
88
+ """Print the command to deactivate the current virtual environment."""
89
+ click.echo("deactivate")
90
+ click.echo("# Virtual environment deactivated", err=True)
91
+
92
+
93
+ @click.group()
94
+ def venv():
95
+ """Manage Python virtual environments (v0.1.19)."""
96
+
97
+
98
+ @venv.command()
99
+ @click.argument("path", required=False)
100
+ def source(path):
101
+ """Source a Python virtual environment.
102
+
103
+ If no path is provided, searches for a virtual environment in the current or parent directories.
104
+ Looks for 'venv' first, then '.venv'.
105
+
106
+ Usage:
107
+ h venv source [PATH] # Source the specified virtual environment or auto-detect
108
+ eval $(h venv source) # In bash/zsh to activate the virtual environment
109
+ source <(h venv source) # Alternative syntax for bash/zsh
110
+ """
111
+ source_virtualenv(path)
112
+
113
+
114
+ @venv.command()
115
+ def deactivate():
116
+ """Deactivate the current virtual environment.
117
+
118
+ Usage:
119
+ h venv deactivate # Show the deactivate command
120
+ eval $(h venv deactivate) # In bash/zsh to deactivate the virtual environment
121
+ """
122
+ deactivate_virtualenv()
123
+
124
+
125
+ # Add short aliases
126
+ s = source
127
+ d = deactivate
128
+
129
+ # Add the commands to the module
130
+ __all__ = ["venv", "source", "deactivate", "s", "d"]