Skip to content

Commit 7bbe9b2

Browse files
Arnobenoit-cty
authored andcommitted
fix: add tests for psutil availability and physical cpu count
1 parent 0d06e9c commit 7bbe9b2

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

codecarbon/core/util.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,26 +121,37 @@ def count_physical_cpus():
121121
)
122122
return 1
123123

124+
124125
def _windows_get_physical_sockets():
125126
try:
126127
# use PowerShell to count number of objects of class Win32_Processor
127-
cmd = ["powershell", "-NoProfile", "-Command", "(Get-CimInstance -ClassName Win32_Processor).Count"]
128-
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10, check=True)
128+
cmd = [
129+
"powershell",
130+
"-NoProfile",
131+
"-Command",
132+
"(Get-CimInstance -ClassName Win32_Processor).Count",
133+
]
134+
result = subprocess.run(
135+
cmd, capture_output=True, text=True, timeout=10, check=True
136+
)
129137

130138
output = result.stdout.strip()
131139

132-
# Fallback: if Count is empty, at least one socket exists
140+
# Fallback: if empty, at least one socket exists
133141
if not output:
134-
logger.debug("PowerShell command returned empty output for socket count. Defaulting to 1.")
135-
output = 1
142+
logger.debug(
143+
"PowerShell command returned empty output for socket count. Defaulting to 1."
144+
)
145+
output = 1
136146

137147
logger.debug(f"Detected {output} physical sockets on Windows.")
138148
return int(output)
139149

140150
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, ValueError) as e:
141151
logger.error(f"Error detecting physical sockets on Windows: {e}")
142152
return 1 # Fallback:at least one socket
143-
153+
154+
144155
def count_cpus() -> int:
145156
if SLURM_JOB_ID is None:
146157
return psutil.cpu_count()

tests/test_cpu.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,28 @@
1111
IntelPowerGadget,
1212
IntelRAPL,
1313
is_powergadget_available,
14+
is_psutil_available,
1415
)
1516
from codecarbon.core.units import Energy, Power, Time
1617
from codecarbon.core.util import count_physical_cpus
1718
from codecarbon.external.hardware import CPU
1819
from codecarbon.input import DataSource
1920

2021

22+
class TestCPU(unittest.TestCase):
23+
def test_is_psutil_available(self):
24+
@mock.patch("psutil.cpu_times")
25+
def test_is_psutil_available(self, mock_cpu_times):
26+
# Test when psutil is available
27+
mock_cpu_times.return_value = mock.Mock()
28+
self.assertTrue(is_psutil_available()) # noqa: E712
29+
30+
@mock.patch("psutil.cpu_times", side_effect=AttributeError)
31+
def test_is_psutil_not_available(self, mock_cpu_times):
32+
# Test when psutil is not available
33+
self.assertFalse(is_psutil_available()) # noqa: E712
34+
35+
2136
class TestIntelPowerGadget(unittest.TestCase):
2237
@pytest.mark.integ_test
2338
def test_intel_power_gadget(self):
@@ -306,10 +321,15 @@ def test_get_matching_cpu(self):
306321
class TestPhysicalCPU(unittest.TestCase):
307322
def test_count_physical_cpus_windows(self):
308323
with mock.patch("platform.system", return_value="Windows"):
309-
with mock.patch.dict(os.environ, {"NUMBER_OF_PROCESSORS": "4"}):
324+
325+
with mock.patch(
326+
"subprocess.run", return_value=mock.Mock(returncode=0, stdout="4")
327+
):
310328
assert count_physical_cpus() == 4
311329

312-
with mock.patch.dict(os.environ, {}, clear=True):
330+
with mock.patch(
331+
"subprocess.run", return_value=mock.Mock(returncode=0, stdout="")
332+
):
313333
assert count_physical_cpus() == 1
314334

315335
def test_count_physical_cpus_linux(self):

0 commit comments

Comments
 (0)