pyhw 0.14.1__py3-none-any.whl → 0.14.2__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.14.1'
1
+ __version__ = '0.14.2'
2
2
  __author__ = 'xiaoran007'
pyhw/backend/nic/macos.py CHANGED
@@ -1,5 +1,8 @@
1
1
  from .nicInfo import NICInfo
2
2
  import subprocess
3
+ import ctypes
4
+ from ctypes import c_char_p, c_bool, c_int32, c_char, byref, create_string_buffer
5
+ from pathlib import Path
3
6
 
4
7
 
5
8
  class NICDetectMacOS:
@@ -11,15 +14,179 @@ class NICDetectMacOS:
11
14
  return self.__nicInfo
12
15
 
13
16
  def __getNICInfo(self):
14
- # Placeholder for a more advanced method.
17
+ # Try to get NIC info using IOKit first
18
+ if not self.__getNICInfoIOKit():
19
+ try:
20
+ # Get default interface
21
+ cmd_get_interface = "route get default | grep interface"
22
+ interface_output = subprocess.run(["bash", "-c", cmd_get_interface],
23
+ capture_output=True, text=True).stdout.strip()
24
+ interface = interface_output.split(":")[1].strip()
25
+
26
+ # Get IP address
27
+ if_ip = subprocess.run(["bash", "-c", f"ipconfig getifaddr {interface}"],
28
+ capture_output=True, text=True).stdout.strip()
29
+
30
+ # Get interface type and link speed
31
+ link_info = self.__getLinkInfo(interface)
32
+
33
+ # Add all information to nicInfo
34
+ self.__nicInfo.nics.append(f"{interface} @ {if_ip} - {link_info}")
35
+ self.__nicInfo.number += 1
36
+ except Exception as e:
37
+ self.__handleError()
38
+ else:
39
+ pass
40
+
41
+ def __getNICInfoIOKit(self):
42
+ try:
43
+ package_root = Path(__file__).resolve().parent.parent.parent
44
+ lib = ctypes.CDLL(f"{package_root}/library/lib/iokitNICLib.dylib")
45
+
46
+ lib.getDefaultInterface.argtypes = [c_char_p]
47
+ lib.getDefaultInterface.restype = c_bool
48
+
49
+ lib.getNetworkInfo.argtypes = [c_char_p, ctypes.POINTER(c_bool),
50
+ c_char_p, ctypes.POINTER(c_int32),
51
+ c_char_p, c_char_p, c_char_p, c_char_p]
52
+ lib.getNetworkInfo.restype = c_bool
53
+ interface = create_string_buffer(32)
54
+ if lib.getDefaultInterface(interface):
55
+ interface_str = interface.value.decode('utf-8')
56
+
57
+ is_wifi = c_bool(False)
58
+ ip_address = create_string_buffer(32)
59
+ speed = c_int32(0)
60
+ band = create_string_buffer(16)
61
+ channel = create_string_buffer(32)
62
+ conn_type = create_string_buffer(32)
63
+ wifi_standard = create_string_buffer(16)
64
+
65
+ if lib.getNetworkInfo(interface_str.encode('utf-8'),
66
+ byref(is_wifi),
67
+ ip_address,
68
+ byref(speed),
69
+ band,
70
+ channel,
71
+ conn_type,
72
+ wifi_standard):
73
+
74
+ if is_wifi.value:
75
+ conn_info = f"{conn_type.value.decode('utf-8')} 802.11{wifi_standard.value.decode('utf-8')} ({band.value.decode('utf-8')} {speed.value} Mbps)"
76
+ else:
77
+ conn_info = conn_type.value.decode('utf-8')
78
+
79
+ formatted_output = f"{interface_str} @ {ip_address.value.decode('utf-8')} - {conn_info}"
80
+
81
+ self.__nicInfo.nics.append(formatted_output)
82
+ self.__nicInfo.number += 1
83
+
84
+ return True
85
+
86
+ else:
87
+ return False
88
+ else:
89
+ return False
90
+
91
+ except Exception as e:
92
+ # print(f"An error occurred while getting NIC info using IOKit: {e}")
93
+ return False
94
+
95
+
96
+ def __getLinkInfo(self, interface):
15
97
  try:
