codecarbon 3.2.5__tar.gz → 3.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codecarbon-3.2.5 → codecarbon-3.2.6}/PKG-INFO +8 -8
- {codecarbon-3.2.5 → codecarbon-3.2.6}/README.md +7 -7
- codecarbon-3.2.6/codecarbon/_version.py +1 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/cli/cli_utils.py +12 -16
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/cli/main.py +21 -12
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/cli/monitor.py +2 -1
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/powermetrics.py +1 -1
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/emissions_tracker.py +3 -2
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/hardware.py +4 -4
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/ram.py +1 -1
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output.py +3 -0
- codecarbon-3.2.6/codecarbon/output_methods/boamps/__init__.py +25 -0
- codecarbon-3.2.6/codecarbon/output_methods/boamps/mapper.py +260 -0
- codecarbon-3.2.6/codecarbon/output_methods/boamps/models.py +303 -0
- codecarbon-3.2.6/codecarbon/output_methods/boamps/output.py +164 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/PKG-INFO +8 -8
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/SOURCES.txt +5 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/pyproject.toml +4 -3
- codecarbon-3.2.6/tests/test_api_call.py +307 -0
- codecarbon-3.2.6/tests/test_boamps_output.py +1172 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_config.py +17 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_core_util.py +25 -10
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_cpu.py +192 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_cpu_load.py +65 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_emissions_tracker.py +27 -0
- codecarbon-3.2.6/tests/test_powermetrics.py +161 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_ram.py +147 -0
- codecarbon-3.2.6/tests/test_resource_tracker.py +352 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_unsupported_gpu.py +6 -2
- codecarbon-3.2.5/codecarbon/_version.py +0 -1
- codecarbon-3.2.5/tests/test_api_call.py +0 -108
- codecarbon-3.2.5/tests/test_powermetrics.py +0 -37
- codecarbon-3.2.5/tests/test_resource_tracker.py +0 -43
- {codecarbon-3.2.5 → codecarbon-3.2.6}/LICENSE +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/cli/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/cli/auth.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/api_client.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/cloud.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/config.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/cpu.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/electricitymaps_api.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/emissions.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/gpu.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/gpu_amd.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/gpu_device.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/gpu_nvidia.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/measure.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/rapl.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/resource_tracker.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/schemas.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/units.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/core/util.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/canada_provinces.geojson +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/cloud/impact.csv +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/hardware/cpu_dataset_builder/amd_cpu_scrapper.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/hardware/cpu_dataset_builder/intel_cpu_scrapper.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/hardware/cpu_dataset_builder/merge_scrapped_cpu_power.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/hardware/cpu_power.csv +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/private_infra/2016/usa_emissions.json +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/private_infra/2023/canada_energy_mix.json +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/private_infra/carbon_intensity_per_source.json +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/private_infra/global_energy_mix.json +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/data/private_infra/nordic_emissions.json +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/geography.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/logger.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/scheduler.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/external/task.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/input.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/lock.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/base_output.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/emissions_data.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/file.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/http.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/logger.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/metrics/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/metrics/logfire.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/metrics/metric_docs.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/output_methods/metrics/prometheus.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/py.typed +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/assets/__init__.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/assets/car_icon.png +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/assets/house_icon.png +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/assets/tv_icon.png +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/carbonboard.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/carbonboard_on_api.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/components.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/data.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon/viz/units.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/dependency_links.txt +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/entry_points.txt +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/requires.txt +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/codecarbon.egg-info/top_level.txt +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/setup.cfg +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_cloud.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_custom_handler.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_electricitymaps_api.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_electricitymaps_backward_compatibility.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_electricitymaps_config_backward_compatibility.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_emissions.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_emissions_tracker_constant.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_emissions_tracker_flush.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_energy.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_geography.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_gpu.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_gpu_amd.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_gpu_nvidia.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_input.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_lock.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_logger.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_logging_output.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_offline_emissions_tracker.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_package_integrity.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_rapl_mmio_scanning.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_rapl_parameters.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_rapl_permissions.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_tracking_inference.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_utilization_tracking.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_viz_data.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/test_viz_units.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/testdata.py +0 -0
- {codecarbon-3.2.5 → codecarbon-3.2.6}/tests/testutils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecarbon
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.6
|
|
4
4
|
Author: Mila, DataForGood, BCG GAMMA, Comet.ml, Haverford College
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://codecarbon.io/
|
|
@@ -52,8 +52,8 @@ Estimate and track carbon emissions from your computer, quantify and analyze the
|
|
|
52
52
|
|
|
53
53
|
CodeCarbon websites:
|
|
54
54
|
- [Main website](https://codecarbon.io) to learn why we do this.
|
|
55
|
-
- [Dashboard](https://dashboard.codecarbon.io/) to see your emissions, [read the API doc](https://
|
|
56
|
-
- [Documentation](https://
|
|
55
|
+
- [Dashboard](https://dashboard.codecarbon.io/) to see your emissions, [read the API doc](https://docs.codecarbon.io/latest/getting-started/api/) before.
|
|
56
|
+
- [Documentation](https://docs.codecarbon.io) to learn how to use the package and our methodology.
|
|
57
57
|
- [GitHub](https://github.com/mlco2/codecarbon) to look at the source code and contribute.
|
|
58
58
|
- [Discord](https://discord.gg/GS9js2XkJR) to chat with us.
|
|
59
59
|
|
|
@@ -99,7 +99,7 @@ We created a Python package that estimates your hardware electricity power consu
|
|
|
99
99
|
|
|
100
100
|

|
|
101
101
|
|
|
102
|
-
We explain more about this calculation in the [**Methodology**](https://
|
|
102
|
+
We explain more about this calculation in the [**Methodology**](https://docs.codecarbon.io/latest/introduction/methodology/) section of the documentation.
|
|
103
103
|
|
|
104
104
|
Our hope is that this package will be used widely for estimating the carbon footprint of computing, and for establishing best practices with regards to the disclosure and reduction of this footprint.
|
|
105
105
|
|
|
@@ -121,7 +121,7 @@ conda activate your_env
|
|
|
121
121
|
pip install codecarbon
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
To see more installation options please refer to the documentation: [**Installation**](https://
|
|
124
|
+
To see more installation options please refer to the documentation: [**Installation**](https://docs.codecarbon.io/latest/getting-started/installation/)
|
|
125
125
|
|
|
126
126
|
## Start to estimate your impact 📏
|
|
127
127
|
|
|
@@ -175,7 +175,7 @@ def your_function_to_track():
|
|
|
175
175
|
```
|
|
176
176
|
The package will track the emissions generated by the execution of your function.
|
|
177
177
|
|
|
178
|
-
There is other ways to use **codecarbon** package, please refer to the documentation to learn more about it: [**Usage**](https://
|
|
178
|
+
There is other ways to use **codecarbon** package, please refer to the documentation to learn more about it: [**Usage**](https://docs.codecarbon.io/latest/getting-started/usage/)
|
|
179
179
|
|
|
180
180
|
## Visualize 📊
|
|
181
181
|
|
|
@@ -189,7 +189,7 @@ You can now visualize your experiment emissions on the [dashboard](https://dashb
|
|
|
189
189
|
> - cloud mode
|
|
190
190
|
> - comet integration...
|
|
191
191
|
>
|
|
192
|
-
> Please explore the [**Documentation**](https://
|
|
192
|
+
> Please explore the [**Documentation**](https://docs.codecarbon.io/) to learn about it
|
|
193
193
|
> If ever what your are looking for is not yet implemented, let us know through the *issues* and even better become one of our 🦸🏼♀️🦸🏼♂️ contributors! more info 👇🏼
|
|
194
194
|
|
|
195
195
|
|
|
@@ -201,7 +201,7 @@ You are welcome to open issues, even suggest solutions and better still contribu
|
|
|
201
201
|
|
|
202
202
|
In order to contribute a change to our code base, please submit a pull request (PR) via GitHub and someone from our team will go over it and accept it.
|
|
203
203
|
|
|
204
|
-
Check out our [contribution guidelines :arrow_upper_right:](https://github.com/mlco2/codecarbon/blob/master/CONTRIBUTING.md)
|
|
204
|
+
Check out our [contribution guidelines :arrow_upper_right:](https://github.com/mlco2/codecarbon/blob/master/docs/contributing/CONTRIBUTING.md)
|
|
205
205
|
|
|
206
206
|
Feel free to chat with us on [Discord](https://discord.gg/GS9js2XkJR).
|
|
207
207
|
|
|
@@ -4,8 +4,8 @@ Estimate and track carbon emissions from your computer, quantify and analyze the
|
|
|
4
4
|
|
|
5
5
|
CodeCarbon websites:
|
|
6
6
|
- [Main website](https://codecarbon.io) to learn why we do this.
|
|
7
|
-
- [Dashboard](https://dashboard.codecarbon.io/) to see your emissions, [read the API doc](https://
|
|
8
|
-
- [Documentation](https://
|
|
7
|
+
- [Dashboard](https://dashboard.codecarbon.io/) to see your emissions, [read the API doc](https://docs.codecarbon.io/latest/getting-started/api/) before.
|
|
8
|
+
- [Documentation](https://docs.codecarbon.io) to learn how to use the package and our methodology.
|
|
9
9
|
- [GitHub](https://github.com/mlco2/codecarbon) to look at the source code and contribute.
|
|
10
10
|
- [Discord](https://discord.gg/GS9js2XkJR) to chat with us.
|
|
11
11
|
|
|
@@ -51,7 +51,7 @@ We created a Python package that estimates your hardware electricity power consu
|
|
|
51
51
|
|
|
52
52
|

|
|
53
53
|
|
|
54
|
-
We explain more about this calculation in the [**Methodology**](https://
|
|
54
|
+
We explain more about this calculation in the [**Methodology**](https://docs.codecarbon.io/latest/introduction/methodology/) section of the documentation.
|
|
55
55
|
|
|
56
56
|
Our hope is that this package will be used widely for estimating the carbon footprint of computing, and for establishing best practices with regards to the disclosure and reduction of this footprint.
|
|
57
57
|
|
|
@@ -73,7 +73,7 @@ conda activate your_env
|
|
|
73
73
|
pip install codecarbon
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
To see more installation options please refer to the documentation: [**Installation**](https://
|
|
76
|
+
To see more installation options please refer to the documentation: [**Installation**](https://docs.codecarbon.io/latest/getting-started/installation/)
|
|
77
77
|
|
|
78
78
|
## Start to estimate your impact 📏
|
|
79
79
|
|
|
@@ -127,7 +127,7 @@ def your_function_to_track():
|
|
|
127
127
|
```
|
|
128
128
|
The package will track the emissions generated by the execution of your function.
|
|
129
129
|
|
|
130
|
-
There is other ways to use **codecarbon** package, please refer to the documentation to learn more about it: [**Usage**](https://
|
|
130
|
+
There is other ways to use **codecarbon** package, please refer to the documentation to learn more about it: [**Usage**](https://docs.codecarbon.io/latest/getting-started/usage/)
|
|
131
131
|
|
|
132
132
|
## Visualize 📊
|
|
133
133
|
|
|
@@ -141,7 +141,7 @@ You can now visualize your experiment emissions on the [dashboard](https://dashb
|
|
|
141
141
|
> - cloud mode
|
|
142
142
|
> - comet integration...
|
|
143
143
|
>
|
|
144
|
-
> Please explore the [**Documentation**](https://
|
|
144
|
+
> Please explore the [**Documentation**](https://docs.codecarbon.io/) to learn about it
|
|
145
145
|
> If ever what your are looking for is not yet implemented, let us know through the *issues* and even better become one of our 🦸🏼♀️🦸🏼♂️ contributors! more info 👇🏼
|
|
146
146
|
|
|
147
147
|
|
|
@@ -153,7 +153,7 @@ You are welcome to open issues, even suggest solutions and better still contribu
|
|
|
153
153
|
|
|
154
154
|
In order to contribute a change to our code base, please submit a pull request (PR) via GitHub and someone from our team will go over it and accept it.
|
|
155
155
|
|
|
156
|
-
Check out our [contribution guidelines :arrow_upper_right:](https://github.com/mlco2/codecarbon/blob/master/CONTRIBUTING.md)
|
|
156
|
+
Check out our [contribution guidelines :arrow_upper_right:](https://github.com/mlco2/codecarbon/blob/master/docs/contributing/CONTRIBUTING.md)
|
|
157
157
|
|
|
158
158
|
Feel free to chat with us on [Discord](https://discord.gg/GS9js2XkJR).
|
|
159
159
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.2.6"
|
|
@@ -5,6 +5,8 @@ from typing import Optional
|
|
|
5
5
|
import typer
|
|
6
6
|
from rich.prompt import Confirm
|
|
7
7
|
|
|
8
|
+
from codecarbon.core.config import get_hierarchical_config
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
def get_config(path: Optional[Path] = None):
|
|
10
12
|
p = path or Path.cwd().resolve() / ".codecarbon.config"
|
|
@@ -37,22 +39,16 @@ def get_api_endpoint(path: Optional[Path] = None):
|
|
|
37
39
|
return "https://api.codecarbon.io"
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
config = configparser.ConfigParser()
|
|
51
|
-
config.read(str(p))
|
|
52
|
-
if "codecarbon" in config.sections():
|
|
53
|
-
d = dict(config["codecarbon"])
|
|
54
|
-
if "experiment_id" in d:
|
|
55
|
-
return d["experiment_id"]
|
|
42
|
+
def get_existing_exp_id() -> Optional[str]:
|
|
43
|
+
"""
|
|
44
|
+
Return experiment_id resolved from the same hierarchical config strategy
|
|
45
|
+
used by EmissionsTracker (global file, local file, then CODECARBON_* env).
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
conf = get_hierarchical_config()
|
|
49
|
+
except KeyError:
|
|
50
|
+
return None
|
|
51
|
+
return conf.get("experiment_id")
|
|
56
52
|
|
|
57
53
|
|
|
58
54
|
def write_local_exp_id(exp_id, path: Optional[Path] = None):
|
|
@@ -18,7 +18,7 @@ from codecarbon.cli.cli_utils import (
|
|
|
18
18
|
create_new_config_file,
|
|
19
19
|
get_api_endpoint,
|
|
20
20
|
get_config,
|
|
21
|
-
|
|
21
|
+
get_existing_exp_id,
|
|
22
22
|
overwrite_local_config,
|
|
23
23
|
)
|
|
24
24
|
from codecarbon.cli.monitor import run_and_monitor
|
|
@@ -114,7 +114,8 @@ def api_get():
|
|
|
114
114
|
"""
|
|
115
115
|
ex: test-api
|
|
116
116
|
"""
|
|
117
|
-
|
|
117
|
+
api_endpoint = get_api_endpoint()
|
|
118
|
+
api = ApiClient(endpoint_url=api_endpoint)
|
|
118
119
|
api.set_access_token(get_access_token())
|
|
119
120
|
organizations = api.get_list_organizations()
|
|
120
121
|
print(organizations)
|
|
@@ -123,15 +124,18 @@ def api_get():
|
|
|
123
124
|
@codecarbon.command("login", short_help="Login to CodeCarbon")
|
|
124
125
|
def login():
|
|
125
126
|
authorize()
|
|
126
|
-
|
|
127
|
+
api_endpoint = get_api_endpoint()
|
|
128
|
+
api = ApiClient(endpoint_url=api_endpoint)
|
|
127
129
|
access_token = get_access_token()
|
|
128
130
|
api.set_access_token(access_token)
|
|
129
131
|
api.check_auth()
|
|
130
132
|
|
|
131
133
|
|
|
132
134
|
def get_api_key(project_id: str):
|
|
135
|
+
api_endpoint = get_api_endpoint()
|
|
136
|
+
api_endpoint = api_endpoint.rstrip("/")
|
|
133
137
|
req = requests.post(
|
|
134
|
-
f"{
|
|
138
|
+
f"{api_endpoint}/projects/{project_id}/api-tokens",
|
|
135
139
|
json={
|
|
136
140
|
"project_id": project_id,
|
|
137
141
|
"name": "api token",
|
|
@@ -306,7 +310,7 @@ def config():
|
|
|
306
310
|
overwrite_local_config("api_key", api_key, path=file_path)
|
|
307
311
|
show_config(file_path)
|
|
308
312
|
print(
|
|
309
|
-
"Consult [link=https://
|
|
313
|
+
"Consult [link=https://docs.codecarbon.io/latest/getting-started/usage/#configuration]configuration documentation[/link] for more configuration options"
|
|
310
314
|
)
|
|
311
315
|
|
|
312
316
|
|
|
@@ -318,20 +322,25 @@ def config():
|
|
|
318
322
|
def monitor(
|
|
319
323
|
ctx: typer.Context,
|
|
320
324
|
measure_power_secs: Annotated[
|
|
321
|
-
int,
|
|
325
|
+
int,
|
|
326
|
+
typer.Option(help="Interval between two measures."),
|
|
322
327
|
] = 10,
|
|
323
328
|
api_call_interval: Annotated[
|
|
324
|
-
int,
|
|
329
|
+
int,
|
|
330
|
+
typer.Option(help="Number of measures between API calls."),
|
|
325
331
|
] = 30,
|
|
326
332
|
api: Annotated[
|
|
327
|
-
bool,
|
|
333
|
+
bool,
|
|
334
|
+
typer.Option(help="Choose to call Code Carbon API or not"),
|
|
328
335
|
] = True,
|
|
329
336
|
offline: Annotated[bool, typer.Option(help="Run in offline mode")] = False,
|
|
330
337
|
country_iso_code: Annotated[
|
|
331
|
-
str,
|
|
338
|
+
str,
|
|
339
|
+
typer.Option(help="3-letter country ISO code for offline mode"),
|
|
332
340
|
] = None,
|
|
333
341
|
region: Annotated[
|
|
334
|
-
str,
|
|
342
|
+
str,
|
|
343
|
+
typer.Option(help="Region/province for offline mode"),
|
|
335
344
|
] = None,
|
|
336
345
|
):
|
|
337
346
|
"""Monitor your machine's carbon emissions."""
|
|
@@ -356,10 +365,10 @@ def monitor(
|
|
|
356
365
|
"region": region,
|
|
357
366
|
}
|
|
358
367
|
else:
|
|
359
|
-
experiment_id =
|
|
368
|
+
experiment_id = get_existing_exp_id()
|
|
360
369
|
if api and experiment_id is None:
|
|
361
370
|
print(
|
|
362
|
-
"ERROR: No experiment id, call 'codecarbon config' first
|
|
371
|
+
"ERROR: No experiment id. Set CODECARBON_EXPERIMENT_ID, call 'codecarbon config' first, or run in offline mode with `--offline --country-iso-code FRA`.",
|
|
363
372
|
file=sys.stderr,
|
|
364
373
|
)
|
|
365
374
|
raise typer.Exit(1)
|
|
@@ -14,7 +14,8 @@ from codecarbon.emissions_tracker import EmissionsTracker
|
|
|
14
14
|
def run_and_monitor(
|
|
15
15
|
ctx: typer.Context,
|
|
16
16
|
log_level: Annotated[
|
|
17
|
-
str,
|
|
17
|
+
str,
|
|
18
|
+
typer.Option(help="Log level (critical, error, warning, info, debug)"),
|
|
18
19
|
] = "error",
|
|
19
20
|
**tracker_args,
|
|
20
21
|
):
|
|
@@ -58,7 +58,7 @@ def _has_powermetrics_sudo() -> bool:
|
|
|
58
58
|
"""Not using PowerMetrics, sudo password prompt detected.
|
|
59
59
|
If you want to enable Powermetrics please modify your sudoers file
|
|
60
60
|
as described in :
|
|
61
|
-
https://
|
|
61
|
+
https://docs.codecarbon.io/latest/introduction/methodology/#power-usage
|
|
62
62
|
"""
|
|
63
63
|
)
|
|
64
64
|
return False
|
|
@@ -978,9 +978,10 @@ class BaseEmissionsTracker(ABC):
|
|
|
978
978
|
if isinstance(hardware, GPU):
|
|
979
979
|
gpu_ids_to_monitor = hardware.gpu_ids
|
|
980
980
|
gpu_details = hardware.devices.get_gpu_details()
|
|
981
|
-
for gpu_detail in gpu_details:
|
|
981
|
+
for gpu_index, gpu_detail in enumerate(gpu_details):
|
|
982
|
+
resolved_gpu_index = gpu_detail.get("gpu_index", gpu_index)
|
|
982
983
|
if (
|
|
983
|
-
|
|
984
|
+
resolved_gpu_index in gpu_ids_to_monitor
|
|
984
985
|
and "gpu_utilization" in gpu_detail
|
|
985
986
|
):
|
|
986
987
|
self._gpu_utilization_history.append(
|
|
@@ -377,12 +377,12 @@ class CPU(BaseHardware):
|
|
|
377
377
|
|
|
378
378
|
def total_power(self) -> Power:
|
|
379
379
|
self._power_history.append(self._get_power_from_cpus())
|
|
380
|
-
if len(self._power_history) == 0:
|
|
381
|
-
logger.warning("Power history is empty, returning 0 W")
|
|
382
|
-
return Power.from_watts(0)
|
|
383
380
|
power_history_in_W = [power.W for power in self._power_history]
|
|
384
|
-
cpu_power = sum(power_history_in_W) / len(power_history_in_W)
|
|
385
381
|
self._power_history = []
|
|
382
|
+
if not power_history_in_W:
|
|
383
|
+
logger.warning("No power samples collected, returning 0 W")
|
|
384
|
+
return Power.from_watts(0)
|
|
385
|
+
cpu_power = sum(power_history_in_W) / len(power_history_in_W)
|
|
386
386
|
return Power.from_watts(cpu_power)
|
|
387
387
|
|
|
388
388
|
def measure_power_and_energy(self, last_duration: float) -> Tuple[Power, Energy]:
|
|
@@ -24,7 +24,7 @@ class RAM(BaseHardware):
|
|
|
24
24
|
In V3, we need to improve the accuracy of the RAM power estimation.
|
|
25
25
|
Because the power consumption of RAM is not linear with the amount of memory used,
|
|
26
26
|
|
|
27
|
-
See https://
|
|
27
|
+
See https://docs.codecarbon.io/latest/introduction/methodology/#ram for details on the RAM
|
|
28
28
|
power estimation methodology.
|
|
29
29
|
|
|
30
30
|
"""
|
|
@@ -4,6 +4,9 @@ Provides functionality for persistence of data
|
|
|
4
4
|
|
|
5
5
|
from codecarbon.output_methods.base_output import BaseOutput # noqa: F401
|
|
6
6
|
|
|
7
|
+
# Output to BoAmps format
|
|
8
|
+
from codecarbon.output_methods.boamps import BoAmpsOutput # noqa: F401
|
|
9
|
+
|
|
7
10
|
# emissions data
|
|
8
11
|
from codecarbon.output_methods.emissions_data import ( # noqa: F401
|
|
9
12
|
EmissionsData,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BoAmps output support for CodeCarbon.
|
|
3
|
+
|
|
4
|
+
Provides first-class support for generating BoAmps (Boavizta) standardized
|
|
5
|
+
JSON reports from CodeCarbon emission tracking data.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from codecarbon.output_methods.boamps.mapper import ( # noqa: F401
|
|
9
|
+
map_emissions_to_boamps,
|
|
10
|
+
)
|
|
11
|
+
from codecarbon.output_methods.boamps.models import ( # noqa: F401
|
|
12
|
+
BoAmpsAlgorithm,
|
|
13
|
+
BoAmpsDataset,
|
|
14
|
+
BoAmpsEnvironment,
|
|
15
|
+
BoAmpsHardware,
|
|
16
|
+
BoAmpsHeader,
|
|
17
|
+
BoAmpsInfrastructure,
|
|
18
|
+
BoAmpsMeasure,
|
|
19
|
+
BoAmpsPublisher,
|
|
20
|
+
BoAmpsReport,
|
|
21
|
+
BoAmpsSoftware,
|
|
22
|
+
BoAmpsSystem,
|
|
23
|
+
BoAmpsTask,
|
|
24
|
+
)
|
|
25
|
+
from codecarbon.output_methods.boamps.output import BoAmpsOutput # noqa: F401
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Maps CodeCarbon EmissionsData to BoAmps report format.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
from dataclasses import fields as dataclass_fields
|
|
7
|
+
from dataclasses import replace
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from codecarbon.output_methods.boamps.models import (
|
|
11
|
+
BoAmpsEnvironment,
|
|
12
|
+
BoAmpsHardware,
|
|
13
|
+
BoAmpsHeader,
|
|
14
|
+
BoAmpsInfrastructure,
|
|
15
|
+
BoAmpsMeasure,
|
|
16
|
+
BoAmpsReport,
|
|
17
|
+
BoAmpsSoftware,
|
|
18
|
+
BoAmpsSystem,
|
|
19
|
+
BoAmpsTask,
|
|
20
|
+
)
|
|
21
|
+
from codecarbon.output_methods.emissions_data import EmissionsData
|
|
22
|
+
|
|
23
|
+
BOAMPS_FORMAT_VERSION = "0.1"
|
|
24
|
+
BOAMPS_FORMAT_SPEC_URI = "https://github.com/Boavizta/BoAmps/tree/main/model"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _to_boamps_datetime(timestamp: str) -> str:
|
|
28
|
+
"""Normalize a timestamp to BoAmps format (YYYY-MM-DD HH:MM:SS)."""
|
|
29
|
+
return timestamp.replace("T", " ") if timestamp else timestamp
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def map_emissions_to_boamps(
|
|
33
|
+
emissions: EmissionsData,
|
|
34
|
+
task: Optional[BoAmpsTask] = None,
|
|
35
|
+
header: Optional[BoAmpsHeader] = None,
|
|
36
|
+
quality: Optional[str] = None,
|
|
37
|
+
infra_overrides: Optional[dict] = None,
|
|
38
|
+
environment_overrides: Optional[dict] = None,
|
|
39
|
+
) -> BoAmpsReport:
|
|
40
|
+
"""
|
|
41
|
+
Map CodeCarbon EmissionsData to a BoAmps report.
|
|
42
|
+
|
|
43
|
+
Auto-fills fields from EmissionsData and merges with user-provided context.
|
|
44
|
+
User-provided values take precedence over auto-detected values.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
emissions: CodeCarbon emissions data from a completed run.
|
|
48
|
+
task: User-provided task context (required for schema-valid BoAmps).
|
|
49
|
+
header: User-provided header overrides.
|
|
50
|
+
quality: Quality assessment ("high", "medium", "low").
|
|
51
|
+
infra_overrides: Additional infrastructure fields (cloud_instance, cloud_service).
|
|
52
|
+
environment_overrides: Additional environment fields (power_source, etc.).
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
A BoAmpsReport populated with auto-detected and user-provided data.
|
|
56
|
+
"""
|
|
57
|
+
report_header = _build_header(emissions, header)
|
|
58
|
+
measures = [_build_measure(emissions)]
|
|
59
|
+
system = _build_system(emissions)
|
|
60
|
+
software = _build_software(emissions)
|
|
61
|
+
infrastructure = _build_infrastructure(emissions, infra_overrides)
|
|
62
|
+
environment = _build_environment(emissions, environment_overrides)
|
|
63
|
+
|
|
64
|
+
if task is None:
|
|
65
|
+
warnings.warn(
|
|
66
|
+
"No BoAmps task context provided. The output will be missing required "
|
|
67
|
+
"fields (taskStage, taskFamily, algorithms, dataset) and will not "
|
|
68
|
+
"validate against the BoAmps schema.",
|
|
69
|
+
UserWarning,
|
|
70
|
+
stacklevel=2,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return BoAmpsReport(
|
|
74
|
+
header=report_header,
|
|
75
|
+
task=task,
|
|
76
|
+
measures=measures,
|
|
77
|
+
system=system,
|
|
78
|
+
software=software,
|
|
79
|
+
infrastructure=infrastructure,
|
|
80
|
+
environment=environment,
|
|
81
|
+
quality=quality,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _build_header(
|
|
86
|
+
emissions: EmissionsData, user_header: Optional[BoAmpsHeader]
|
|
87
|
+
) -> BoAmpsHeader:
|
|
88
|
+
"""Build header from EmissionsData, merging with user overrides."""
|
|
89
|
+
auto_header = BoAmpsHeader(
|
|
90
|
+
format_version=BOAMPS_FORMAT_VERSION,
|
|
91
|
+
format_version_specification_uri=BOAMPS_FORMAT_SPEC_URI,
|
|
92
|
+
report_id=emissions.run_id,
|
|
93
|
+
report_datetime=_to_boamps_datetime(emissions.timestamp),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if user_header is None:
|
|
97
|
+
return auto_header
|
|
98
|
+
|
|
99
|
+
# User values override auto-detected values
|
|
100
|
+
return BoAmpsHeader(
|
|
101
|
+
licensing=user_header.licensing or auto_header.licensing,
|
|
102
|
+
format_version=user_header.format_version or auto_header.format_version,
|
|
103
|
+
format_version_specification_uri=(
|
|
104
|
+
user_header.format_version_specification_uri
|
|
105
|
+
or auto_header.format_version_specification_uri
|
|
106
|
+
),
|
|
107
|
+
report_id=user_header.report_id or auto_header.report_id,
|
|
108
|
+
report_datetime=user_header.report_datetime or auto_header.report_datetime,
|
|
109
|
+
report_status=user_header.report_status or auto_header.report_status,
|
|
110
|
+
publisher=user_header.publisher or auto_header.publisher,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _build_measure(emissions: EmissionsData) -> BoAmpsMeasure:
|
|
115
|
+
"""Build a BoAmps measure from EmissionsData."""
|
|
116
|
+
# Note: emissions.tracking_mode is "process"/"machine" (CodeCarbon's scope),
|
|
117
|
+
# not the CPU/GPU power tracking method (rapl, nvml, etc.) that BoAmps expects
|
|
118
|
+
# for cpuTrackingMode/gpuTrackingMode. We omit these fields since we don't
|
|
119
|
+
# have the actual tracker implementation details in EmissionsData.
|
|
120
|
+
measure = BoAmpsMeasure(
|
|
121
|
+
measurement_method="codecarbon",
|
|
122
|
+
version=emissions.codecarbon_version,
|
|
123
|
+
power_consumption=emissions.energy_consumed,
|
|
124
|
+
measurement_duration=emissions.duration,
|
|
125
|
+
measurement_date_time=_to_boamps_datetime(emissions.timestamp),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# CPU utilization as fraction (0-1)
|
|
129
|
+
if emissions.cpu_utilization_percent > 0:
|
|
130
|
+
measure.average_utilization_cpu = round(
|
|
131
|
+
emissions.cpu_utilization_percent / 100.0, 4
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# GPU fields only if GPU is present
|
|
135
|
+
if emissions.gpu_count and emissions.gpu_count > 0:
|
|
136
|
+
if emissions.gpu_utilization_percent > 0:
|
|
137
|
+
measure.average_utilization_gpu = round(
|
|
138
|
+
emissions.gpu_utilization_percent / 100.0, 4
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return measure
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _build_system(emissions: EmissionsData) -> BoAmpsSystem:
|
|
145
|
+
"""Build system info from EmissionsData."""
|
|
146
|
+
return BoAmpsSystem(os=emissions.os)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _build_software(emissions: EmissionsData) -> BoAmpsSoftware:
|
|
150
|
+
"""Build software info from EmissionsData."""
|
|
151
|
+
return BoAmpsSoftware(
|
|
152
|
+
language="python",
|
|
153
|
+
version=emissions.python_version,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _build_infrastructure(
|
|
158
|
+
emissions: EmissionsData, overrides: Optional[dict] = None
|
|
159
|
+
) -> BoAmpsInfrastructure:
|
|
160
|
+
"""Build infrastructure from EmissionsData hardware fields."""
|
|
161
|
+
components = []
|
|
162
|
+
|
|
163
|
+
# CPU component (always present)
|
|
164
|
+
# emissions.cpu_count is logical thread count. BoAmps nbComponent expects
|
|
165
|
+
# physical cores. Standard SMT/HT uses 2 threads per core.
|
|
166
|
+
cpu_cores = max(1, int(emissions.cpu_count) // 2) if emissions.cpu_count else 1
|
|
167
|
+
cpu_component = BoAmpsHardware(
|
|
168
|
+
component_type="cpu",
|
|
169
|
+
component_name=emissions.cpu_model,
|
|
170
|
+
nb_component=cpu_cores,
|
|
171
|
+
)
|
|
172
|
+
components.append(cpu_component)
|
|
173
|
+
|
|
174
|
+
# GPU component (only if present)
|
|
175
|
+
if emissions.gpu_count and emissions.gpu_count > 0:
|
|
176
|
+
gpu_component = BoAmpsHardware(
|
|
177
|
+
component_type="gpu",
|
|
178
|
+
component_name=emissions.gpu_model if emissions.gpu_model else None,
|
|
179
|
+
nb_component=int(emissions.gpu_count),
|
|
180
|
+
)
|
|
181
|
+
components.append(gpu_component)
|
|
182
|
+
|
|
183
|
+
# RAM component (always present)
|
|
184
|
+
ram_component = BoAmpsHardware(
|
|
185
|
+
component_type="ram",
|
|
186
|
+
nb_component=1,
|
|
187
|
+
memory_size=emissions.ram_total_size,
|
|
188
|
+
)
|
|
189
|
+
components.append(ram_component)
|
|
190
|
+
|
|
191
|
+
# emissions.on_cloud can be "N" even on public cloud (the tracker clears
|
|
192
|
+
# cloud_provider/region for some providers). Use cloud_provider as a
|
|
193
|
+
# secondary signal to avoid misreporting cloud runs as on-premise.
|
|
194
|
+
is_cloud = emissions.on_cloud == "Y" or bool(emissions.cloud_provider)
|
|
195
|
+
infra = BoAmpsInfrastructure(
|
|
196
|
+
infra_type="publicCloud" if is_cloud else "onPremise",
|
|
197
|
+
cloud_provider=(
|
|
198
|
+
emissions.cloud_provider if is_cloud and emissions.cloud_provider else None
|
|
199
|
+
),
|
|
200
|
+
components=components,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Apply overrides from context file
|
|
204
|
+
if overrides:
|
|
205
|
+
for attr in ("cloud_instance", "cloud_service", "infra_type"):
|
|
206
|
+
if attr in overrides:
|
|
207
|
+
setattr(infra, attr, overrides[attr])
|
|
208
|
+
|
|
209
|
+
# Merge user-provided components: enrich auto-detected components
|
|
210
|
+
# with user-supplied details (manufacturer, family, series, share, etc.)
|
|
211
|
+
# by matching on component_type. Extra user components are appended.
|
|
212
|
+
if "components" in overrides:
|
|
213
|
+
user_components = overrides["components"]
|
|
214
|
+
auto_by_type = {c.component_type: c for c in infra.components}
|
|
215
|
+
merged = []
|
|
216
|
+
used_types = set()
|
|
217
|
+
for user_comp in user_components:
|
|
218
|
+
if user_comp.component_type in auto_by_type:
|
|
219
|
+
auto = auto_by_type[user_comp.component_type]
|
|
220
|
+
# Build a merged copy: user values take precedence,
|
|
221
|
+
# auto-detected fill blanks. Avoids mutating the originals.
|
|
222
|
+
fill = {
|
|
223
|
+
f.name: getattr(auto, f.name)
|
|
224
|
+
for f in dataclass_fields(user_comp)
|
|
225
|
+
if f.name != "component_type"
|
|
226
|
+
and getattr(user_comp, f.name) is None
|
|
227
|
+
}
|
|
228
|
+
user_comp = replace(user_comp, **fill) if fill else user_comp
|
|
229
|
+
used_types.add(user_comp.component_type)
|
|
230
|
+
merged.append(user_comp)
|
|
231
|
+
# Keep auto-detected components that the user didn't override
|
|
232
|
+
for auto in infra.components:
|
|
233
|
+
if auto.component_type not in used_types:
|
|
234
|
+
merged.append(auto)
|
|
235
|
+
infra.components = merged
|
|
236
|
+
|
|
237
|
+
return infra
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _build_environment(
|
|
241
|
+
emissions: EmissionsData, overrides: Optional[dict] = None
|
|
242
|
+
) -> BoAmpsEnvironment:
|
|
243
|
+
"""Build environment from EmissionsData location fields."""
|
|
244
|
+
env = BoAmpsEnvironment(
|
|
245
|
+
country=emissions.country_name,
|
|
246
|
+
latitude=emissions.latitude,
|
|
247
|
+
longitude=emissions.longitude,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
if overrides:
|
|
251
|
+
for attr in (
|
|
252
|
+
"location",
|
|
253
|
+
"power_supplier_type",
|
|
254
|
+
"power_source",
|
|
255
|
+
"power_source_carbon_intensity",
|
|
256
|
+
):
|
|
257
|
+
if attr in overrides:
|
|
258
|
+
setattr(env, attr, overrides[attr])
|
|
259
|
+
|
|
260
|
+
return env
|