From 627ec64fc19ddd10de7631cfa7153bf83eec3086 Mon Sep 17 00:00:00 2001 From: Snailed Date: Wed, 5 Feb 2025 15:00:31 +0100 Subject: [PATCH 1/8] Fix DRAM measurements --- carbontracker/components/cpu/intel.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/carbontracker/components/cpu/intel.py b/carbontracker/components/cpu/intel.py index c234b22..529436a 100644 --- a/carbontracker/components/cpu/intel.py +++ b/carbontracker/components/cpu/intel.py @@ -82,9 +82,11 @@ def _get_measurements(self): return measurements - def _convert_rapl_name(self, name, pattern) -> Union[None, str]: - if re.match(pattern, name): - return "cpu:" + name[-1] + def _convert_rapl_name(self, package, name, pattern) -> Union[None, str]: + match = re.match(pattern, package) + name = name if "package" not in name else "cpu" + if match: + return name + ":" + match.group(1) def init(self): # Get amount of intel-rapl folders @@ -93,15 +95,15 @@ def init(self): self._devices: List[str] = [] self._rapl_devices: List[str] = [] self.parts_pattern = re.compile(r"intel-rapl:(\d):(\d)") - devices_pattern = re.compile("intel-rapl:.") + devices_pattern = re.compile("intel-rapl:(\d)(:\d)?") for package in packages: if re.fullmatch(devices_pattern, package): with open(os.path.join(RAPL_DIR, package, "name"), "r") as f: name = f.read().strip() - if name != "psys": + if name != "psys" and ("package" in name or "dram" in name): self._rapl_devices.append(package) - rapl_name = self._convert_rapl_name(package, devices_pattern) + rapl_name = self._convert_rapl_name(package, name, devices_pattern) if rapl_name is not None: self._devices.append(rapl_name) From 1bc0854da3c4b04e26a0ef353600532a1d847235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Hag=20L=C3=B8vstad?= Date: Wed, 5 Feb 2025 15:28:41 +0100 Subject: [PATCH 2/8] fix malformed regex and fixed tests --- carbontracker/components/cpu/intel.py | 2 +- tests/components/test_intel.py | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/carbontracker/components/cpu/intel.py b/carbontracker/components/cpu/intel.py index 529436a..5d4bfe3 100644 --- a/carbontracker/components/cpu/intel.py +++ b/carbontracker/components/cpu/intel.py @@ -95,7 +95,7 @@ def init(self): self._devices: List[str] = [] self._rapl_devices: List[str] = [] self.parts_pattern = re.compile(r"intel-rapl:(\d):(\d)") - devices_pattern = re.compile("intel-rapl:(\d)(:\d)?") + devices_pattern = re.compile(r"intel-rapl:(\d)(:\d)?") for package in packages: if re.fullmatch(devices_pattern, package): diff --git a/tests/components/test_intel.py b/tests/components/test_intel.py index 17f317e..9a48dd8 100644 --- a/tests/components/test_intel.py +++ b/tests/components/test_intel.py @@ -21,6 +21,7 @@ def test_available(self, mock_listdir, mock_exists): def test_devices(self, mock_file, mock_listdir, mock_exists): mock_exists.return_value = True mock_listdir.side_effect = [["intel-rapl:0", "intel-rapl:1"], ["name"], ["name"]] + mock_file.return_value.read.side_effect = ["package-0", "package-1"] cpu = IntelCPU(pids=[], devices_by_pid={}) cpu.init() @@ -72,14 +73,18 @@ def test__read_energy(self, mock_file): @patch("builtins.open", new_callable=mock_open) def test__get_measurements(self, mock_file, mock_listdir, mock_exists): mock_exists.return_value = True - mock_listdir.return_value = ["intel-rapl:0", "intel-rapl:1"] - mock_file.return_value.read.return_value = "1000000" + # Simulate true RAPL zone hierarchy + mock_listdir.return_value = ["intel-rapl:0", "intel-rapl:0:0", "intel-rapl:0:1", "intel-rapl:0:2","intel-rapl:1"] + #mock_file.return_value.read.return_value = "1000000" + mock_file.return_value.read.side_effect = ["package-0", "cores", "uncores", "dram", "psys", "1000000", "99999", "88", "88", "88"] cpu = IntelCPU(pids=[], devices_by_pid={}) cpu.init() measurements = cpu._get_measurements() - self.assertEqual(measurements, [1000000, 1000000]) + self.assertEqual(measurements, [1000000, 99999]) + self.assertEqual(cpu._rapl_devices, ["intel-rapl:0", "intel-rapl:0:2"]) # Only package and dram zones are considered, the rest are included in package + self.assertEqual(cpu._devices, ["cpu:0", "dram:0"]) @patch("os.listdir") @patch("builtins.open", new_callable=mock_open, read_data="cpu") @@ -89,7 +94,17 @@ def test__convert_rapl_name(self, mock_file, mock_listdir): cpu = IntelCPU(pids=[], devices_by_pid={}) cpu.init() - self.assertEqual(cpu._convert_rapl_name("intel-rapl:0", re.compile("intel-rapl:.")), "cpu:0") + self.assertEqual(cpu._convert_rapl_name("intel-rapl:0", "package-0", re.compile(r"intel-rapl:(\d)(:\d)?")), "cpu:0") + + @patch("os.listdir") + @patch("builtins.open", new_callable=mock_open, read_data="cpu") + def test__convert_rapl_name_dram(self, mock_file, mock_listdir): + mock_listdir.return_value = ["intel-rapl:0", "intel-rapl:1"] + + cpu = IntelCPU(pids=[], devices_by_pid={}) + cpu.init() + + self.assertEqual(cpu._convert_rapl_name("intel-rapl:1", "dram", re.compile(r"intel-rapl:(\d)(:\d)?")), "dram:1") @patch("os.path.exists") @patch("os.listdir") @@ -97,6 +112,7 @@ def test__convert_rapl_name(self, mock_file, mock_listdir): def test_init(self, mock_file, mock_listdir, mock_exists): mock_exists.return_value = True mock_listdir.return_value = ["intel-rapl:0", "intel-rapl:1"] + mock_file.return_value.read.side_effect = ["package-0", "package-1"] cpu = IntelCPU(pids=[], devices_by_pid={}) cpu.init() From 80c85d36ea0c6d6df602b8083a11e841f5976faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 10:51:04 +0100 Subject: [PATCH 3/8] Fix CI --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6ddad72..c8c015f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8','3.9', '3.10', '3.11', '3.12'] + python-version: ['3.7.17', '3.8.18','3.9.21', '3.10.16', '3.11.11', '3.12.9'] # Latest version available for each. Ref: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json steps: - uses: actions/checkout@v3 From deaad938f4994b02a97fb15ef152ebda20371497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 10:52:41 +0100 Subject: [PATCH 4/8] Upgrade to setup-python@v5 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c8c015f..059f6c8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From f7c5848b4c09132023a5ccec259c91c29e200377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 11:20:47 +0100 Subject: [PATCH 5/8] Downgrade ubuntu version to fix setup-python --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 059f6c8..419098a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: matrix: python-version: ['3.7.17', '3.8.18','3.9.21', '3.10.16', '3.11.11', '3.12.9'] # Latest version available for each. Ref: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json From 335efe3bc73a588607fa26a6ff9a3a032f913f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Hag=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 12:42:43 +0100 Subject: [PATCH 6/8] improved error message for RAPL permission issues --- carbontracker/components/component.py | 24 ++++++++++++++---------- carbontracker/components/cpu/intel.py | 6 ++++-- carbontracker/exceptions.py | 3 ++- carbontracker/tracker.py | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/carbontracker/components/component.py b/carbontracker/components/component.py index 94a19a0..2b1a081 100644 --- a/carbontracker/components/component.py +++ b/carbontracker/components/component.py @@ -9,6 +9,8 @@ ) from carbontracker.components.handler import Handler from typing import Iterable, List, Union, Type, Sized +from carbontracker.loggerutil import Logger +import os COMPONENTS = [ { @@ -43,7 +45,7 @@ def handlers_by_name(name) -> List[Type[Handler]]: class Component: - def __init__(self, name: str, pids: Iterable[int], devices_by_pid: bool): + def __init__(self, name: str, pids: Iterable[int], devices_by_pid: bool, logger: Logger): self.name = name if name not in component_names(): raise exceptions.ComponentNameError( @@ -54,6 +56,7 @@ def __init__(self, name: str, pids: Iterable[int], devices_by_pid: bool): ) self.power_usages: List[List[float]] = [] self.cur_epoch: int = -1 # Sentry + self.logger = logger @property def handler(self) -> Handler: @@ -97,18 +100,19 @@ def collect_power_usage(self, epoch: int): self.power_usages.append([]) try: self.power_usages[-1] += self.handler.power_usage() - except exceptions.IntelRaplPermissionError: + except exceptions.IntelRaplPermissionError as e: + energy_paths = " and ".join(e.file_names) + commands = ["sudo chmod +r " + energy_path for energy_path in e.file_names] # Only raise error if no measurements have been collected. if not self.power_usages[-1]: - print( - "No sudo access to read Intel's RAPL measurements from the energy_uj file." - "\nSee issue: https://github.com/lfwa/carbontracker/issues/40" - ) + self.logger.err_critical( + f"Could not read CPU/DRAM energy consumption due to lack of read-permissions.\n\tPlease run the following command(s): \n\t\t{"\n\t\t".join(commands)}" + ) # Append zero measurement to avoid further errors. self.power_usages.append([0]) except exceptions.GPUPowerUsageRetrievalError: if not self.power_usages[-1]: - print( + self.logger.err_critical( "GPU model does not support retrieval of power usages in NVML." "\nSee issue: https://github.com/lfwa/carbontracker/issues/36" ) @@ -154,16 +158,16 @@ def shutdown(self): def create_components( - components: str, pids: Iterable[int], devices_by_pid: bool + components: str, pids: Iterable[int], devices_by_pid: bool, logger: Logger ) -> List[Component]: components = components.strip().replace(" ", "").lower() if components == "all": return [ - Component(name=comp_name, pids=pids, devices_by_pid=devices_by_pid) + Component(name=comp_name, pids=pids, devices_by_pid=devices_by_pid, logger=logger) for comp_name in component_names() ] else: return [ - Component(name=comp_name, pids=pids, devices_by_pid=devices_by_pid) + Component(name=comp_name, pids=pids, devices_by_pid=devices_by_pid, logger=logger) for comp_name in components.split(",") ] diff --git a/carbontracker/components/cpu/intel.py b/carbontracker/components/cpu/intel.py index 5d4bfe3..c8b7a6f 100644 --- a/carbontracker/components/cpu/intel.py +++ b/carbontracker/components/cpu/intel.py @@ -56,6 +56,7 @@ def _read_energy(self, path: str) -> int: def _get_measurements(self): measurements = [] + permission_errors = [] for package in self._rapl_devices: try: power_usage = self._read_energy(os.path.join(RAPL_DIR, package)) @@ -63,7 +64,7 @@ def _get_measurements(self): # If there is no sudo access, we cannot read the energy_uj file. # Permission denied error is raised. except PermissionError: - raise exceptions.IntelRaplPermissionError() + permission_errors += [os.path.join(RAPL_DIR, package, "energy_uj")] except FileNotFoundError: # check cpu/gpu/dram @@ -79,7 +80,8 @@ def _get_measurements(self): ) measurements.append(total_power_usage) - + if permission_errors: + raise exceptions.IntelRaplPermissionError(permission_errors) return measurements def _convert_rapl_name(self, package, name, pattern) -> Union[None, str]: diff --git a/carbontracker/exceptions.py b/carbontracker/exceptions.py index 4b28893..20cfce7 100644 --- a/carbontracker/exceptions.py +++ b/carbontracker/exceptions.py @@ -23,7 +23,8 @@ def __init__(self, expected_unit, received_unit, message): class IntelRaplPermissionError(Exception): """Raised when an Intel RAPL permission error occurs.""" - pass + def __init__(self, file_names: list[str]): + self.file_names = file_names class GPUPowerUsageRetrievalError(Exception): diff --git a/carbontracker/tracker.py b/carbontracker/tracker.py index 80bd2fa..64ab2ec 100644 --- a/carbontracker/tracker.py +++ b/carbontracker/tracker.py @@ -340,7 +340,7 @@ def __init__( self.tracker = CarbonTrackerThread( delete=self._delete, components=component.create_components( - components=components, pids=pids, devices_by_pid=devices_by_pid + components=components, pids=pids, devices_by_pid=devices_by_pid, logger=self.logger ), logger=self.logger, ignore_errors=ignore_errors, From e537a969898f21aad629e37e86d9046cfd4152b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20Hag=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 14:16:05 +0100 Subject: [PATCH 7/8] Improved logging for RAPL permission issues and fixed tests --- carbontracker/components/component.py | 2 +- carbontracker/exceptions.py | 4 ++- tests/components/test_intel.py | 4 +-- tests/test_component.py | 44 +++++++++++++-------------- tests/test_exceptions.py | 2 +- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/carbontracker/components/component.py b/carbontracker/components/component.py index 2b1a081..9f7d2d1 100644 --- a/carbontracker/components/component.py +++ b/carbontracker/components/component.py @@ -106,7 +106,7 @@ def collect_power_usage(self, epoch: int): # Only raise error if no measurements have been collected. if not self.power_usages[-1]: self.logger.err_critical( - f"Could not read CPU/DRAM energy consumption due to lack of read-permissions.\n\tPlease run the following command(s): \n\t\t{"\n\t\t".join(commands)}" + r"Could not read CPU/DRAM energy consumption due to lack of read-permissions.\n\tPlease run the following command(s): \n\t\t" + r"\n\t\t".join(commands) ) # Append zero measurement to avoid further errors. self.power_usages.append([0]) diff --git a/carbontracker/exceptions.py b/carbontracker/exceptions.py index 20cfce7..733510f 100644 --- a/carbontracker/exceptions.py +++ b/carbontracker/exceptions.py @@ -1,3 +1,5 @@ +from typing import List + class NoComponentsAvailableError(Exception): def __init__( self, @@ -23,7 +25,7 @@ def __init__(self, expected_unit, received_unit, message): class IntelRaplPermissionError(Exception): """Raised when an Intel RAPL permission error occurs.""" - def __init__(self, file_names: list[str]): + def __init__(self, file_names: List[str]): self.file_names = file_names diff --git a/tests/components/test_intel.py b/tests/components/test_intel.py index 9a48dd8..3ed56e0 100644 --- a/tests/components/test_intel.py +++ b/tests/components/test_intel.py @@ -12,7 +12,7 @@ def test_available(self, mock_listdir, mock_exists): mock_exists.return_value = True mock_listdir.return_value = ["some_directory"] - component = Component(name='cpu', pids=[], devices_by_pid={}) + component = Component(name='cpu', pids=[], devices_by_pid={}, logger=None) self.assertTrue(component.available()) @patch("os.path.exists") @@ -35,7 +35,7 @@ def test_available_false(self, mock_available, mock_listdir, mock_exists): mock_exists.return_value = False mock_listdir.return_value = [] - cpu = Component(name='cpu', pids=[], devices_by_pid={}) + cpu = Component(name='cpu', pids=[], devices_by_pid={}, logger=None) self.assertFalse(cpu.available()) @patch("time.sleep") diff --git a/tests/test_component.py b/tests/test_component.py index 92a1cb1..33f7f0d 100644 --- a/tests/test_component.py +++ b/tests/test_component.py @@ -24,23 +24,23 @@ class TestComponent(unittest.TestCase): def test_init_valid_component( self, mock_handlers_by_name, mock_error_by_name, mock_component_names ): - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) self.assertEqual(component.name, "gpu") self.assertEqual(component._handler, mock_handlers_by_name()[0]()) def test_init_invalid_component(self): with self.assertRaises(exceptions.ComponentNameError): - Component(name="unknown", pids=[], devices_by_pid=False) + Component(name="unknown", pids=[], devices_by_pid=False, logger=None) def test_devices(self): handler_mock = MagicMock(devices=MagicMock(return_value=["Test GPU"])) - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = handler_mock self.assertEqual(component.devices(), ["Test GPU"]) def test_available_true(self): handler_mock = MagicMock(available=MagicMock(return_value=True)) - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = handler_mock self.assertTrue(component.available()) @@ -52,33 +52,33 @@ def test_available_true(self): return_value=False, ) def test_available_false(self, mock_apple_gpu_available, mock_nvidia_gpu_available): - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) self.assertFalse(component.available()) def test_collect_power_usage_no_measurement(self): handler_mock = MagicMock( - power_usage=MagicMock(side_effect=exceptions.IntelRaplPermissionError) + power_usage=MagicMock(side_effect=exceptions.IntelRaplPermissionError(file_names=["file1", "file2"])) ) - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=MagicMock(err_critical=MagicMock())) component._handler = handler_mock component.collect_power_usage(epoch=1) self.assertEqual(component.power_usages, [[], [0]]) def test_collect_power_usage_with_measurement(self): handler_mock = MagicMock(power_usage=MagicMock(return_value=[1000])) - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) component._handler = handler_mock component.collect_power_usage(epoch=1) self.assertEqual(component.power_usages, [[1000]]) def test_collect_power_usage_with_measurement_but_no_epoch(self): - power_collector = Component(name="cpu", pids=[], devices_by_pid=False) + power_collector = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) power_collector._handler = MagicMock(power_usage=MagicMock(return_value=[1000])) power_collector.collect_power_usage(epoch=0) assert len(power_collector.power_usages) == 0 def test_collect_power_usage_with_previous_measurement(self): - power_collector = Component(name="cpu", pids=[], devices_by_pid=False) + power_collector = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) power_collector._handler = MagicMock(power_usage=MagicMock(return_value=[1000])) power_collector.collect_power_usage(epoch=1) power_collector.collect_power_usage(epoch=3) @@ -88,13 +88,13 @@ def test_collect_power_usage_GPUPowerUsageRetrievalError(self): handler_mock = MagicMock( power_usage=MagicMock(side_effect=exceptions.GPUPowerUsageRetrievalError) ) - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=MagicMock(err_critical=MagicMock())) component._handler = handler_mock component.collect_power_usage(epoch=1) self.assertEqual(component.power_usages, [[], [0]]) def test_energy_usage(self): - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) component.power_usages = [[1000], [2000], [3000]] epoch_times = [1, 2, 3] energy_usages = component.energy_usage(epoch_times) @@ -104,14 +104,14 @@ def test_energy_usage(self): self.assertTrue(np.all(np.array(energy_usages) > 0)) def test_energy_usage_no_measurements(self): - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) component.power_usages = [[]] epoch_times = [1] energy_usages = component.energy_usage(epoch_times) self.assertEqual(energy_usages, [0]) def test_energy_usage_with_power_from_later_epoch(self): - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) component.power_usages = [[1000], [2000], [3000]] epoch_times = [1, 2, 3, 4] energy_usages = component.energy_usage(epoch_times) @@ -121,7 +121,7 @@ def test_energy_usage_with_power_from_later_epoch(self): ) def test_energy_usage_no_power(self): - component = Component(name="cpu", pids=[], devices_by_pid=False) + component = Component(name="cpu", pids=[], devices_by_pid=False, logger=None) component.power_usages = [[], [], [], [], []] epoch_times = [1, 2, 3, 4, 5] energy_usages = component.energy_usage(epoch_times) @@ -132,7 +132,7 @@ def test_energy_usage_no_power(self): def test_init(self): handler_mock = MagicMock() - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = handler_mock component.init() handler_mock.init.assert_called_once() @@ -144,15 +144,15 @@ def test_init(self): def test_shutdown(self): handler_mock = MagicMock() - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = handler_mock component.shutdown() handler_mock.shutdown.assert_called_once() def test_create_components(self): - gpu = create_components("gpu", pids=[], devices_by_pid=False) - cpu = create_components("cpu", pids=[], devices_by_pid=False) - all_components = create_components("all", pids=[], devices_by_pid=False) + gpu = create_components("gpu", pids=[], devices_by_pid=False, logger=None) + cpu = create_components("cpu", pids=[], devices_by_pid=False, logger=None) + all_components = create_components("all", pids=[], devices_by_pid=False, logger=None) self.assertEqual(len(gpu), 1) self.assertEqual(len(cpu), 1) self.assertEqual(len(all_components), 2) @@ -166,12 +166,12 @@ def test_error_by_name(self): ) def test_handler_property_with_handler_set(self): - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = "test" self.assertEqual(component.handler, "test") def test_handler_property_without_handler(self): - component = Component(name="gpu", pids=[], devices_by_pid=False) + component = Component(name="gpu", pids=[], devices_by_pid=False, logger=None) component._handler = None with self.assertRaises(exceptions.GPUError): component.handler() diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index a4c0992..f75582a 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -12,7 +12,7 @@ def test_unit_error(self): def test_intel_rapl_permission_error(self): with self.assertRaises(exceptions.IntelRaplPermissionError): - raise exceptions.IntelRaplPermissionError + raise exceptions.IntelRaplPermissionError(file_names=["file1", "file2"]) def test_gpu_power_usage_retrieval_error(self): with self.assertRaises(exceptions.GPUPowerUsageRetrievalError): From ea007b17092883bc31f78a395e0d82c9d200737a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20L=C3=B8vstad?= Date: Thu, 6 Feb 2025 14:36:21 +0100 Subject: [PATCH 8/8] Downgrade to ubuntu-22.04 to fix setup-python --- .github/workflows/publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 171521e..e333b69 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,7 +8,7 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: matrix: python-version: [3.7, 3.8, 3.9, '3.10', '3.11', '3.12'] @@ -30,7 +30,7 @@ jobs: lint: needs: test - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: matrix: python-version: [3.7, 3.8, 3.9, '3.10']