16
- interface = subprocess.run(["bash", "-c", "route get default | grep interface"], capture_output=True, text=True).stdout.strip().split(":")[1]
17
- if_ip = subprocess.run(["bash", "-c", f"ipconfig getifaddr {interface}"], capture_output=True, text=True).stdout.strip()
18
- self.__nicInfo.nics.append(f"{interface} @ {if_ip}")
19
- self.__nicInfo.number += 1
98
+ # Check if interface is wireless
99
+ is_wifi_cmd = f"networksetup -getairportpower {interface} 2>/dev/null"
100
+ is_wifi_result = subprocess.run(["bash", "-c", is_wifi_cmd],
101
+ capture_output=True, text=True).returncode
102
+
103
+ if is_wifi_result == 0: # This is a Wi-Fi interface
104
+ speed, channel, band = self.__getWifiInfo(interface)
105
+ return f"Wi-Fi {band} ({speed} Mbps)"
106
+ else:
107
+ # For wired connections, get link speed using networksetup
108
+ media_cmd = f"networksetup -getmedia {interface} | grep 'Active'"
109
+ media_info = subprocess.run(["bash", "-c", media_cmd],
110
+ capture_output=True, text=True).stdout.strip()
111
+
112
+ if media_info:
113
+ parts = media_info.split(':', 1)
114
+ if len(parts) > 1:
115
+ # Extract "2500Base-T <full-duplex>" part
116
+ media_details = parts[1].strip()
117
+
118
+ # Parse the speed part (e.g., "2500Base-T")
119
+ speed_part = media_details.split()[0] if media_details else ""
120
+
121
+ if "2500Base-T" in speed_part:
122
+ return "Wired (2.5 Gbps)"
123
+ elif "1000Base-T" in speed_part:
124
+ return "Wired (1 Gbps)"
125
+ elif "100Base-T" in speed_part:
126
+ return "Wired (100 Mbps)"
127
+ elif "10000Base-T" in speed_part:
128
+ return "Wired (10 Gbps)"
129
+ elif "Base-T" in speed_part or "base-T" in speed_part:
130
+ # Extract the numeric part from formats like "5000Base-T"
131
+ import re
132
+ speed_match = re.search(r'(\d+)(?:Base-T|base-T)', speed_part)
133
+ if speed_match:
134
+ speed_value = int(speed_match.group(1))
135
+ if speed_value >= 1000:
136
+ return f"Wired ({speed_value / 1000:.1f} Gbps)"
137
+ else:
138
+ return f"Wired ({speed_value} Mbps)"
139
+ return f"Wired ({speed_part})"
20
140
  except:
