pyhw 0.15.1__py3-none-any.whl → 0.15.3__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.
pyhw/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = '0.15.1'
1
+ __version__ = '0.15.3'
2
2
  __author__ = 'xiaoran007'
@@ -12,9 +12,9 @@ class MemoryDetectBSD(MemoryDetectLinux):
12
12
 
13
13
  def getMemoryInfo(self):
14
14
  self.__getMemorySysctl()
15
- self._memoryInfo.total = self.__physical_memory / 1024 / 1024 # Convert bytes to MiB
16
- self._memoryInfo.used = (self.__physical_memory - self.__free_memory) / 1024 / 1024 # Convert bytes to MiB
17
- self._memoryInfo.memory = f"{round(self._memoryInfo.used, 2)} MiB / {round(self._memoryInfo.total, 2)} MiB"
15
+ self._memoryInfo.total = self.__physical_memory / 1024 / 1024 / 1024 # Convert bytes to GiB
16
+ self._memoryInfo.used = (self.__physical_memory - self.__free_memory) / 1024 / 1024 / 1024 # Convert bytes to GiB
17
+ self._memoryInfo.memory = f"{round(self._memoryInfo.used, 2)} GiB / {round(self._memoryInfo.total, 2)} GiB"
18
18
  return self._memoryInfo
19
19
 
20
20
  def __getMemorySysctl(self):
@@ -7,7 +7,7 @@ class MemoryDetectLinux:
7
7
 
8
8
  def getMemoryInfo(self):
9
9
  self._getMemory()
10
- self._memoryInfo.memory = f"{self._memoryInfo.used} MiB / {self._memoryInfo.total} MiB"
10
+ self._memoryInfo.memory = f"{self._memoryInfo.used} GiB / {self._memoryInfo.total} GiB"
11
11
  return self._memoryInfo
12
12
 
13
13
  def _getMemory(self):
@@ -15,9 +15,9 @@ class MemoryDetectLinux:
15
15
  with open("/proc/meminfo", "r") as file:
16
16
  for line in file:
17
17
  if line.startswith("MemTotal:"):
18
- self._memoryInfo.total = round(float(line.split(":")[1].strip()[:-3]) / 1024, 2)
18
+ self._memoryInfo.total = round(float(line.split(":")[1].strip()[:-3]) / 1024 / 1024, 2)
19
19
  elif line.startswith("MemAvailable:"):
20
- self._memoryInfo.available = round(float(line.split(":")[1].strip()[:-3]) / 1024, 2)
20
+ self._memoryInfo.available = round(float(line.split(":")[1].strip()[:-3]) / 1024 / 1024, 2)
21
21
  self._memoryInfo.used = round(self._memoryInfo.total - self._memoryInfo.available, 2)
22
22
  except FileNotFoundError:
23
23
  pass
@@ -19,9 +19,9 @@ class MemoryDetectMacOS:
19
19
 
20
20
  def getMemoryInfo(self):
21
21
  self.__getMemory()
22
- self.__memoryInfo.total = self.__mem_total / 1024 / 1024 # Convert bytes to MiB
23
- self.__memoryInfo.used = self.__mem_used / 1024 / 1024 # Convert bytes to MiB
24
- self.__memoryInfo.memory = f"{round(self.__memoryInfo.used, 2)} MiB / {round(self.__memoryInfo.total, 2)} MiB"
22
+ self.__memoryInfo.total = self.__mem_total / 1024 / 1024 / 1024 # Convert bytes to GiB
23
+ self.__memoryInfo.used = self.__mem_used / 1024 / 1024 / 1024 # Convert bytes to GiB
24
+ self.__memoryInfo.memory = f"{self.__memoryInfo.used:.2f} GiB / {self.__memoryInfo.total:.2f} GiB"
25
25
  return self.__memoryInfo
26
26
 
27
27
  def __getMemory(self):
@@ -10,7 +10,7 @@ class MemoryDetectWindows:
10
10
 
11
11
  def getMemoryInfo(self):
12
12
  self._getMemory()
13
- self._memoryInfo.memory = f"{self._memoryInfo.used} MiB / {self._memoryInfo.total} MiB"
13
+ self._memoryInfo.memory = f"{self._memoryInfo.used} GiB / {self._memoryInfo.total} GiB"
14
14
  return self._memoryInfo
