From 738b812a1a3bc5d23965c6d5bfdd81a488dcabbf Mon Sep 17 00:00:00 2001 From: davidberenstein1957 Date: Tue, 19 May 2026 20:49:38 +0200 Subject: [PATCH 1/4] fix: handle amdsmi load failures when libamd_smi is missing When the amdsmi Python package is installed without ROCm (e.g. on macOS), import can raise KeyError while resolving libamd_smi.so. Treat AttributeError, OSError, and KeyError like a broken install: disable AMD metrics and warn instead of crashing the CodeCarbon CLI on import. --- codecarbon/core/gpu_amd.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/codecarbon/core/gpu_amd.py b/codecarbon/core/gpu_amd.py index 6cff5a287..9b1b3ddc1 100644 --- a/codecarbon/core/gpu_amd.py +++ b/codecarbon/core/gpu_amd.py @@ -28,14 +28,12 @@ def is_rocm_system(): "Please install amdsmi to get GPU metrics." ) AMDSMI_AVAILABLE = False -except AttributeError as e: +except (AttributeError, OSError, KeyError) as error: amdsmi = None - # In some environments, amdsmi may be present but not properly configured, leading to AttributeError when importing logger.warning( - "AMD GPU detected but amdsmi is not properly configured. " - "Please ensure amdsmi is correctly installed to get GPU metrics." - "Tips : check consistency between Python amdsmi package and ROCm versions, and ensure AMD drivers are up to date." - f" Error: {e}" + "amdsmi is installed but could not load libamd_smi (ROCm drivers missing " + "or incompatible). AMD GPU metrics will be unavailable. Error: %s", + error, ) AMDSMI_AVAILABLE = False From ef18da7a157369c32c57474fd0c8ec2dd897b520 Mon Sep 17 00:00:00 2001 From: davidberenstein1957 Date: Tue, 19 May 2026 20:51:35 +0200 Subject: [PATCH 2/4] fix(gpu_amd): only extend amdsmi import except types Keep original warning message and comment; catch OSError and KeyError when libamd_smi fails to load (e.g. macOS with amdsmi wheel but no ROCm). Co-authored-by: Cursor --- codecarbon/core/gpu_amd.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/codecarbon/core/gpu_amd.py b/codecarbon/core/gpu_amd.py index 9b1b3ddc1..bd8eeb226 100644 --- a/codecarbon/core/gpu_amd.py +++ b/codecarbon/core/gpu_amd.py @@ -28,12 +28,14 @@ def is_rocm_system(): "Please install amdsmi to get GPU metrics." ) AMDSMI_AVAILABLE = False -except (AttributeError, OSError, KeyError) as error: +except (AttributeError, OSError, KeyError) as e: amdsmi = None + # In some environments, amdsmi may be present but not properly configured, leading to AttributeError when importing logger.warning( - "amdsmi is installed but could not load libamd_smi (ROCm drivers missing " - "or incompatible). AMD GPU metrics will be unavailable. Error: %s", - error, + "AMD GPU detected but amdsmi is not properly configured. " + "Please ensure amdsmi is correctly installed to get GPU metrics." + "Tips : check consistency between Python amdsmi package and ROCm versions, and ensure AMD drivers are up to date." + f" Error: {e}" ) AMDSMI_AVAILABLE = False From 241e498db409241ab4ae885bdd18afac7a97289d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 May 2026 10:19:55 +0000 Subject: [PATCH 3/4] test: add coverage for OSError/KeyError/AttributeError amdsmi import failures Agent-Logs-Url: https://github.com/mlco2/codecarbon/sessions/009db467-8429-4146-8907-bcbd0a16593b Co-authored-by: benoit-cty <6603048+benoit-cty@users.noreply.github.com> --- tests/test_gpu_amd.py | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/test_gpu_amd.py b/tests/test_gpu_amd.py index 72b39e54b..6a3488bbf 100644 --- a/tests/test_gpu_amd.py +++ b/tests/test_gpu_amd.py @@ -395,6 +395,75 @@ def test_get_compute_and_graphics_processes(self): assert device._get_graphics_processes() == [] +class TestAmdsmiImportFailures: + """Tests for module-level amdsmi import error handling in gpu_amd.py.""" + + def _import_gpu_amd_with_amdsmi_error(self, error_to_raise): + """ + Simulate a fresh import of codecarbon.core.gpu_amd where importing amdsmi + raises *error_to_raise*. Returns the freshly imported module object. + """ + import builtins + import importlib + import sys + + # Remove cached modules so the module body is re-executed + saved = {} + for name in ("amdsmi", "codecarbon.core.gpu_amd"): + if name in sys.modules: + saved[name] = sys.modules.pop(name) + + _real_import = builtins.__import__ + + def _patched_import(name, *args, **kwargs): + if name == "amdsmi": + raise error_to_raise + return _real_import(name, *args, **kwargs) + + try: + with mock.patch("builtins.__import__", side_effect=_patched_import): + module = importlib.import_module("codecarbon.core.gpu_amd") + return module + finally: + # Drop the freshly created module entries and restore original state + sys.modules.pop("amdsmi", None) + sys.modules.pop("codecarbon.core.gpu_amd", None) + sys.modules.update(saved) + + def test_oserror_sets_amdsmi_unavailable(self): + """OSError during amdsmi import (e.g. missing libamd_smi.so) must disable AMD GPU support.""" + module = self._import_gpu_amd_with_amdsmi_error( + OSError("libamd_smi.so: cannot open shared object file: No such file or directory") + ) + assert module.amdsmi is None + assert module.AMDSMI_AVAILABLE is False + + def test_keyerror_sets_amdsmi_unavailable(self): + """KeyError during amdsmi import (e.g. macOS with amdsmi installed but no ROCm) must disable AMD GPU support.""" + module = self._import_gpu_amd_with_amdsmi_error(KeyError("missing_rocm_key")) + assert module.amdsmi is None + assert module.AMDSMI_AVAILABLE is False + + def test_attributeerror_sets_amdsmi_unavailable(self): + """AttributeError during amdsmi import must disable AMD GPU support.""" + module = self._import_gpu_amd_with_amdsmi_error( + AttributeError("module 'amdsmi' has no attribute 'amdsmi_init'") + ) + assert module.amdsmi is None + assert module.AMDSMI_AVAILABLE is False + + def test_import_failure_logs_warning(self): + """Each import-time failure (OSError/KeyError/AttributeError) must log a warning.""" + for error in ( + OSError("libamd_smi.so not found"), + KeyError("rocm_key"), + AttributeError("missing attr"), + ): + with mock.patch("codecarbon.external.logger.logger.warning") as warning_mock: + self._import_gpu_amd_with_amdsmi_error(error) + warning_mock.assert_called() + + class TestAllGPUDevicesAmd: def test_init_with_no_amd_handles(self): from codecarbon.core.gpu import AllGPUDevices From ba1565fd487effcdc43f70022e4361977c870526 Mon Sep 17 00:00:00 2001 From: benoit-cty Date: Wed, 20 May 2026 14:45:05 +0200 Subject: [PATCH 4/4] run precommit --- tests/test_gpu_amd.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_gpu_amd.py b/tests/test_gpu_amd.py index 6a3488bbf..e066ee657 100644 --- a/tests/test_gpu_amd.py +++ b/tests/test_gpu_amd.py @@ -433,7 +433,9 @@ def _patched_import(name, *args, **kwargs): def test_oserror_sets_amdsmi_unavailable(self): """OSError during amdsmi import (e.g. missing libamd_smi.so) must disable AMD GPU support.""" module = self._import_gpu_amd_with_amdsmi_error( - OSError("libamd_smi.so: cannot open shared object file: No such file or directory") + OSError( + "libamd_smi.so: cannot open shared object file: No such file or directory" + ) ) assert module.amdsmi is None assert module.AMDSMI_AVAILABLE is False @@ -459,7 +461,9 @@ def test_import_failure_logs_warning(self): KeyError("rocm_key"), AttributeError("missing attr"), ): - with mock.patch("codecarbon.external.logger.logger.warning") as warning_mock: + with mock.patch( + "codecarbon.external.logger.logger.warning" + ) as warning_mock: self._import_gpu_amd_with_amdsmi_error(error) warning_mock.assert_called()