21
- self.__handleError()
141
+ return "Unknown connection type"
142
+
143
+ def __getWifiInfo(self, interface):
144
+ # 使用 system_profiler 获取 WiFi 信息
145
+ profiler_cmd = f"system_profiler SPAirPortDataType -json"
146
+ try:
147
+ wifi_data = subprocess.run(["bash", "-c", profiler_cmd],
148
+ capture_output=True, text=True, timeout=5).stdout
149
+
150
+ import json
151
+ data = json.loads(wifi_data)
152
+
153
+ # 根据实际 JSON 结构提取信息
154
+ if 'SPAirPortDataType' in data and isinstance(data['SPAirPortDataType'], list):
155
+ airport_data = data['SPAirPortDataType'][0]
156
+
157
+ # 获取接口列表
158
+ if 'spairport_airport_interfaces' in airport_data:
159
+ interfaces = airport_data['spairport_airport_interfaces']
160
+
161
+ # 查找匹配的接口
162
+ for iface in interfaces:
163
+ if interface == iface.get('_name', ''):
164
+ # 获取当前网络信息
165
+ current_network = iface.get('spairport_current_network_information', {})
166
+
167
+ # 从当前连接中提取速率
168
+ speed = current_network.get('spairport_network_rate', 'Unknown')
169
+
170
+ # 获取信道信息
171
+ channel_info = current_network.get('spairport_network_channel', 'Unknown')
172
+
173
+ # 确定频段信息
174
+ band = "Unknown"
175
+ if isinstance(channel_info, str) and "GHz" in channel_info:
176
+ if "2GHz" in channel_info:
177
+ band = "2.4GHz"
178
+ elif "5GHz" in channel_info:
179
+ band = "5GHz"
180
+ elif "6GHz" in channel_info:
181
+ band = "6GHz"
182
+
183
+ return speed, channel_info, band
184
+
185
+ return "Unknown", "Unknown", "Unknown"
186
+ except Exception as e:
187
+ # 可以考虑添加日志记录 print(f"WiFi info error: {str(e)}")
188
+ return "Unknown", "Unknown", "Unknown"
22
189
 
23
190
  def __handleError(self):
24
- self.__nicInfo.nics.append("en0")
191
+ self.__nicInfo.nics.append("en0 - Unknown connection")
25
192
  self.__nicInfo.number = 1
Binary file
@@ -0,0 +1,76 @@
1
+ import ctypes
2
+ from ctypes import c_char_p, c_bool, c_int32, c_char, byref, create_string_buffer
3
+ import os
4
+
5
+
6
+ def main():
7
+ current_dir = os.path.dirname(os.path.abspath(__file__))
8
+ lib_path = os.path.join(current_dir, "../lib/iokitNICLib.dylib")
9
+
10
+ try:
11
+ lib = ctypes.CDLL(lib_path)
12
+
13
+ lib.getDefaultInterface.argtypes = [c_char_p]
14
+ lib.getDefaultInterface.restype = c_bool
15
+
16
+ lib.getNetworkInfo.argtypes = [c_char_p, ctypes.POINTER(c_bool),
17
+ c_char_p, ctypes.POINTER(c_int32),
18
+ c_char_p, c_char_p, c_char_p, c_char_p]
19
+ lib.getNetworkInfo.restype = c_bool
20
+
21
+ interface = create_string_buffer(32)
22
+ if lib.getDefaultInterface(interface):
23
+ interface_str = interface.value.decode('utf-8')
24
+
25
+ # interface_str = "en1"
26
+ print(f"默认网络接口: {interface_str}")
27
+
28
+ is_wifi = c_bool(False)
29
+ ip_address = create_string_buffer(32)
30
+ speed = c_int32(0)
31
+ band = create_string_buffer(16)
32
+ channel = create_string_buffer(32)
33
+ conn_type = create_string_buffer(32)
34
+ wifi_standard = create_string_buffer(16)
35
+
36
+ if lib.getNetworkInfo(interface_str.encode('utf-8'),
37
+ byref(is_wifi),
38
+ ip_address,
39
+ byref(speed),
40
+ band,
41
+ channel,
42
+ conn_type,
43
+ wifi_standard):
44
+
45
+ print("=== 网络信息 ===")
46
+ print(f"接口: {interface_str}")
47
+ print(f"IP地址: {ip_address.value.decode('utf-8')}")
48
+ print(f"连接类型: {conn_type.value.decode('utf-8')}")
49
+ print(f"速度: {speed.value} Mbps")
50
+
51
+ if is_wifi.value:
52
+ print(f"Wi-Fi频段: {band.value.decode('utf-8')}")
53
+ print(f"信道: {channel.value.decode('utf-8')}")
54
+ print(f"Wi-Fi标准: {wifi_standard.value.decode('utf-8')}")
55
+
56
+ if is_wifi.value:
57
+ wifi_info = f"{wifi_standard.value.decode('utf-8')} {band.value.decode('utf-8')}"
58
+ conn_info = f"{conn_type.value.decode('utf-8')} ({wifi_info}, {speed.value} Mbps)"
59
+ else:
60
+ conn_info = conn_type.value.decode('utf-8')
61
+
62
+ formatted_output = f"{interface_str} @ {ip_address.value.decode('utf-8')} - {conn_info}"
63
+ print("\n格式化输出:")
64
+ print(formatted_output)
65
+ else:
66
+ print(f"无法获取接口 {interface_str} 的网络信息")
67
+ else:
68
+ print("无法获取默认网络接口")
69
+
70
+ except Exception as e:
71
+ print(f"错误: {e}")
72
+
73
+
74
+ if __name__ == "__main__":
75
+ main()
76
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhw
3
- Version: 0.14.1
3
+ Version: 0.14.2
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>
@@ -1,4 +1,4 @@
1
- pyhw/__init__.py,sha256=vLCCfp6vkFGuTLWzKhiTL7svLlIrWaFlQfh5-mhr7yk,49
1
+ pyhw/__init__.py,sha256=YQSawzjDRCIzy8piPhOd3ggWHVeCQJ6_1EBuDzHeFAY,49
2
2
  pyhw/__main__.py,sha256=_8lT1XlZNR71daSu1IWs5befhb8wocCT4xIx2aMp-1Q,7168