15
15
 
16
16
  def _getMemory(self):
@@ -21,8 +21,8 @@ class MemoryDetectWindows:
21
21
  raise BackendException("Failed to get memory information on Windows.")
22
22
 
23
23
  res = json.loads(result.stdout)
24
- free_memory = int(res['FreePhysicalMemory']) / 1024
25
- total_memory = int(res['TotalVisibleMemorySize']) / 1024
24
+ free_memory = int(res['FreePhysicalMemory']) / 1024 / 1024
25
+ total_memory = int(res['TotalVisibleMemorySize']) / 1024 / 1024
26
26
  used_memory = total_memory - free_memory
27
27
  self._memoryInfo.total = round(total_memory, 2)
28
28
  self._memoryInfo.available = round(free_memory, 2)
@@ -4,6 +4,7 @@ from ..pyhwUtil import getOS
4
4
  from ..pyhwException import BackendException
5
5
  import subprocess
6
6
  import re
7
+ import os
7
8
 
8
9
 
9
10
  class Printer:
@@ -40,31 +41,91 @@ class Printer:
40
41
  print("\n".join(self.__combined_lines))
41
42
 
42
43
  def __dropLongString(self):
43
- # Need more accurate way to drop long strings
44
- if getOS() == "linux":
44
+ """
45
+ Truncate lines that exceed terminal width, accounting for ANSI escape sequences.
46
+ ANSI escape sequences don't contribute to visible width but are counted by len().
47
+ Enabled on both Linux and macOS.
48
+ """
49
+ if getOS() in ["linux", "macos"]:
45
50
  fixed_lines = list()
46
51
  for line in self.__combined_lines:
47
- if len(line) > self.__columns+20:
48
- fixed_lines.append(line[:self.__columns+20])
52
+ visible_length = self.__getVisibleLength(line)
53
+ if visible_length > self.__columns:
54
+ truncated_line = self.__truncateToWidth(line, self.__columns)
55
+ fixed_lines.append(truncated_line)
49
56
  else:
50
57
  fixed_lines.append(line)
51
58
  self.__combined_lines = fixed_lines
52
59
  else:
53
60
  pass
54
61
 
62
+ @staticmethod
63
+ def __getVisibleLength(text: str) -> int:
64
+ """
65
+ Calculate the visible length of a string, excluding ANSI escape sequences.
66
+ ANSI codes follow the pattern: \033[...m
67
+ """
68
+ ansi_pattern = re.compile(r'\033\[[0-9;]*m')
69
+ clean_text = ansi_pattern.sub('', text)
70
+ return len(clean_text)
71
+
72
+ @staticmethod
73
+ def __truncateToWidth(text: str, max_width: int) -> str:
74
+ """
75
+ Truncate a string to a maximum visible width while preserving ANSI escape sequences.
76
+ Ensures proper color reset at the end if truncated.
77
+ """
78
+ ansi_pattern = re.compile(r'(\033\[[0-9;]*m)')
79
+ parts = ansi_pattern.split(text)
80
+
81
+ result = []
82
+ visible_count = 0
83
+
84
+ for part in parts:
85
+ if ansi_pattern.match(part):
86
+ result.append(part)
87
+ else:
88
+ remaining = max_width - visible_count
89
+ if remaining <= 0:
90
+ break
91
+ if len(part) <= remaining:
92
+ result.append(part)
93
+ visible_count += len(part)
94
+ else:
95
+ result.append(part[:remaining])
96
+ visible_count += remaining
97
+ break
98
+
99
+ truncated = ''.join(result)
100
+ if not truncated.endswith('\033[0m'):
101
+ truncated += '\033[0m'
102
+
103
+ return truncated
104
+
55
105
  @staticmethod
56
106
  def __getColumns() -> int:
