From 37a03f19dde8b3b9e2484aedc1bd20f494a28527 Mon Sep 17 00:00:00 2001 From: Diogo Ribeiro Date: Fri, 27 Mar 2026 11:54:34 +0000 Subject: [PATCH 1/3] fix(cli): use configured API endpoint and declare option defaults --- codecarbon/cli/main.py | 27 ++++++++++++++++++--------- codecarbon/cli/monitor.py | 3 ++- tests/cli/test_cli_main.py | 24 ++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/codecarbon/cli/main.py b/codecarbon/cli/main.py index b6e90fe76..84b241dcb 100644 --- a/codecarbon/cli/main.py +++ b/codecarbon/cli/main.py @@ -114,7 +114,8 @@ def api_get(): """ ex: test-api """ - api = ApiClient(endpoint_url=API_URL) # TODO: get endpoint from config + api_endpoint = get_api_endpoint() + api = ApiClient(endpoint_url=api_endpoint) api.set_access_token(get_access_token()) organizations = api.get_list_organizations() print(organizations) @@ -123,15 +124,18 @@ def api_get(): @codecarbon.command("login", short_help="Login to CodeCarbon") def login(): authorize() - api = ApiClient(endpoint_url=API_URL) # TODO: get endpoint from config + api_endpoint = get_api_endpoint() + api = ApiClient(endpoint_url=api_endpoint) access_token = get_access_token() api.set_access_token(access_token) api.check_auth() def get_api_key(project_id: str): + api_endpoint = get_api_endpoint() + api_endpoint = api_endpoint.rstrip("/") req = requests.post( - f"{API_URL}/projects/{project_id}/api-tokens", + f"{api_endpoint}/projects/{project_id}/api-tokens", json={ "project_id": project_id, "name": "api token", @@ -318,20 +322,25 @@ def config(): def monitor( ctx: typer.Context, measure_power_secs: Annotated[ - int, typer.Option(help="Interval between two measures.") + int, + typer.Option(default=10, help="Interval between two measures."), ] = 10, api_call_interval: Annotated[ - int, typer.Option(help="Number of measures between API calls.") + int, + typer.Option(default=30, help="Number of measures between API calls."), ] = 30, api: Annotated[ - bool, typer.Option(help="Choose to call Code Carbon API or not") + bool, + typer.Option(default=True, help="Choose to call Code Carbon API or not"), ] = True, - offline: Annotated[bool, typer.Option(help="Run in offline mode")] = False, + offline: Annotated[bool, typer.Option(default=False, help="Run in offline mode")] = False, country_iso_code: Annotated[ - str, typer.Option(help="3-letter country ISO code for offline mode") + str, + typer.Option(default=None, help="3-letter country ISO code for offline mode"), ] = None, region: Annotated[ - str, typer.Option(help="Region/province for offline mode") + str, + typer.Option(default=None, help="Region/province for offline mode"), ] = None, ): """Monitor your machine's carbon emissions.""" diff --git a/codecarbon/cli/monitor.py b/codecarbon/cli/monitor.py index ce606cfb5..811f4b79a 100644 --- a/codecarbon/cli/monitor.py +++ b/codecarbon/cli/monitor.py @@ -14,7 +14,8 @@ def run_and_monitor( ctx: typer.Context, log_level: Annotated[ - str, typer.Option(help="Log level (critical, error, warning, info, debug)") + str, + typer.Option(default="error", help="Log level (critical, error, warning, info, debug)"), ] = "error", **tracker_args, ): diff --git a/tests/cli/test_cli_main.py b/tests/cli/test_cli_main.py index d1d204cf6..fdafe4919 100644 --- a/tests/cli/test_cli_main.py +++ b/tests/cli/test_cli_main.py @@ -42,6 +42,24 @@ def test_api_get_calls_api_and_prints(monkeypatch): assert "fake-org" in result.output +def test_api_get_uses_get_api_endpoint(monkeypatch): + call_info = {} + + class CustomApiClient(FakeApiClient): + def __init__(self, endpoint_url=None): + call_info["endpoint_url"] = endpoint_url + super().__init__(endpoint_url=endpoint_url) + + runner = CliRunner() + monkeypatch.setattr(cli_main, "ApiClient", CustomApiClient) + monkeypatch.setattr(cli_main, "get_api_endpoint", lambda: "https://custom.codecarbon.io") + monkeypatch.setattr(cli_main, "get_access_token", fake_get_access_token) + + result = runner.invoke(cli_main.codecarbon, ["test-api"]) + assert result.exit_code == 0 + assert call_info["endpoint_url"] == "https://custom.codecarbon.io" + + def test_monitor_offline_requires_country_iso_code(): runner = CliRunner() result = runner.invoke(cli_main.codecarbon, ["monitor", "--offline"]) @@ -133,11 +151,11 @@ def fake_cli(): def test_login_calls_authorize_and_auth_check(monkeypatch): - calls = {"authorize": 0, "set_token": None, "check_auth": 0} + calls = {"authorize": 0, "set_token": None, "check_auth": 0, "endpoint_url": None} class FakeApiClient: def __init__(self, endpoint_url=None): - self.endpoint_url = endpoint_url + calls["endpoint_url"] = endpoint_url def set_access_token(self, token): calls["set_token"] = token @@ -151,6 +169,7 @@ def check_auth(self): "authorize", lambda: calls.__setitem__("authorize", calls["authorize"] + 1), ) + monkeypatch.setattr(cli_main, "get_api_endpoint", lambda: "https://custom-login.codecarbon.io") monkeypatch.setattr(cli_main, "get_access_token", lambda: "login-token") runner = CliRunner() @@ -159,6 +178,7 @@ def check_auth(self): assert calls["authorize"] == 1 assert calls["set_token"] == "login-token" assert calls["check_auth"] == 1 + assert calls["endpoint_url"] == "https://custom-login.codecarbon.io" def test_get_api_key_uses_bearer_token(monkeypatch): From e5c7136aeaf01a6947820a9c6293441a8f4947b6 Mon Sep 17 00:00:00 2001 From: Diogo Ribeiro Date: Fri, 27 Mar 2026 12:12:04 +0000 Subject: [PATCH 2/3] fix(cli): use configured API endpoint in CLI commands --- codecarbon/cli/main.py | 12 ++++++------ codecarbon/cli/monitor.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/codecarbon/cli/main.py b/codecarbon/cli/main.py index 84b241dcb..4d9b41cd4 100644 --- a/codecarbon/cli/main.py +++ b/codecarbon/cli/main.py @@ -323,24 +323,24 @@ def monitor( ctx: typer.Context, measure_power_secs: Annotated[ int, - typer.Option(default=10, help="Interval between two measures."), + typer.Option(help="Interval between two measures."), ] = 10, api_call_interval: Annotated[ int, - typer.Option(default=30, help="Number of measures between API calls."), + typer.Option(help="Number of measures between API calls."), ] = 30, api: Annotated[ bool, - typer.Option(default=True, help="Choose to call Code Carbon API or not"), + typer.Option(help="Choose to call Code Carbon API or not"), ] = True, - offline: Annotated[bool, typer.Option(default=False, help="Run in offline mode")] = False, + offline: Annotated[bool, typer.Option(help="Run in offline mode")] = False, country_iso_code: Annotated[ str, - typer.Option(default=None, help="3-letter country ISO code for offline mode"), + typer.Option(help="3-letter country ISO code for offline mode"), ] = None, region: Annotated[ str, - typer.Option(default=None, help="Region/province for offline mode"), + typer.Option(help="Region/province for offline mode"), ] = None, ): """Monitor your machine's carbon emissions.""" diff --git a/codecarbon/cli/monitor.py b/codecarbon/cli/monitor.py index 811f4b79a..e5925e3fe 100644 --- a/codecarbon/cli/monitor.py +++ b/codecarbon/cli/monitor.py @@ -15,7 +15,7 @@ def run_and_monitor( ctx: typer.Context, log_level: Annotated[ str, - typer.Option(default="error", help="Log level (critical, error, warning, info, debug)"), + typer.Option(help="Log level (critical, error, warning, info, debug)"), ] = "error", **tracker_args, ): From bab3fe9418eb984ffe2b3627edd332ff466cfa05 Mon Sep 17 00:00:00 2001 From: Diogo Ribeiro Date: Fri, 27 Mar 2026 12:18:13 +0000 Subject: [PATCH 3/3] fix(cli): use configured API endpoint and restore typer compatibility --- tests/cli/test_cli_main.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/cli/test_cli_main.py b/tests/cli/test_cli_main.py index fdafe4919..f4cb2fef7 100644 --- a/tests/cli/test_cli_main.py +++ b/tests/cli/test_cli_main.py @@ -52,7 +52,9 @@ def __init__(self, endpoint_url=None): runner = CliRunner() monkeypatch.setattr(cli_main, "ApiClient", CustomApiClient) - monkeypatch.setattr(cli_main, "get_api_endpoint", lambda: "https://custom.codecarbon.io") + monkeypatch.setattr( + cli_main, "get_api_endpoint", lambda: "https://custom.codecarbon.io" + ) monkeypatch.setattr(cli_main, "get_access_token", fake_get_access_token) result = runner.invoke(cli_main.codecarbon, ["test-api"]) @@ -169,7 +171,9 @@ def check_auth(self): "authorize", lambda: calls.__setitem__("authorize", calls["authorize"] + 1), ) - monkeypatch.setattr(cli_main, "get_api_endpoint", lambda: "https://custom-login.codecarbon.io") + monkeypatch.setattr( + cli_main, "get_api_endpoint", lambda: "https://custom-login.codecarbon.io" + ) monkeypatch.setattr(cli_main, "get_access_token", lambda: "login-token") runner = CliRunner()