3
3
  pyhw/backend/__init__.py,sha256=X1D1D28lSojDrUzUolgJvmbuctwBh_UxG3FwUeL8adA,51
4
4
  pyhw/backend/backendBase.py,sha256=mloo8mPEbgbIdmyQ3I4vdEXMSSjxWi_wnwACmzvHbEo,506
@@ -38,7 +38,7 @@ pyhw/backend/memory/windows.py,sha256=ISihGHBnV8iD4Xj8_kelFSCydPu05CYKxG5q_wM5Zb
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
41
- pyhw/backend/nic/macos.py,sha256=J1hO7FxpQpi98Kx9EmUf5Q4_GxE8xMvb6R5Ok861V8E,853
41
+ pyhw/backend/nic/macos.py,sha256=AOT6IvgEGvWPIpv8UwlTGbFO7zaDDQn4xC1NL8SKmeo,8566
42
42
  pyhw/backend/nic/nicBase.py,sha256=Kng5qoe7FHcnQaf6S-LUe_HyOaBJe0L1SVstdIQ_WJY,962
43
43
  pyhw/backend/nic/nicInfo.py,sha256=wuBuL-aIzD441IUDPGz5e0xctcZ-opdpgqkVxgbvZLg,133
44
44
  pyhw/backend/nic/windows.py,sha256=4yJ0pmiXokegLEC299WLwqiW9uHAgaiVpkR2vCuzECg,1225
@@ -106,10 +106,12 @@ pyhw/frontend/logo/ascii/windows_old.pyhw,sha256=AMsvWAZ50HM8lweWEmzDWbRNDGkKFJo
106
106
  pyhw/library/lib/iokitCPULib.dylib,sha256=uMDDaijZGvTNkdT0ccQ55SDO4rRrzj8GSbrDMKeLAZ0,34280
107
107
  pyhw/library/lib/iokitGPULib.dylib,sha256=6xigd40YGEz9lHUfq_6qpTswz2st-4I9bW6j8ssg29s,155224
108
108
  pyhw/library/lib/iokitHostLib.dylib,sha256=MKxyKUkD4IZomP4exATikWx2SxqSDqQx4FEuIkFAEnc,149912
109
+ pyhw/library/lib/iokitNICLib.dylib,sha256=K6Bn6qAzds93S3qvjN6ClNfP_eP4GQh4BWiXa35z750,212360
109
110
  pyhw/library/lib/nvmlGPULib_amd64.so,sha256=lrkxeJjChUs8oVhaw_uMeXKbUJp24KroQ_hhcLtHfTg,12784