57
- if getOS() == "linux":
58
- try:
59
- result = subprocess.run(['stty', 'size'], capture_output=True, text=True)
60
- _, columns_str = result.stdout.split()
61
- columns = int(columns_str)
62
- except:
63
- columns = 80 # default terminal size is 80 columns
64
- else:
65
- # macOS default terminal size is 80 columns
66
- columns = 80
67
- return columns
107
+ try:
108
+ columns = os.get_terminal_size().columns
109
+ return columns
110
+ except (OSError, AttributeError):
111
+ pass
112
+
113
+ try:
114
+ result = subprocess.run(['stty', 'size'], capture_output=True, text=True, check=True)
115
+ _, columns_str = result.stdout.strip().split()
116
+ columns = int(columns_str)
117
+ return columns
118
+ except (subprocess.CalledProcessError, ValueError, FileNotFoundError):
119
+ pass
120
+
121
+ try:
122
+ columns = int(os.environ.get('COLUMNS', 0))
123
+ if columns > 0:
124
+ return columns
125
+ except (ValueError, TypeError):
126
+ pass
127
+
128
+ return 80
68
129
 
69
130
  def __LogoPreprocess(self):
70
131
  global_color = self.__config.get("colors")[0]
Binary file
Binary file
Binary file
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhw
3
- Version: 0.15.1
3
+ Version: 0.15.3
4
4
  Summary: PyHw, a neofetch-like command line tool for fetching system information but written mostly in python.
5
5
  Author: Xiao Ran
6
6
  Maintainer-email: Xiao Ran <xiaoran.007@icloud.com>
@@ -13,7 +13,7 @@ Classifier: Operating System :: OS Independent
13
13
  Requires-Python: >=3.9
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
- Requires-Dist: pypci-ng>=0.2.7
16
+ Requires-Dist: pypci-ng>=0.3.0
17
17
  Dynamic: license-file
18
18
 
19
19
  # PyHw, a neofetch-like system information fetching tool
@@ -1,4 +1,4 @@
1
- pyhw/__init__.py,sha256=HOB6zppm7om1pAT4p00ZL8jZJeZ3GXNEQS3ktRh0PQU,49
1
+ pyhw/__init__.py,sha256=n85B2Q8z-AqEs2R2FvLy_oKqviq3yymy-uRkvZ2yRww,49
2
2
  pyhw/__main__.py,sha256=sycXv_HBzXuNET2w0-fRgMwHaWIsMALyJ_ZCxdZulDk,7696
3
3
  pyhw/backend/__init__.py,sha256=X1D1D28lSojDrUzUolgJvmbuctwBh_UxG3FwUeL8adA,51
4
4
  pyhw/backend/backendBase.py,sha256=mloo8mPEbgbIdmyQ3I4vdEXMSSjxWi_wnwACmzvHbEo,506
@@ -29,12 +29,12 @@ pyhw/backend/kernel/kernelInfo.py,sha256=Nkumd0McbimCjc7yJrvz6bcwpWu1Tdo_LKomjZr
29
29
  pyhw/backend/kernel/unix.py,sha256=opG4xTO_l4-boX8FeJmnPa2RJB9dFOfhsuPAf3SQAxg,1191
30
30
  pyhw/backend/kernel/windows.py,sha256=kFGnIXIgTp3endyVIoxmUgYh3RrvIqbMHmbWwqlyZro,1180
31
31
  pyhw/backend/memory/__init__.py,sha256=zGBWxfPAAk8ivCBWPLJIpuD-lB7wUJT3x8u2jHiAoCY,65
32
- pyhw/backend/memory/bsd.py,sha256=0sQrdeaxmR-jEtGbcBQLjUVpACU3LIULlJwdP4jVu08,1013
33
- pyhw/backend/memory/linux.py,sha256=_4wsyz-C8pElIG_xcjQQrnhHueRWfg8JUWggVZQaPhc,916
34
- pyhw/backend/memory/macos.py,sha256=ur2HxmmmVkXmaxEcw_otphifVp_csfNMJdgt-idCq7M,2770
32
+ pyhw/backend/memory/bsd.py,sha256=DDlryPsjPiJcAHpqX1e-ERqYirp61elcrlCbzCDBPng,1027
33
+ pyhw/backend/memory/linux.py,sha256=gu1FsVZ_ZuG1hObTfuAdCp_7LKJr3NxtN5UfDXptvF8,930
34
+ pyhw/backend/memory/macos.py,sha256=lUYWBdJpAwaHB1HkFGkW4poMVDSlJ21ZbAIPCb3BA2Y,2772
35
35
  pyhw/backend/memory/memoryBase.py,sha256=trubcJ_7JD_FnrKefUycPFd4OZMFj3Rk75ih5YVsSXg,790
