commiefetch 1.2.0__tar.gz → 1.2.2__tar.gz

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.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commiefetch
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Communist-themed system information tool — like neofetch, but red
5
5
  Author: commiefetch contributors
6
- License-Expression: MIT
6
+ License-Expression: GPL-3.0-only
7
7
  Project-URL: Source, https://github.com/amalxloop/commiefetch
8
8
  Project-URL: Tracker, https://github.com/amalxloop/commiefetch/issues
9
9
  Keywords: system-info,neofetch,communist,fastfetch,cli
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "commiefetch"
7
- version = "1.2.0"
7
+ version = "1.2.2"
8
8
  description = "Communist-themed system information tool — like neofetch, but red"
9
9
  readme = "README.md"
10
10
  authors = [
11
11
  {name = "commiefetch contributors"},
12
12
  ]
13
- license = "MIT"
13
+ license = "GPL-3.0-only"
14
14
  requires-python = ">=3.8"
15
15
  keywords = ["system-info", "neofetch", "communist", "fastfetch", "cli"]
16
16
  classifiers = [
@@ -1,2 +1,2 @@
1
- __version__ = "1.2.0"
1
+ __version__ = "1.2.2"
2
2
  __app_name__ = "commiefetch"
@@ -187,7 +187,10 @@ def get_module_value(name):
187
187
  }
188
188
  func = mappers.get(name)
189
189
  if func:
190
- return func()
190
+ try:
191
+ return func()
192
+ except Exception:
193
+ return None
191
194
  return None
192
195
 
193
196
 
@@ -195,7 +198,12 @@ def _format_memory(mem):
195
198
  if not mem:
196
199
  return "unknown"
197
200
  if isinstance(mem, dict):
198
- return f"{mem.get('used', 0)} {mem.get('unit', 'MiB')} / {mem.get('total', 0)} {mem.get('unit', 'MiB')} ({mem.get('percent', 0)}%)"
201
+ total = mem.get('total', 0)
202
+ used = mem.get('used', 0)
203
+ pct = mem.get('percent', 0)
204
+ if total >= 1024:
205
+ return f"{used/1024:.1f} GiB / {total/1024:.1f} GiB ({pct}%)"
206
+ return f"{used} MiB / {total} MiB ({pct}%)"
199
207
  return str(mem)
200
208
 
201
209
 
@@ -7,13 +7,22 @@ import shutil
7
7
  import socket
8
8
  import pwd
9
9
  import grp
10
+ import struct
10
11
  from pathlib import Path
11
12
 
12
13
  from .colors import NO_COLOR
13
14
 
14
15
 
15
16
  def is_termux():
16
- return bool(os.environ.get("TERMUX_VERSION")) or "/com.termux/" in __file__
17
+ if bool(os.environ.get("TERMUX_VERSION")):
18
+ return True
19
+ if "/com.termux/" in __file__:
20
+ return True
21
+ if os.environ.get("PREFIX", "").startswith("/data/data/com.termux"):
22
+ return True
23
+ if os.path.exists("/data/data/com.termux/files/usr/bin/termux-setup-package"):
24
+ return True
25
+ return False
17
26
 
18
27
  _cache = {}
19
28
  _cache_time = {}
@@ -328,23 +337,168 @@ def get_gpu():
328
337
  return "unknown"
329
338
 
330
339
 