110
111
  pyhw/library/lib/nvmlGPULib_arm64.so,sha256=DFIYqNcuRxiZ8_jrYoaRB3Dx9GrY7UBXscwXQvV4k3I,13528
111
112
  pyhw/library/test/iokitCPULibTest.py,sha256=BrhMypgfJTeMectpDc9Tmwzp8gYwYAcowaTFf72LlLE,311
112
113
  pyhw/library/test/iokitHostLibTest.py,sha256=oz5x1g4WMdoikU3Eo6zoxcHZ4e-UMRhXg0C0Lflo-ac,272
114
+ pyhw/library/test/iokitNICLibTest.py,sha256=ROjfJf0ocWvRFueIyRBQ4Y0V7stlMNiAADIM3fMy7YY,2947
113
115
  pyhw/library/test/nvmlGPULibTest.py,sha256=F4AjQGZDNj29fRtxvy41zCSFi2Eirp0CQSYuxuw0n60,785
114
116
  pyhw/pyhwException/__init__.py,sha256=juw4PdgPa-eLy0y678BQ7_Ck-BJa-P0LHyKCGePazb8,221
115
117
  pyhw/pyhwException/pyhwException.py,sha256=wxuzFQa9g7XB1q9TUKO_55lw7wMEJMpzG8w1GVTFVa0,197
@@ -118,9 +120,9 @@ pyhw/pyhwUtil/cliUtil.py,sha256=IUcWun5nDwQb20Qe8YefS5j3Jji8a-F41Qd9QwCf0h0,2454
118
120
  pyhw/pyhwUtil/pciUtil.py,sha256=WAluDRDb-gUbqhvSIusFzPrf6r98EkrNEAwbPyMwrTc,202
119
121
  pyhw/pyhwUtil/pyhwUtil.py,sha256=V3M6X9eTirwnwwRiSJaLUWrZKZYMbRihARJVQc879P8,8364
120
122
  pyhw/pyhwUtil/sysctlUtil.py,sha256=S-rUvqi7ZrMyMouIhxlyHEQ4agM7sCT1Y7uzs3Hu5-o,841
121
- pyhw-0.14.1.dist-info/licenses/LICENSE,sha256=hJs6RBqSVCexbTsalkMLNFI5t06kekQEsSVaOt_-yLs,1497
122
- pyhw-0.14.1.dist-info/METADATA,sha256=Hp0gBd0ADXGPYCifzHvy0BSo_yW7HIjblMKu10JAjmk,7715
123
- pyhw-0.14.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
124
- pyhw-0.14.1.dist-info/entry_points.txt,sha256=q-AB8im_QahpmNrmy4aPTJRGi0LlbNlnI3kF7s6pKss,44
125
- pyhw-0.14.1.dist-info/top_level.txt,sha256=7Inxvxt1TngEricKZEex9_WJZS3DbKYFUXDz4v5WHYU,5
126
- pyhw-0.14.1.dist-info/RECORD,,
123
+ pyhw-0.14.2.dist-info/licenses/LICENSE,sha256=hJs6RBqSVCexbTsalkMLNFI5t06kekQEsSVaOt_-yLs,1497
124
+ pyhw-0.14.2.dist-info/METADATA,sha256=r1weeDXKC898D-9W4KYZU2vIaw7RalSipTT_tcgTCog,7715
125
+ pyhw-0.14.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
126
+ pyhw-0.14.2.dist-info/entry_points.txt,sha256=q-AB8im_QahpmNrmy4aPTJRGi0LlbNlnI3kF7s6pKss,44
127
+ pyhw-0.14.2.dist-info/top_level.txt,sha256=7Inxvxt1TngEricKZEex9_WJZS3DbKYFUXDz4v5WHYU,5
128
+ pyhw-0.14.2.dist-info/RECORD,,
File without changes