36
36
  pyhw/backend/memory/memoryInfo.py,sha256=OQF165uEyuapAsi7cKacQYDRnKdrQHeldfyFwzS9N2g,186
37
- pyhw/backend/memory/windows.py,sha256=ISihGHBnV8iD4Xj8_kelFSCydPu05CYKxG5q_wM5ZbA,1201
37
+ pyhw/backend/memory/windows.py,sha256=_hYKJ-y4kRFo5NzJd0C__3tfsJnmXQT1VzOPgQzdJo0,1215
38
38
  pyhw/backend/nic/__init__.py,sha256=eP4eOYIvMF3LcTf954hJa6TnB8R4Qahss2g-UcgypKY,57
39
39
  pyhw/backend/nic/bsd.py,sha256=6nj7XXII5dRz3FGRYAXVgTt0vSgyQo0Re9JA1vlcnuw,134
40
40
  pyhw/backend/nic/linux.py,sha256=e6gX58RBE9IDKb0FrzZ7U2EhDNfGJsR6OvXq6qO5ZOc,2003
@@ -74,7 +74,7 @@ pyhw/backend/uptime/uptimeBase.py,sha256=HVRFZHO-2F_UKH0ti9wR16iHCH7Q8dga0HfxFxU
74
74
  pyhw/backend/uptime/uptimeInfo.py,sha256=TobPEV3MBT3Fiv3W6TOzD3a4MNW-vz2Oi_Trlcihu7k,114
75
75
  pyhw/backend/uptime/windows.py,sha256=JP6Co-V_fljOEMEkydNKDJ7OY7LGhtWf8IRLuIb6F4I,1742
76
76
  pyhw/frontend/__init__.py,sha256=jKkL3EvL069POGesru6FUlsMhW8AxiaVAErubWRFXE8,58
77
- pyhw/frontend/frontendBase.py,sha256=qRZOF5iTVgnzKBEKr4Kat1-Oowy-bRa6oOZu40ADUxo,5032
77
+ pyhw/frontend/frontendBase.py,sha256=IiSbJwWjj4H2CQEcTmFVuzoyUWpl0lx5AIiYm1nbOJ0,7072
78
78
  pyhw/frontend/color/__init__.py,sha256=uPtOM76b_b9F85AgYDyoOGNKeUHGpZnT752g_kCUVng,192
79
79
  pyhw/frontend/color/colorConfig.py,sha256=ReCR3IR6K1c28Tkf3uFg74mSzCMqXmUniegRiyGeq_w,7752
80
80
  pyhw/frontend/color/colorSet.py,sha256=spH8PlRu7capouf-yUgDHgoPCnM5aJ_ncascISZfz2g,1421
@@ -103,10 +103,10 @@ pyhw/frontend/logo/ascii/windows_10.pyhw,sha256=jv5pzZs_CdOzpeTjyXfXJWcTQwK-J0LN
103
103
  pyhw/frontend/logo/ascii/windows_11.pyhw,sha256=VuQTzbBabaEQhm2JBVhy6Ja6lClUGacQsaiNUih9nhU,656
104
104
  pyhw/frontend/logo/ascii/windows_2025.pyhw,sha256=o8eWsiyhNpDoEjiWFiBMfkd-8MdIslGc1Jpm85LU4P8,643
105
105
  pyhw/frontend/logo/ascii/windows_old.pyhw,sha256=AMsvWAZ50HM8lweWEmzDWbRNDGkKFJo9qLY_VRKrciY,580
