Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/package-validation-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ permissions:

env:
MAIN_PYTHON_VERSION: 3.12
# Lowest interpreter allowed by requires-python in pyproject.toml.
MIN_PYTHON_VERSION: "3.10"

jobs:
build-package:
Expand Down Expand Up @@ -69,3 +71,47 @@ jobs:
run: |
.venv/bin/codecarbon --help
.venv/bin/python -c "from codecarbon import EmissionsTracker; print('Package import successful')"

# Proves `pip install codecarbon` works with only the declared runtime
# dependencies (no dev group, no extras), on the oldest supported
# interpreter. The job above installs the dev group first, so it cannot
# catch a runtime dependency that is declared nowhere but the lockfile.
bare-install-smoke:
runs-on: ubuntu-24.04
needs: [build-package]
steps:
- name: Install uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
with:
version: "latest"
- name: Download built package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: pypi_dist
path: dist
- name: Install wheel into a bare virtualenv
run: |
uv venv --python ${{ env.MIN_PYTHON_VERSION }} .venv
uv pip install --python .venv/bin/python dist/*.whl
- name: Smoke test
env:
CODECARBON_ALLOW_MULTIPLE_RUNS: "True"
run: |
.venv/bin/python -c "import codecarbon; print(codecarbon.__version__)"
.venv/bin/codecarbon --help
.venv/bin/python -c "
import time
from codecarbon import OfflineEmissionsTracker
tracker = OfflineEmissionsTracker(country_iso_code='FRA', measure_power_secs=1)
tracker.start()
time.sleep(2)
emissions = tracker.stop()
print('emissions:', emissions)
# stop() returns None on every internal give-up path (tracker never
# started, another instance holding the lock, engine init failed), so
# a bare call would print None and still exit 0. Assert the shape, not
# the magnitude: a runner with no RAPL falls back to constant CPU
# power and 0.0 over 2s is a legitimate result.
assert isinstance(emissions, float), f'tracker.stop() returned {emissions!r}'
assert emissions >= 0.0, emissions
"
4 changes: 4 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ on:
paths:
- "codecarbon/**"
- "pyproject.toml"
- ".github/workflows/package.yml"
- ".github/workflows/package-validation-reusable.yml"
branches: [master]
push:
paths:
- "codecarbon/**"
- "pyproject.toml"
- ".github/workflows/package.yml"
- ".github/workflows/package-validation-reusable.yml"
branches: [master]
jobs:
validate-package:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ jobs:
CODECARBON_API_KEY: ${{ secrets.CODECARBON_API_TOKEN }}
CODECARBON_EXPERIMENT_ID: ${{ secrets.CODECARBON_EXPERIMENT_ID_TEST_PACKAGE }}
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13", "3.14"]
# Must cover every version allowed by requires-python / classifiers
# in pyproject.toml.
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
Expand Down
9 changes: 9 additions & 0 deletions tests/test_gpu_amd.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,15 @@ def _patched_import(name, *args, **kwargs):
sys.modules.pop("amdsmi", None)
sys.modules.pop("codecarbon.core.gpu_amd", None)
sys.modules.update(saved)
# importlib also rebinds the submodule attribute on the parent
# package, and restoring sys.modules alone does not undo that.
# On Python < 3.12 mock.patch resolves "codecarbon.core.gpu_amd.x"
# through that attribute, so a stale binding would send later
# patches to the throwaway module. Put the real one back.
if "codecarbon.core.gpu_amd" in saved:
import codecarbon.core

codecarbon.core.gpu_amd = saved["codecarbon.core.gpu_amd"]

def test_oserror_sets_amdsmi_unavailable(self):
"""OSError during amdsmi import (e.g. missing libamd_smi.so) must disable AMD GPU support."""
Expand Down
Loading