340
+ def _get_dumpsys_memory():
341
+ """Parse 'dumpsys meminfo' output on Android."""
342
+ try:
343
+ out = run_cmd(["dumpsys", "meminfo"], timeout=5)
344
+ if not out:
345
+ out = run_cmd(["/system/bin/dumpsys", "meminfo"], timeout=5)
346
+ if not out:
347
+ return None
348
+ for line in out.split("\n"):
349
+ line = line.strip()
350
+ if "Total RAM:" in line:
351
+ val = line.split(":")[-1].strip()
352
+ val = val.replace(",", "").replace(" ", "")
353
+ if val.endswith("kB"):
354
+ total_mb = int(val[:-2]) // 1024
355
+ elif val.endswith("MB"):
356
+ total_mb = int(val[:-2])
357
+ elif val.endswith("GB"):
358
+ total_mb = int(float(val[:-2]) * 1024)
359
+ else:
360
+ total_mb = int(val) // 1024
361
+ return {"total": total_mb, "used": 0, "available": 0,
362
+ "unit": "MiB", "percent": 0}
363
+ return None
364
+ except Exception:
365
+ return None
366
+
367
+
368
+ def _get_sysinfo_memory():
369
+ try:
370
+ import ctypes
371
+ import platform as _plat
372
+ libc = None
373
+ for name in ["libc.so.6", "libc.so"]:
374
+ try:
375
+ libc = ctypes.CDLL(name)
376
+ break
377
+ except OSError:
378
+ continue
379
+ if libc is None:
380
+ return None
381
+
382
+ buf = ctypes.create_string_buffer(200)
383
+ ret = libc.sysinfo(buf)
384
+ if ret != 0:
385
+ return None
386
+ data = buf.raw
387
+
388
+ is_64 = _plat.machine() in ("aarch64", "x86_64", "amd64")
389
+ if is_64:
390
+ fmt = "<q3Q7QH2QI"
391
+ else:
392
+ fmt = "<i3I7IH2II8x"
393
+
394
+ fields = struct.unpack_from(fmt, data)
395
+ mem_unit = fields[-1] or 1
396
+ totalram = fields[3]
397
+ freeram = fields[4]
398
+ total_mb = totalram * mem_unit // (1024 * 1024)
399
+ if total_mb == 0:
400
+ return None
401
+ free_mb = freeram * mem_unit // (1024 * 1024)
402
+ used_mb = total_mb - free_mb
403
+ return {
404
+ "total": total_mb,
405
+ "used": used_mb,
406
+ "available": free_mb,
407
+ "unit": "MiB",
408
+ "percent": round(used_mb / total_mb * 100, 1) if total_mb else 0,
409
+ }
410
+ except Exception:
411
+ return None
412
+
413
+
414
+ def _parse_meminfo_value(val):
415
+ val = val.strip().replace(",", "")
416
+ if val.endswith(" kB"):
417
+ return int(val.split()[0]) // 1024
418
+ if val.endswith(" MB"):
419
+ return int(val.split()[0])
420
+ if val.endswith(" GB"):
421
+ return int(float(val.split()[0]) * 1024)
422
+ if val.endswith(" KB"):
423
+ return int(val.split()[0]) // 1024
424
+ if val.endswith(" mb"):
425
+ return int(val.split()[0])
426
+ if val.endswith(" gb"):
427
+ return int(float(val.split()[0]) * 1024)
428
+ try:
429
+ return int(val)
430
+ except ValueError:
431
+ try:
432
+ return int(float(val))
433
+ except ValueError:
434
+ return 0
435
+
436
+
331
437
  @cached("memory", 5)
332
438
  def get_memory():
333
439
  try:
334
440
  system = platform.system()
335
441
  if system == "Linux":
336
- with open("/proc/meminfo") as f:
337
- meminfo = {}
338
- for line in f:
442
+ meminfo = {}
443
+ raw = None
444
+ try:
445
+ with open("/proc/meminfo") as f:
446
+ raw = f.read()
447
+ except Exception:
448
+ raw = run_cmd(["cat", "/proc/meminfo"], timeout=3)
449
+ if raw:
450
+ for line in raw.split("\n"):
339
451
  parts = line.split(":")
340
452
  if len(parts) == 2:
341
- val = parts[1].strip()
342
- if val.endswith(" kB"):
343
- val = int(val.split()[0]) // 1024
344
- meminfo[parts[0]] = val
453
+ meminfo[parts[0]] = _parse_meminfo_value(parts[1])
345
454
  total = meminfo.get("MemTotal", 0)
455
+ if not isinstance(total, (int, float)) or total <= 0:
456
+ total = 0
457
+ if total == 0:
458
+ result = _get_sysinfo_memory()
459
+ if result and result.get("total", 0) > 0:
460
+ return result
461
+ result = _get_dumpsys_memory()
462
+ if result and result.get("total", 0) > 0:
463
+ return result
464
+ free_out = run_cmd(["free", "-m"], timeout=3)
465
+ if free_out:
466
+ for line in free_out.split("\n"):
467
+ if line.startswith("Mem:"):
468
+ cols = line.split()
469
+ if len(cols) >= 3:
470
+ try:
471
+ t = int(cols[1])
472
+ if t > 0:
473
+ u = int(cols[2])
474
+ return {
475
+ "total": t, "used": u,
476
+ "available": t - u, "unit": "MiB",
477
+ "percent": round(u / t * 100, 1),
478
+ }
479
+ except Exception:
480
+ pass
481
+ return None
346
482
  avail = meminfo.get("MemAvailable", 0)
483
+ if not isinstance(avail, (int, float)):
484
+ avail = 0
485
+ if avail == 0:
486
+ free = meminfo.get("MemFree", 0)
487
+ buffers = meminfo.get("Buffers", 0)
488
+ cached = meminfo.get("Cached", 0)
489
+ slab = meminfo.get("SReclaimable", 0)
490
+ if not isinstance(free, (int, float)):
491
+ free = 0
492
+ if not isinstance(buffers, (int, float)):
493
+ buffers = 0
494
+ if not isinstance(cached, (int, float)):
495
+ cached = 0
496
+ if not isinstance(slab, (int, float)):
497
+ slab = 0
498
+ avail = free + buffers + cached + slab
347
499
  used = total - avail