106
- pyhw/library/lib/iokitCPULib.dylib,sha256=uMDDaijZGvTNkdT0ccQ55SDO4rRrzj8GSbrDMKeLAZ0,34280
107
- pyhw/library/lib/iokitGPULib.dylib,sha256=uiULOcAPpwOG7LZGR8Sdmjh_p5QjKN1OBBCfDMnUohk,155640
108
- pyhw/library/lib/iokitHostLib.dylib,sha256=MKxyKUkD4IZomP4exATikWx2SxqSDqQx4FEuIkFAEnc,149912
109
- pyhw/library/lib/iokitNICLib.dylib,sha256=4IP-GPmxiS6unnj8poktJrMGEWh0dQPclghdjVI9atE,212360
106
+ pyhw/library/lib/iokitCPULib.dylib,sha256=6E77TMJcIFInm_uCTmzH_Q16JWCKKTMK7Cm4Z6AiqmQ,34280
107
+ pyhw/library/lib/iokitGPULib.dylib,sha256=H6_RMZcFyH1NfiATq-RCJ-X97-Huh4TdktT-om-yLBI,155816
108
+ pyhw/library/lib/iokitHostLib.dylib,sha256=vt5YDen6pLBk26u2ODCz8jkSNo2sR7elU4kjgABGSfQ,148968
109
+ pyhw/library/lib/iokitNICLib.dylib,sha256=TNNDDdx60QjY9JA8BrPVnyQZ2EhyiiD_ebaFzspp7So,209448
110
110
  pyhw/library/lib/nvmlGPULib_amd64.so,sha256=lrkxeJjChUs8oVhaw_uMeXKbUJp24KroQ_hhcLtHfTg,12784
111
111
  pyhw/library/lib/nvmlGPULib_arm64.so,sha256=DFIYqNcuRxiZ8_jrYoaRB3Dx9GrY7UBXscwXQvV4k3I,13528
112
112
  pyhw/library/test/iokitCPULibTest.py,sha256=BrhMypgfJTeMectpDc9Tmwzp8gYwYAcowaTFf72LlLE,311
@@ -121,9 +121,9 @@ pyhw/pyhwUtil/cliUtil.py,sha256=IUcWun5nDwQb20Qe8YefS5j3Jji8a-F41Qd9QwCf0h0,2454
121
121
  pyhw/pyhwUtil/pciUtil.py,sha256=WAluDRDb-gUbqhvSIusFzPrf6r98EkrNEAwbPyMwrTc,202
122
122
  pyhw/pyhwUtil/pyhwUtil.py,sha256=XA1sQnAZmfA3QdmCzqiNWN4CDJKtnPK7N0j_1p3shiQ,8373
123
123
  pyhw/pyhwUtil/sysctlUtil.py,sha256=S-rUvqi7ZrMyMouIhxlyHEQ4agM7sCT1Y7uzs3Hu5-o,841
124
- pyhw-0.15.1.dist-info/licenses/LICENSE,sha256=hJs6RBqSVCexbTsalkMLNFI5t06kekQEsSVaOt_-yLs,1497
125
- pyhw-0.15.1.dist-info/METADATA,sha256=3OfrFEDp6Yd09Vs06NFoEqvIVoztuj240TKTsJIT-TQ,7715
126
- pyhw-0.15.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
127
- pyhw-0.15.1.dist-info/entry_points.txt,sha256=q-AB8im_QahpmNrmy4aPTJRGi0LlbNlnI3kF7s6pKss,44
128
- pyhw-0.15.1.dist-info/top_level.txt,sha256=7Inxvxt1TngEricKZEex9_WJZS3DbKYFUXDz4v5WHYU,5
129
- pyhw-0.15.1.dist-info/RECORD,,
124
+ pyhw-0.15.3.dist-info/licenses/LICENSE,sha256=hJs6RBqSVCexbTsalkMLNFI5t06kekQEsSVaOt_-yLs,1497
125
+ pyhw-0.15.3.dist-info/METADATA,sha256=2MgmAU1onwWHoFj-2UjpLXK-vDE8zEMBgRA1Hb4-mIc,7715
126
+ pyhw-0.15.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
127
+ pyhw-0.15.3.dist-info/entry_points.txt,sha256=q-AB8im_QahpmNrmy4aPTJRGi0LlbNlnI3kF7s6pKss,44
128
+ pyhw-0.15.3.dist-info/top_level.txt,sha256=7Inxvxt1TngEricKZEex9_WJZS3DbKYFUXDz4v5WHYU,5
129
+ pyhw-0.15.3.dist-info/RECORD,,
File without changes