hwdetect 1.0.0__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.
- hwdetect-1.0.0/PKG-INFO +7 -0
- hwdetect-1.0.0/README.md +31 -0
- hwdetect-1.0.0/hwdetect/__init__.py +0 -0
- hwdetect-1.0.0/hwdetect/hardware_detect_base +0 -0
- hwdetect-1.0.0/hwdetect/hardware_detect_base.c +180 -0
- hwdetect-1.0.0/hwdetect/hardware_detect_base_py.py +154 -0
- hwdetect-1.0.0/hwdetect/main.py +52 -0
- hwdetect-1.0.0/hwdetect.egg-info/PKG-INFO +7 -0
- hwdetect-1.0.0/hwdetect.egg-info/SOURCES.txt +12 -0
- hwdetect-1.0.0/hwdetect.egg-info/dependency_links.txt +1 -0
- hwdetect-1.0.0/hwdetect.egg-info/entry_points.txt +2 -0
- hwdetect-1.0.0/hwdetect.egg-info/top_level.txt +1 -0
- hwdetect-1.0.0/setup.cfg +4 -0
- hwdetect-1.0.0/setup.py +41 -0
hwdetect-1.0.0/PKG-INFO
ADDED
hwdetect-1.0.0/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
sudo apt update
|
|
2
|
+
sudo apt install python3-pip
|
|
3
|
+
|
|
4
|
+
python3 -m pip install -e .
|
|
5
|
+
|
|
6
|
+
pip3 install -e .
|
|
7
|
+
|
|
8
|
+
# Install the package locally in editable mode (great for testing)
|
|
9
|
+
pip install -e .
|
|
10
|
+
|
|
11
|
+
# OR install it normally
|
|
12
|
+
pip install .
|
|
13
|
+
|
|
14
|
+
hwdetect
|
|
15
|
+
|
|
16
|
+
# 1. Create a virtual environment named "venv"
|
|
17
|
+
python3 -m venv venv
|
|
18
|
+
|
|
19
|
+
# 2. Activate the virtual environment
|
|
20
|
+
source venv/bin/activate
|
|
21
|
+
|
|
22
|
+
# 3. Now install your package
|
|
23
|
+
pip install -e .
|
|
24
|
+
|
|
25
|
+
sudo apt install python3.14-venv
|
|
26
|
+
|
|
27
|
+
python3 -m venv venv
|
|
28
|
+
|
|
29
|
+
source venv/bin/activate
|
|
30
|
+
|
|
31
|
+
pip install -e .
|
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* hardware_detect_base.c
|
|
3
|
+
* Compile: gcc -O2 hardware_detect_base.c -o hardware_detect_base
|
|
4
|
+
* Run: ./hardware_detect_base
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
#include <cpuid.h>
|
|
11
|
+
#include <sys/utsname.h>
|
|
12
|
+
#include <sys/sysinfo.h>
|
|
13
|
+
#include <unistd.h>
|
|
14
|
+
#include <fcntl.h>
|
|
15
|
+
#include <dirent.h>
|
|
16
|
+
|
|
17
|
+
// Helper to read sysfs/proc text files safely
|
|
18
|
+
void read_sysfs_value(const char *path, char *buffer, size_t max_len) {
|
|
19
|
+
int fd = open(path, O_RDONLY);
|
|
20
|
+
if (fd < 0) {
|
|
21
|
+
snprintf(buffer, max_len, "N/A (Requires Root or Unsupported)");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
ssize_t bytes = read(fd, buffer, max_len - 1);
|
|
25
|
+
if (bytes > 0) {
|
|
26
|
+
buffer[bytes] = '\0';
|
|
27
|
+
// Strip trailing newline
|
|
28
|
+
char *newline = strchr(buffer, '\n');
|
|
29
|
+
if (newline) *newline = '\0';
|
|
30
|
+
} else {
|
|
31
|
+
snprintf(buffer, max_len, "N/A");
|
|
32
|
+
}
|
|
33
|
+
close(fd);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 1. CPU Detection using x86 CPUID Assembly & Standard Headers
|
|
37
|
+
void detect_cpu() {
|
|
38
|
+
printf("========================================\n");
|
|
39
|
+
printf(" CPU CONFIGURATION \n");
|
|
40
|
+
printf("========================================\n");
|
|
41
|
+
|
|
42
|
+
unsigned int eax, ebx, ecx, edx;
|
|
43
|
+
|
|
44
|
+
// CPU Vendor String (Leaf 0x00000000)
|
|
45
|
+
char vendor[13] = {0};
|
|
46
|
+
__cpuid(0, eax, ebx, ecx, edx);
|
|
47
|
+
*(unsigned int *)&vendor[0] = ebx;
|
|
48
|
+
*(unsigned int *)&vendor[4] = edx;
|
|
49
|
+
*(unsigned int *)&vendor[8] = ecx;
|
|
50
|
+
printf("CPU Vendor : %s\n", vendor);
|
|
51
|
+
|
|
52
|
+
// CPU Brand String via Assembly (Leaves 0x80000002, 0x80000003, 0x80000004)
|
|
53
|
+
char brand[49] = {0};
|
|
54
|
+
unsigned int *bptr = (unsigned int *)brand;
|
|
55
|
+
for (unsigned int leaf = 0x80000002; leaf <= 0x80000004; ++leaf) {
|
|
56
|
+
__cpuid(leaf, eax, ebx, ecx, edx);
|
|
57
|
+
*bptr++ = eax;
|
|
58
|
+
*bptr++ = ebx;
|
|
59
|
+
*bptr++ = ecx;
|
|
60
|
+
*bptr++ = edx;
|
|
61
|
+
}
|
|
62
|
+
printf("CPU Model : %s\n", brand[0] ? brand : "Unknown");
|
|
63
|
+
|
|
64
|
+
// Cores and Threads from system headers
|
|
65
|
+
long proc_online = sysconf(_SC_NPROCESSORS_ONLN);
|
|
66
|
+
long proc_conf = sysconf(_SC_NPROCESSORS_CONF);
|
|
67
|
+
printf("Logical Threads : %ld\n", proc_online);
|
|
68
|
+
printf("Configured Cores: %ld\n", proc_conf);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 2. RAM Detection using <sys/sysinfo.h> & /proc/meminfo
|
|
72
|
+
void detect_ram() {
|
|
73
|
+
printf("\n========================================\n");
|
|
74
|
+
printf(" RAM CONFIGURATION \n");
|
|
75
|
+
printf("========================================\n");
|
|
76
|
+
|
|
77
|
+
struct sysinfo si;
|
|
78
|
+
if (sysinfo(&si) == 0) {
|
|
79
|
+
unsigned long total_ram = (si.totalram * si.mem_unit) / (1024 * 1024);
|
|
80
|
+
unsigned long free_ram = (si.freeram * si.mem_unit) / (1024 * 1024);
|
|
81
|
+
unsigned long avail_ram = (si.freeram + si.bufferram) * si.mem_unit / (1024 * 1024);
|
|
82
|
+
|
|
83
|
+
printf("Total Memory : %lu MB (%.2f GB)\n", total_ram, total_ram / 1024.0);
|
|
84
|
+
printf("Free Memory : %lu MB\n", free_ram);
|
|
85
|
+
printf("Available Memory: %lu MB\n", avail_ram);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Module Specs via DMI Sysfs
|
|
89
|
+
char ram_type[64], ram_speed[64];
|
|
90
|
+
read_sysfs_value("/sys/class/dmi/id/memory_device_type", ram_type, sizeof(ram_type));
|
|
91
|
+
read_sysfs_value("/sys/class/dmi/id/memory_device_speed", ram_speed, sizeof(ram_speed));
|
|
92
|
+
printf("DMI Memory Type : %s\n", ram_type);
|
|
93
|
+
printf("DMI Speed : %s\n", ram_speed);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 3. Motherboard Detection via Sysfs DMI tables
|
|
97
|
+
void detect_motherboard() {
|
|
98
|
+
printf("\n========================================\n");
|
|
99
|
+
printf(" MOTHERBOARD CONFIGURATION \n");
|
|
100
|
+
printf("========================================\n");
|
|
101
|
+
|
|
102
|
+
char vendor[128], product[128], version[128], bios_ver[128];
|
|
103
|
+
read_sysfs_value("/sys/class/dmi/id/board_vendor", vendor, sizeof(vendor));
|
|
104
|
+
read_sysfs_value("/sys/class/dmi/id/board_name", product, sizeof(product));
|
|
105
|
+
read_sysfs_value("/sys/class/dmi/id/board_version", version, sizeof(version));
|
|
106
|
+
read_sysfs_value("/sys/class/dmi/id/bios_version", bios_ver, sizeof(bios_ver));
|
|
107
|
+
|
|
108
|
+
printf("Manufacturer : %s\n", vendor);
|
|
109
|
+
printf("Board Model : %s\n", product);
|
|
110
|
+
printf("Board Revision : %s\n", version);
|
|
111
|
+
printf("BIOS Version : %s\n", bios_ver);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 4. GPU Detection via PCI Bus Scanning (/sys/bus/pci/devices)
|
|
115
|
+
void detect_gpu() {
|
|
116
|
+
printf("\n========================================\n");
|
|
117
|
+
printf(" GPU CONFIGURATION \n");
|
|
118
|
+
printf("========================================\n");
|
|
119
|
+
|
|
120
|
+
DIR *dir = opendir("/sys/bus/pci/devices");
|
|
121
|
+
if (!dir) {
|
|
122
|
+
printf("Cannot access PCI bus.\n");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
struct dirent *entry;
|
|
127
|
+
int count = 0;
|
|
128
|
+
while ((entry = readdir(dir)) != NULL) {
|
|
129
|
+
if (entry->d_name[0] == '.') continue;
|
|
130
|
+
|
|
131
|
+
char class_path[512], class_buf[32] = {0};
|
|
132
|
+
snprintf(class_path, sizeof(class_path), "/sys/bus/pci/devices/%s/class", entry->d_name);
|
|
133
|
+
read_sysfs_value(class_path, class_buf, sizeof(class_buf));
|
|
134
|
+
|
|
135
|
+
// Display Controller Class Prefix: 0x030000 (VGA) or 0x030200 (3D Controller)
|
|
136
|
+
if (strncmp(class_buf, "0x03", 4) == 0) {
|
|
137
|
+
count++;
|
|
138
|
+
char vendor_path[512], device_path[512];
|
|
139
|
+
char vendor_id[32] = {0}, device_id[32] = {0};
|
|
140
|
+
|
|
141
|
+
snprintf(vendor_path, sizeof(vendor_path), "/sys/bus/pci/devices/%s/vendor", entry->d_name);
|
|
142
|
+
snprintf(device_path, sizeof(device_path), "/sys/bus/pci/devices/%s/device", entry->d_name);
|
|
143
|
+
read_sysfs_value(vendor_path, vendor_id, sizeof(vendor_id));
|
|
144
|
+
read_sysfs_value(device_path, device_id, sizeof(device_id));
|
|
145
|
+
|
|
146
|
+
printf("[GPU #%d]\n", count);
|
|
147
|
+
printf(" PCI Slot ID : %s\n", entry->d_name);
|
|
148
|
+
printf(" Vendor ID : %s\n", vendor_id);
|
|
149
|
+
printf(" Device ID : %s\n", device_id);
|
|
150
|
+
printf(" Device Class : %s\n", class_buf);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
closedir(dir);
|
|
154
|
+
if (count == 0) printf("No PCI Display Adapters found.\n");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 5. Operating System Specifications using <sys/utsname.h>
|
|
158
|
+
void detect_os() {
|
|
159
|
+
printf("\n========================================\n");
|
|
160
|
+
printf(" OS & KERNEL SPEC \n");
|
|
161
|
+
printf("========================================\n");
|
|
162
|
+
|
|
163
|
+
struct utsname os_info;
|
|
164
|
+
if (uname(&os_info) == 0) {
|
|
165
|
+
printf("OS Kernel Name : %s\n", os_info.sysname);
|
|
166
|
+
printf("Node Hostname : %s\n", os_info.nodename);
|
|
167
|
+
printf("Kernel Release : %s\n", os_info.release);
|
|
168
|
+
printf("Kernel Version : %s\n", os_info.version);
|
|
169
|
+
printf("Architecture : %s\n", os_info.machine);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
int main() {
|
|
174
|
+
detect_os();
|
|
175
|
+
detect_cpu();
|
|
176
|
+
detect_ram();
|
|
177
|
+
detect_motherboard();
|
|
178
|
+
detect_gpu();
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import glob
|
|
3
|
+
import ctypes
|
|
4
|
+
import struct
|
|
5
|
+
|
|
6
|
+
def read_file(path):
|
|
7
|
+
try:
|
|
8
|
+
with open(path, "r") as f:
|
|
9
|
+
return f.read().strip()
|
|
10
|
+
except Exception:
|
|
11
|
+
return "N/A"
|
|
12
|
+
|
|
13
|
+
# 1. OS & Kernel (via C libc uname call)
|
|
14
|
+
class UNameStruct(ctypes.Structure):
|
|
15
|
+
_fields_ = [
|
|
16
|
+
('sysname', ctypes.c_char * 65),
|
|
17
|
+
('nodename', ctypes.c_char * 65),
|
|
18
|
+
('release', ctypes.c_char * 65),
|
|
19
|
+
('version', ctypes.c_char * 65),
|
|
20
|
+
('machine', ctypes.c_char * 65),
|
|
21
|
+
('domainname', ctypes.c_char * 65)
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
def detect_os():
|
|
25
|
+
print("=" * 45)
|
|
26
|
+
print(" OS & KERNEL SPEC ")
|
|
27
|
+
print("=" * 45)
|
|
28
|
+
try:
|
|
29
|
+
libc = ctypes.CDLL("libc.so.6")
|
|
30
|
+
buf = UNameStruct()
|
|
31
|
+
if libc.uname(ctypes.byref(buf)) == 0:
|
|
32
|
+
print(f"OS Kernel Name : {buf.sysname.decode()}")
|
|
33
|
+
print(f"Hostname : {buf.nodename.decode()}")
|
|
34
|
+
print(f"Kernel Release : {buf.release.decode()}")
|
|
35
|
+
print(f"Architecture : {buf.machine.decode()}")
|
|
36
|
+
except Exception as e:
|
|
37
|
+
print(f"Could not execute libc.uname: {e}")
|
|
38
|
+
|
|
39
|
+
# 2. CPU Specs (Reading raw CPU brand/topology from kernel sysfs)
|
|
40
|
+
def detect_cpu():
|
|
41
|
+
print("\n" + "=" * 45)
|
|
42
|
+
print(" CPU CONFIGURATION ")
|
|
43
|
+
print("=" * 45)
|
|
44
|
+
|
|
45
|
+
# Read model name from sysfs/proc directly
|
|
46
|
+
cpu_model = "Unknown"
|
|
47
|
+
if os.path.exists("/proc/cpuinfo"):
|
|
48
|
+
with open("/proc/cpuinfo", "r") as f:
|
|
49
|
+
for line in f:
|
|
50
|
+
if "model name" in line:
|
|
51
|
+
cpu_model = line.split(":")[1].strip()
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
logical_threads = os.cpu_count() or 0
|
|
55
|
+
|
|
56
|
+
# Calculate physical cores by parsing core IDs
|
|
57
|
+
core_ids = set()
|
|
58
|
+
for cpu_dir in glob.glob("/sys/devices/system/cpu/cpu[0-9]*"):
|
|
59
|
+
core_id = read_file(f"{cpu_dir}/topology/core_id")
|
|
60
|
+
if core_id != "N/A":
|
|
61
|
+
core_ids.add(core_id)
|
|
62
|
+
|
|
63
|
+
physical_cores = len(core_ids) if core_ids else "N/A"
|
|
64
|
+
|
|
65
|
+
print(f"CPU Model : {cpu_model}")
|
|
66
|
+
print(f"Physical Cores : {physical_cores}")
|
|
67
|
+
print(f"Logical Threads : {logical_threads}")
|
|
68
|
+
|
|
69
|
+
# 3. RAM Specs (via libc sysinfo and /proc/meminfo)
|
|
70
|
+
class SysInfoStruct(ctypes.Structure):
|
|
71
|
+
_fields_ = [
|
|
72
|
+
('uptime', ctypes.c_long),
|
|
73
|
+
('loads', ctypes.c_ulong * 3),
|
|
74
|
+
('totalram', ctypes.c_ulong),
|
|
75
|
+
('freeram', ctypes.c_ulong),
|
|
76
|
+
('sharedram', ctypes.c_ulong),
|
|
77
|
+
('bufferram', ctypes.c_ulong),
|
|
78
|
+
('totalswap', ctypes.c_ulong),
|
|
79
|
+
('freeswap', ctypes.c_ulong),
|
|
80
|
+
('procs', ctypes.c_ushort),
|
|
81
|
+
('totalhigh', ctypes.c_ulong),
|
|
82
|
+
('freehigh', ctypes.c_ulong),
|
|
83
|
+
('mem_unit', ctypes.c_uint)
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
def detect_ram():
|
|
87
|
+
print("\n" + "=" * 45)
|
|
88
|
+
print(" RAM CONFIGURATION ")
|
|
89
|
+
print("=" * 45)
|
|
90
|
+
try:
|
|
91
|
+
libc = ctypes.CDLL("libc.so.6")
|
|
92
|
+
info = SysInfoStruct()
|
|
93
|
+
if libc.sysinfo(ctypes.byref(info)) == 0:
|
|
94
|
+
unit = info.mem_unit if info.mem_unit > 0 else 1
|
|
95
|
+
total_gb = (info.totalram * unit) / (1024 ** 3)
|
|
96
|
+
free_gb = (info.freeram * unit) / (1024 ** 3)
|
|
97
|
+
print(f"Total RAM : {total_gb:.2f} GB")
|
|
98
|
+
print(f"Free RAM : {free_gb:.2f} GB")
|
|
99
|
+
except Exception as e:
|
|
100
|
+
print(f"Error fetching memory via libc: {e}")
|
|
101
|
+
|
|
102
|
+
# Read RAM module hardware details from DMI tables
|
|
103
|
+
ram_type = read_file("/sys/class/dmi/id/memory_device_type")
|
|
104
|
+
ram_speed = read_file("/sys/class/dmi/id/memory_device_speed")
|
|
105
|
+
print(f"Memory Type : {ram_type}")
|
|
106
|
+
print(f"Memory Speed : {ram_speed}")
|
|
107
|
+
|
|
108
|
+
# 4. Motherboard Specs
|
|
109
|
+
def detect_motherboard():
|
|
110
|
+
print("\n" + "=" * 45)
|
|
111
|
+
print(" MOTHERBOARD CONFIGURATION ")
|
|
112
|
+
print("=" * 45)
|
|
113
|
+
vendor = read_file("/sys/class/dmi/id/board_vendor")
|
|
114
|
+
product = read_file("/sys/class/dmi/id/board_name")
|
|
115
|
+
version = read_file("/sys/class/dmi/id/board_version")
|
|
116
|
+
bios = read_file("/sys/class/dmi/id/bios_version")
|
|
117
|
+
|
|
118
|
+
print(f"Manufacturer : {vendor}")
|
|
119
|
+
print(f"Product Name : {product}")
|
|
120
|
+
print(f"Board Revision : {version}")
|
|
121
|
+
print(f"BIOS Version : {bios}")
|
|
122
|
+
|
|
123
|
+
# 5. GPU Specs (PCI Bus Scan via /sys/bus/pci/devices)
|
|
124
|
+
def detect_gpu():
|
|
125
|
+
print("\n" + "=" * 45)
|
|
126
|
+
print(" GPU CONFIGURATION ")
|
|
127
|
+
print("=" * 45)
|
|
128
|
+
gpu_devices = []
|
|
129
|
+
pci_devices = glob.glob("/sys/bus/pci/devices/*")
|
|
130
|
+
|
|
131
|
+
for dev in pci_devices:
|
|
132
|
+
cls = read_file(f"{dev}/class")
|
|
133
|
+
# Match PCI class 0x030000 (VGA) or 0x030200 (3D Controller)
|
|
134
|
+
if cls.startswith("0x03"):
|
|
135
|
+
vendor_id = read_file(f"{dev}/vendor")
|
|
136
|
+
device_id = read_file(f"{dev}/device")
|
|
137
|
+
gpu_devices.append((dev.split("/")[-1], vendor_id, device_id, cls))
|
|
138
|
+
|
|
139
|
+
if gpu_devices:
|
|
140
|
+
for idx, (slot, vendor, device, dev_cls) in enumerate(gpu_devices, 1):
|
|
141
|
+
print(f"[GPU #{idx}]")
|
|
142
|
+
print(f" PCI Bus Address: {slot}")
|
|
143
|
+
print(f" Vendor ID : {vendor}")
|
|
144
|
+
print(f" Device ID : {device}")
|
|
145
|
+
print(f" Class Code : {dev_cls}")
|
|
146
|
+
else:
|
|
147
|
+
print("No PCI GPU devices detected.")
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
detect_os()
|
|
151
|
+
detect_cpu()
|
|
152
|
+
detect_ram()
|
|
153
|
+
detect_motherboard()
|
|
154
|
+
detect_gpu()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import logging
|
|
4
|
+
from . import hardware_detect_base_py
|
|
5
|
+
|
|
6
|
+
# Configure Logging
|
|
7
|
+
logging.basicConfig(
|
|
8
|
+
level=logging.INFO,
|
|
9
|
+
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
10
|
+
datefmt='%Y-%m-%d %H:%M:%S'
|
|
11
|
+
)
|
|
12
|
+
logger = logging.getLogger("HWDetect")
|
|
13
|
+
|
|
14
|
+
def run_hardware_detect():
|
|
15
|
+
# Locate the directory where this package is installed
|
|
16
|
+
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
17
|
+
c_binary = os.path.join(base_dir, 'hardware_detect_base')
|
|
18
|
+
|
|
19
|
+
logger.info("Attempting to detect hardware using low-level C binary...")
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
if not os.path.exists(c_binary):
|
|
23
|
+
raise FileNotFoundError("C binary not found. It may have failed to compile during installation.")
|
|
24
|
+
|
|
25
|
+
# Execute the C binary and capture the output
|
|
26
|
+
result = subprocess.run([c_binary], capture_output=True, text=True, check=True)
|
|
27
|
+
print(result.stdout)
|
|
28
|
+
logger.info("Hardware detection completed successfully using C binary.")
|
|
29
|
+
|
|
30
|
+
except subprocess.CalledProcessError as e:
|
|
31
|
+
logger.warning(f"C binary executed but returned an error (Code {e.returncode}).")
|
|
32
|
+
logger.debug(f"C binary stderr: {e.stderr}")
|
|
33
|
+
_run_python_fallback()
|
|
34
|
+
|
|
35
|
+
except Exception as e:
|
|
36
|
+
logger.warning(f"C binary execution failed: {e}")
|
|
37
|
+
_run_python_fallback()
|
|
38
|
+
|
|
39
|
+
def _run_python_fallback():
|
|
40
|
+
logger.info("Falling back to Python-based hardware detection...")
|
|
41
|
+
try:
|
|
42
|
+
hardware_detect_base_py.detect_os()
|
|
43
|
+
hardware_detect_base_py.detect_cpu()
|
|
44
|
+
hardware_detect_base_py.detect_ram()
|
|
45
|
+
hardware_detect_base_py.detect_motherboard()
|
|
46
|
+
hardware_detect_base_py.detect_gpu()
|
|
47
|
+
logger.info("Hardware detection completed successfully using Python fallback.")
|
|
48
|
+
except Exception as e:
|
|
49
|
+
logger.error(f"Critical Failure: Python fallback also failed. Exception: {e}")
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
run_hardware_detect()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
hwdetect/__init__.py
|
|
4
|
+
hwdetect/hardware_detect_base
|
|
5
|
+
hwdetect/hardware_detect_base.c
|
|
6
|
+
hwdetect/hardware_detect_base_py.py
|
|
7
|
+
hwdetect/main.py
|
|
8
|
+
hwdetect.egg-info/PKG-INFO
|
|
9
|
+
hwdetect.egg-info/SOURCES.txt
|
|
10
|
+
hwdetect.egg-info/dependency_links.txt
|
|
11
|
+
hwdetect.egg-info/entry_points.txt
|
|
12
|
+
hwdetect.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hwdetect
|
hwdetect-1.0.0/setup.cfg
ADDED
hwdetect-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
from setuptools.command.build_py import build_py
|
|
5
|
+
|
|
6
|
+
class CustomBuildCommand(build_py):
|
|
7
|
+
"""Custom build command to compile the C source during pip install."""
|
|
8
|
+
def run(self):
|
|
9
|
+
# Paths for the C source and the output binary
|
|
10
|
+
c_source = os.path.join('hwdetect', 'hardware_detect_base.c')
|
|
11
|
+
c_binary = os.path.join('hwdetect', 'hardware_detect_base')
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
print(f"Compiling {c_source} using GCC...")
|
|
15
|
+
subprocess.check_call(['gcc', '-O2', c_source, '-o', c_binary])
|
|
16
|
+
print("C binary compiled successfully.")
|
|
17
|
+
except Exception as e:
|
|
18
|
+
print(f"WARNING: Failed to compile C source. The package will rely on the Python fallback. Error: {e}")
|
|
19
|
+
|
|
20
|
+
# Continue with the standard Python package build process
|
|
21
|
+
super().run()
|
|
22
|
+
|
|
23
|
+
setup(
|
|
24
|
+
name="hwdetect",
|
|
25
|
+
version="1.0.0",
|
|
26
|
+
description="A hybrid C/Python hardware detection package.",
|
|
27
|
+
author="codingmaster24",
|
|
28
|
+
packages=find_packages(),
|
|
29
|
+
# Ensure the compiled binary is included in the final package
|
|
30
|
+
package_data={'hwdetect': ['hardware_detect_base', 'hardware_detect_base.c']},
|
|
31
|
+
include_package_data=True,
|
|
32
|
+
cmdclass={
|
|
33
|
+
'build_py': CustomBuildCommand,
|
|
34
|
+
},
|
|
35
|
+
# This creates a terminal command you can run from anywhere
|
|
36
|
+
entry_points={
|
|
37
|
+
'console_scripts': [
|
|
38
|
+
'hwdetect=hwdetect.main:run_hardware_detect',
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
)
|