500
+ if used < 0:
501
+ used = 0
348
502
  return {
349
503
  "total": total,
350
504
  "used": used,
@@ -417,10 +571,10 @@ def get_memory():
417
571
  "unit": "MiB",
418
572
  "percent": round(used_mb / total_mb * 100, 1) if total_mb else 0,
419
573
  }
420
- return {"total": total, "used": 0, "unit": "MiB", "percent": 0}
421
- return {"total": 0, "used": 0, "unit": "MiB", "percent": 0}
574
+ return None
575
+ return None
422
576
  except Exception:
423
- return {"total": 0, "used": 0, "unit": "MiB", "percent": 0}
577
+ return None
424
578
 
425
579
 
426
580
  @cached("swap", 30)
@@ -456,7 +610,7 @@ def get_disk(path="/"):
456
610
  total = usage.total // (1024 * 1024)
457
611
  used = usage.used // (1024 * 1024)
458
612
  free = usage.free // (1024 * 1024)
459
- return {
613
+ info = {
460
614
  "total": total,
461
615
  "used": used,
462
616
  "free": free,
@@ -464,7 +618,45 @@ def get_disk(path="/"):
464
618
  "mount": path,
465
619
  "percent": round(used / total * 100, 1) if total else 0,
466
620
  }
621
+ if is_termux():
622
+ for p in ["/storage/emulated/0", "/sdcard", "/data/media/0"]:
623
+ try:
624
+ u2 = shutil.disk_usage(p)
625
+ t2 = u2.total // (1024 * 1024)
626
+ if t2 > info["total"]:
627
+ info = {
628
+ "total": t2,
629
+ "used": u2.used // (1024 * 1024),
630
+ "free": u2.free // (1024 * 1024),
631
+ "unit": "MiB",
632
+ "mount": p,
633
+ "percent": round(u2.used // (1024 * 1024) / t2 * 100, 1) if t2 else 0,
634
+ }
635
+ except Exception:
636
+ pass
637
+ return info
467
638
  except Exception:
639
+ if is_termux():
640
+ for p in [path, "/storage/emulated/0", "/sdcard", "/data/media/0"]:
641
+ out = run_cmd(["df", "-m", p], timeout=5)
642
+ if out:
643
+ for line in out.split("\n"):
644
+ parts = line.split()
645
+ if len(parts) >= 6 and parts[-1] == p:
646
+ try:
647
+ total = int(parts[1])
648
+ if total > 0:
649
+ used = int(parts[2])
650
+ return {
651
+ "total": total,
652
+ "used": used,
653
+ "free": total - used,
654
+ "unit": "MiB",
655
+ "mount": p,
656
+ "percent": round(used / total * 100, 1) if total else 0,
657
+ }
658
+ except Exception:
659
+ pass
468
660
  return None
469
661
 
470
662
 
@@ -487,6 +679,24 @@ def get_disks():
487
679
  "mount": mount,
488
680
  "info": info,
489
681
  })
682
+ if not disks and is_termux():
683
+ root = get_disk("/")
684
+ if root and root["total"] >= 1024:
685
+ disks.append({
686
+ "device": "rootfs",
687
+ "mount": "/",
688
+ "info": root,
689
+ })
690
+ for p in ["/storage/emulated/0", "/sdcard", "/data/media/0"]:
691
+ info = get_disk(p)
692
+ if info and info["total"] >= 1024:
693
+ seen = any(d["mount"] == p for d in disks)
694
+ if not seen:
695
+ disks.append({
696
+ "device": "internal",
697
+ "mount": p,
698
+ "info": info,
699
+ })
490
700
  return disks[:4]
491
701
  except Exception:
492
702
  pass
@@ -578,6 +788,15 @@ def get_desktop():
578
788
  def get_packages():
579
789
  system = platform.system()
580
790
  count = 0
791
+ if is_termux():
792
+ out = run_cmd(["dpkg", "--list"], timeout=5)
793
+ if out:
794
+ count = len([l for l in out.split("\n") if l.startswith("ii")])
795
+ if not count:
796
+ out = run_cmd(["apt", "list", "--installed", "2>/dev/null"], timeout=5)
797
+ if out:
798
+ count = len([l for l in out.split("\n") if "/" in l])
799
+ return count or 0
581
800
  if system == "Linux":
582
801
  methods = [
583
802
  (["dpkg", "--list"], lambda l: len(l.split("\n")) - 5),
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commiefetch
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Communist-themed system information tool — like neofetch, but red
5
5
  Author: commiefetch contributors
6
- License-Expression: MIT
6
+ License-Expression: GPL-3.0-only
7
7
  Project-URL: Source, https://github.com/amalxloop/commiefetch
8
8
  Project-URL: Tracker, https://github.com/amalxloop/commiefetch/issues
9
9
  Keywords: system-info,neofetch,communist,fastfetch,cli
File without changes
File without changes
File without changes
File without changes