greencalculus 0.1.0__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.
- greencalculus-0.1.0/LICENSE +21 -0
- greencalculus-0.1.0/PKG-INFO +111 -0
- greencalculus-0.1.0/README.md +90 -0
- greencalculus-0.1.0/greencalculus/__init__.py +155 -0
- greencalculus-0.1.0/greencalculus.egg-info/PKG-INFO +111 -0
- greencalculus-0.1.0/greencalculus.egg-info/SOURCES.txt +8 -0
- greencalculus-0.1.0/greencalculus.egg-info/dependency_links.txt +1 -0
- greencalculus-0.1.0/greencalculus.egg-info/top_level.txt +1 -0
- greencalculus-0.1.0/pyproject.toml +35 -0
- greencalculus-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GreenCalculus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: greencalculus
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The carbon-accounting API — sourced emission factors and audit-traced calculations, every value traceable to its source.
|
|
5
|
+
Author-email: GreenCalculus <jeremiah@greencalculus.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://greencalculus.com/developers
|
|
8
|
+
Project-URL: Documentation, https://greencalculus.com/developers/docs
|
|
9
|
+
Project-URL: Source, https://github.com/jeremiahsay/greencalculus-sdk
|
|
10
|
+
Keywords: carbon,emissions,co2,co2e,ghg,greenhouse-gas,emission-factors,esg,pcaf,climate,sustainability,carbon-accounting,scope-3,embodied-carbon,defra,ipcc
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# greencalculus
|
|
23
|
+
|
|
24
|
+
The official Python client for the [GreenCalculus API](https://greencalculus.com/developers) — sourced greenhouse-gas emission factors and audit-traced calculations. Every value comes back with its source cell and data version, so you hand back citable numbers, not guesses.
|
|
25
|
+
|
|
26
|
+
Zero third-party dependencies (standard library only).
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install greencalculus
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quickstart
|
|
35
|
+
|
|
36
|
+
Get a free API key (1,000 calls/month, no card) at **[greencalculus.com/developers](https://greencalculus.com/developers)**.
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from greencalculus import GreenCalculus
|
|
40
|
+
|
|
41
|
+
gc = GreenCalculus(api_key="gc_live_...")
|
|
42
|
+
|
|
43
|
+
# A sourced emission factor. value & unit are at the top level for convenience;
|
|
44
|
+
# the full sourced row (source cell, gas, GWP set) stays under ["factor"].
|
|
45
|
+
f = gc.factor("grid.gbr.electricity.location_based")
|
|
46
|
+
print(f["value"], f["unit"]) # 0.13096 kg CO2e per kWh
|
|
47
|
+
print(f["factor"]["source"]["id"]) # DEFRA_2026
|
|
48
|
+
|
|
49
|
+
# An audit-traced calculation — the full working, not just a total
|
|
50
|
+
r = gc.ghg_activity(
|
|
51
|
+
activity={"value": 1000, "unit": "kWh"},
|
|
52
|
+
factor_key="grid.gbr.electricity.location_based",
|
|
53
|
+
)
|
|
54
|
+
print(r["emissions"]["value"], r["emissions"]["unit"])
|
|
55
|
+
print(r["source"]["id"]) # e.g. EMBER_YEARLY_ELECTRICITY_2025
|
|
56
|
+
|
|
57
|
+
# Plain language -> the right factor, with a confidence score
|
|
58
|
+
m = gc.resolve("UK grid electricity")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Calculations
|
|
62
|
+
|
|
63
|
+
Every engine returns the formula, the source, the data version, and a deterministic receipt.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
gc.pcaf(asset_class="listed_equity_corporate_bonds", holdings=[{
|
|
67
|
+
"outstanding_amount": 1_000_000,
|
|
68
|
+
"denominator": {"type": "evic", "value": 2_500_000_000_000},
|
|
69
|
+
"company_emissions": {"value": 20_000_000},
|
|
70
|
+
"data_quality_score": 2,
|
|
71
|
+
}])
|
|
72
|
+
|
|
73
|
+
gc.embodied(materials=[{
|
|
74
|
+
"material_key": "materials.concrete.ready_mix.c8_10",
|
|
75
|
+
"quantity": {"value": 50, "unit": "m3"},
|
|
76
|
+
"boundary": "A1-C",
|
|
77
|
+
}])
|
|
78
|
+
|
|
79
|
+
gc.freight(mass={"value": 1, "unit": "tonne"},
|
|
80
|
+
distance={"value": 100, "unit": "km"},
|
|
81
|
+
factor_key="freight.rail.tonne_km")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Also available: `electricity`, `spend_based`, `business_travel`, and `batch(calculations=[...])`. Any methodology works via `gc.calculate("<methodology>", **body)`.
|
|
85
|
+
|
|
86
|
+
## Reproducibility
|
|
87
|
+
|
|
88
|
+
Pin any factor to a past data version so a figure reproduces exactly in an audit:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
gc.factor("grid.gbr.electricity.location_based", as_of="2026.111")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Errors
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from greencalculus import GreenCalculusError
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
gc.factor("does.not.exist")
|
|
101
|
+
except GreenCalculusError as e:
|
|
102
|
+
print(e.status, e.code, e.message)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Links
|
|
106
|
+
|
|
107
|
+
- Docs: https://greencalculus.com/developers/docs
|
|
108
|
+
- Data rights & continuity: https://greencalculus.com/developers/trust
|
|
109
|
+
- MCP server (agents): `mcp.greencalculus.com`
|
|
110
|
+
|
|
111
|
+
MIT licensed.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# greencalculus
|
|
2
|
+
|
|
3
|
+
The official Python client for the [GreenCalculus API](https://greencalculus.com/developers) — sourced greenhouse-gas emission factors and audit-traced calculations. Every value comes back with its source cell and data version, so you hand back citable numbers, not guesses.
|
|
4
|
+
|
|
5
|
+
Zero third-party dependencies (standard library only).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install greencalculus
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
Get a free API key (1,000 calls/month, no card) at **[greencalculus.com/developers](https://greencalculus.com/developers)**.
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from greencalculus import GreenCalculus
|
|
19
|
+
|
|
20
|
+
gc = GreenCalculus(api_key="gc_live_...")
|
|
21
|
+
|
|
22
|
+
# A sourced emission factor. value & unit are at the top level for convenience;
|
|
23
|
+
# the full sourced row (source cell, gas, GWP set) stays under ["factor"].
|
|
24
|
+
f = gc.factor("grid.gbr.electricity.location_based")
|
|
25
|
+
print(f["value"], f["unit"]) # 0.13096 kg CO2e per kWh
|
|
26
|
+
print(f["factor"]["source"]["id"]) # DEFRA_2026
|
|
27
|
+
|
|
28
|
+
# An audit-traced calculation — the full working, not just a total
|
|
29
|
+
r = gc.ghg_activity(
|
|
30
|
+
activity={"value": 1000, "unit": "kWh"},
|
|
31
|
+
factor_key="grid.gbr.electricity.location_based",
|
|
32
|
+
)
|
|
33
|
+
print(r["emissions"]["value"], r["emissions"]["unit"])
|
|
34
|
+
print(r["source"]["id"]) # e.g. EMBER_YEARLY_ELECTRICITY_2025
|
|
35
|
+
|
|
36
|
+
# Plain language -> the right factor, with a confidence score
|
|
37
|
+
m = gc.resolve("UK grid electricity")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Calculations
|
|
41
|
+
|
|
42
|
+
Every engine returns the formula, the source, the data version, and a deterministic receipt.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
gc.pcaf(asset_class="listed_equity_corporate_bonds", holdings=[{
|
|
46
|
+
"outstanding_amount": 1_000_000,
|
|
47
|
+
"denominator": {"type": "evic", "value": 2_500_000_000_000},
|
|
48
|
+
"company_emissions": {"value": 20_000_000},
|
|
49
|
+
"data_quality_score": 2,
|
|
50
|
+
}])
|
|
51
|
+
|
|
52
|
+
gc.embodied(materials=[{
|
|
53
|
+
"material_key": "materials.concrete.ready_mix.c8_10",
|
|
54
|
+
"quantity": {"value": 50, "unit": "m3"},
|
|
55
|
+
"boundary": "A1-C",
|
|
56
|
+
}])
|
|
57
|
+
|
|
58
|
+
gc.freight(mass={"value": 1, "unit": "tonne"},
|
|
59
|
+
distance={"value": 100, "unit": "km"},
|
|
60
|
+
factor_key="freight.rail.tonne_km")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Also available: `electricity`, `spend_based`, `business_travel`, and `batch(calculations=[...])`. Any methodology works via `gc.calculate("<methodology>", **body)`.
|
|
64
|
+
|
|
65
|
+
## Reproducibility
|
|
66
|
+
|
|
67
|
+
Pin any factor to a past data version so a figure reproduces exactly in an audit:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
gc.factor("grid.gbr.electricity.location_based", as_of="2026.111")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Errors
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from greencalculus import GreenCalculusError
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
gc.factor("does.not.exist")
|
|
80
|
+
except GreenCalculusError as e:
|
|
81
|
+
print(e.status, e.code, e.message)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Links
|
|
85
|
+
|
|
86
|
+
- Docs: https://greencalculus.com/developers/docs
|
|
87
|
+
- Data rights & continuity: https://greencalculus.com/developers/trust
|
|
88
|
+
- MCP server (agents): `mcp.greencalculus.com`
|
|
89
|
+
|
|
90
|
+
MIT licensed.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""GreenCalculus — the carbon-accounting API.
|
|
2
|
+
|
|
3
|
+
Sourced greenhouse-gas emission factors and audit-traced calculations, every
|
|
4
|
+
value traceable to its source cell and data version.
|
|
5
|
+
|
|
6
|
+
from greencalculus import GreenCalculus
|
|
7
|
+
|
|
8
|
+
gc = GreenCalculus(api_key="gc_live_...") # free key: greencalculus.com/developers
|
|
9
|
+
|
|
10
|
+
# a sourced factor
|
|
11
|
+
f = gc.factor("grid.gbr.electricity.location_based")
|
|
12
|
+
print(f["factor"]["value"], f["factor"]["unit"])
|
|
13
|
+
|
|
14
|
+
# an audit-traced calculation
|
|
15
|
+
r = gc.ghg_activity(activity={"value": 1000, "unit": "kWh"},
|
|
16
|
+
factor_key="grid.gbr.electricity.location_based")
|
|
17
|
+
print(r["emissions"]["value"], r["emissions"]["unit"])
|
|
18
|
+
|
|
19
|
+
# plain language -> the right factor
|
|
20
|
+
m = gc.resolve("UK grid electricity")
|
|
21
|
+
|
|
22
|
+
Zero third-party dependencies (standard library only).
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import json as _json
|
|
27
|
+
import urllib.error
|
|
28
|
+
import urllib.parse
|
|
29
|
+
import urllib.request
|
|
30
|
+
from typing import Any, Dict, List, Optional
|
|
31
|
+
|
|
32
|
+
__version__ = "0.1.0"
|
|
33
|
+
__all__ = ["GreenCalculus", "GreenCalculusError"]
|
|
34
|
+
|
|
35
|
+
DEFAULT_BASE_URL = "https://api.greencalculus.com"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GreenCalculusError(Exception):
|
|
39
|
+
"""Raised when the API returns a non-2xx response."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, status: int, code: str, message: str) -> None:
|
|
42
|
+
self.status = status
|
|
43
|
+
self.code = code
|
|
44
|
+
self.message = message
|
|
45
|
+
super().__init__(f"[{status} {code}] {message}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class GreenCalculus:
|
|
49
|
+
"""A thin, typed client for the GreenCalculus API."""
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
api_key: str,
|
|
54
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
55
|
+
timeout: float = 30.0,
|
|
56
|
+
) -> None:
|
|
57
|
+
if not api_key:
|
|
58
|
+
raise ValueError(
|
|
59
|
+
"api_key is required — get a free one at https://greencalculus.com/developers"
|
|
60
|
+
)
|
|
61
|
+
self.api_key = api_key
|
|
62
|
+
self.base_url = base_url.rstrip("/")
|
|
63
|
+
self.timeout = timeout
|
|
64
|
+
|
|
65
|
+
# ── transport ────────────────────────────────────────────────────────
|
|
66
|
+
def _request(
|
|
67
|
+
self,
|
|
68
|
+
method: str,
|
|
69
|
+
path: str,
|
|
70
|
+
params: Optional[Dict[str, Any]] = None,
|
|
71
|
+
body: Optional[Dict[str, Any]] = None,
|
|
72
|
+
) -> Dict[str, Any]:
|
|
73
|
+
url = self.base_url + path
|
|
74
|
+
if params:
|
|
75
|
+
clean = {k: v for k, v in params.items() if v is not None}
|
|
76
|
+
if clean:
|
|
77
|
+
url += "?" + urllib.parse.urlencode(clean)
|
|
78
|
+
data = _json.dumps(body).encode("utf-8") if body is not None else None
|
|
79
|
+
req = urllib.request.Request(
|
|
80
|
+
url,
|
|
81
|
+
data=data,
|
|
82
|
+
method=method,
|
|
83
|
+
headers={
|
|
84
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
"Accept": "application/json",
|
|
87
|
+
"User-Agent": f"greencalculus-python/{__version__}",
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
try:
|
|
91
|
+
with urllib.request.urlopen(req, timeout=self.timeout) as resp:
|
|
92
|
+
return _json.loads(resp.read().decode("utf-8"))
|
|
93
|
+
except urllib.error.HTTPError as exc:
|
|
94
|
+
err: Dict[str, Any] = {}
|
|
95
|
+
try:
|
|
96
|
+
err = _json.loads(exc.read().decode("utf-8")).get("error", {})
|
|
97
|
+
except Exception:
|
|
98
|
+
pass
|
|
99
|
+
raise GreenCalculusError(
|
|
100
|
+
exc.code, err.get("code", "http_error"), err.get("message", str(exc))
|
|
101
|
+
) from None
|
|
102
|
+
|
|
103
|
+
# ── factors ──────────────────────────────────────────────────────────
|
|
104
|
+
def factor(self, key: str, as_of: Optional[str] = None) -> Dict[str, Any]:
|
|
105
|
+
"""Look up a single emission factor by its canonical key.
|
|
106
|
+
|
|
107
|
+
Pass ``as_of="2026.111"`` to pin a past data version for reproducibility.
|
|
108
|
+
"""
|
|
109
|
+
return self._request(
|
|
110
|
+
"GET", "/v1/factors/" + urllib.parse.quote(key, safe=""), params={"as_of": as_of}
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def resolve(self, description: str, **kwargs: Any) -> Dict[str, Any]:
|
|
114
|
+
"""Resolve a plain-language description to the best-matched factor(s),
|
|
115
|
+
each with a confidence score."""
|
|
116
|
+
return self._request("POST", "/v1/calculate/resolve", body={"description": description, **kwargs})
|
|
117
|
+
|
|
118
|
+
# ── calculations ─────────────────────────────────────────────────────
|
|
119
|
+
def calculate(self, methodology: str, **body: Any) -> Dict[str, Any]:
|
|
120
|
+
"""Run a calculation. ``methodology`` is one of: ghg-activity, pcaf,
|
|
121
|
+
embodied, electricity, freight, spend-based, business-travel, batch."""
|
|
122
|
+
return self._request("POST", "/v1/calculate/" + methodology, body=body)
|
|
123
|
+
|
|
124
|
+
def ghg_activity(self, **body: Any) -> Dict[str, Any]:
|
|
125
|
+
"""GHG Protocol activity-based emissions (activity x factor)."""
|
|
126
|
+
return self.calculate("ghg-activity", **body)
|
|
127
|
+
|
|
128
|
+
def pcaf(self, **body: Any) -> Dict[str, Any]:
|
|
129
|
+
"""PCAF financed emissions."""
|
|
130
|
+
return self.calculate("pcaf", **body)
|
|
131
|
+
|
|
132
|
+
def embodied(self, **body: Any) -> Dict[str, Any]:
|
|
133
|
+
"""EN 15978 embodied carbon."""
|
|
134
|
+
return self.calculate("embodied", **body)
|
|
135
|
+
|
|
136
|
+
def electricity(self, **body: Any) -> Dict[str, Any]:
|
|
137
|
+
"""Scope 2 electricity (location/market based)."""
|
|
138
|
+
return self.calculate("electricity", **body)
|
|
139
|
+
|
|
140
|
+
def freight(self, **body: Any) -> Dict[str, Any]:
|
|
141
|
+
"""Freight / logistics (mass x distance)."""
|
|
142
|
+
return self.calculate("freight", **body)
|
|
143
|
+
|
|
144
|
+
def spend_based(self, **body: Any) -> Dict[str, Any]:
|
|
145
|
+
"""Spend-based EEIO estimation."""
|
|
146
|
+
return self.calculate("spend-based", **body)
|
|
147
|
+
|
|
148
|
+
def business_travel(self, **body: Any) -> Dict[str, Any]:
|
|
149
|
+
"""Business travel (passenger transport)."""
|
|
150
|
+
return self.calculate("business-travel", **body)
|
|
151
|
+
|
|
152
|
+
def batch(self, items: List[Dict[str, Any]]) -> Dict[str, Any]:
|
|
153
|
+
"""Run many calculations in one request. Each item names a `methodology`
|
|
154
|
+
and carries that methodology's own arguments."""
|
|
155
|
+
return self.calculate("batch", items=items)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: greencalculus
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The carbon-accounting API — sourced emission factors and audit-traced calculations, every value traceable to its source.
|
|
5
|
+
Author-email: GreenCalculus <jeremiah@greencalculus.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://greencalculus.com/developers
|
|
8
|
+
Project-URL: Documentation, https://greencalculus.com/developers/docs
|
|
9
|
+
Project-URL: Source, https://github.com/jeremiahsay/greencalculus-sdk
|
|
10
|
+
Keywords: carbon,emissions,co2,co2e,ghg,greenhouse-gas,emission-factors,esg,pcaf,climate,sustainability,carbon-accounting,scope-3,embodied-carbon,defra,ipcc
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# greencalculus
|
|
23
|
+
|
|
24
|
+
The official Python client for the [GreenCalculus API](https://greencalculus.com/developers) — sourced greenhouse-gas emission factors and audit-traced calculations. Every value comes back with its source cell and data version, so you hand back citable numbers, not guesses.
|
|
25
|
+
|
|
26
|
+
Zero third-party dependencies (standard library only).
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install greencalculus
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quickstart
|
|
35
|
+
|
|
36
|
+
Get a free API key (1,000 calls/month, no card) at **[greencalculus.com/developers](https://greencalculus.com/developers)**.
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from greencalculus import GreenCalculus
|
|
40
|
+
|
|
41
|
+
gc = GreenCalculus(api_key="gc_live_...")
|
|
42
|
+
|
|
43
|
+
# A sourced emission factor. value & unit are at the top level for convenience;
|
|
44
|
+
# the full sourced row (source cell, gas, GWP set) stays under ["factor"].
|
|
45
|
+
f = gc.factor("grid.gbr.electricity.location_based")
|
|
46
|
+
print(f["value"], f["unit"]) # 0.13096 kg CO2e per kWh
|
|
47
|
+
print(f["factor"]["source"]["id"]) # DEFRA_2026
|
|
48
|
+
|
|
49
|
+
# An audit-traced calculation — the full working, not just a total
|
|
50
|
+
r = gc.ghg_activity(
|
|
51
|
+
activity={"value": 1000, "unit": "kWh"},
|
|
52
|
+
factor_key="grid.gbr.electricity.location_based",
|
|
53
|
+
)
|
|
54
|
+
print(r["emissions"]["value"], r["emissions"]["unit"])
|
|
55
|
+
print(r["source"]["id"]) # e.g. EMBER_YEARLY_ELECTRICITY_2025
|
|
56
|
+
|
|
57
|
+
# Plain language -> the right factor, with a confidence score
|
|
58
|
+
m = gc.resolve("UK grid electricity")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Calculations
|
|
62
|
+
|
|
63
|
+
Every engine returns the formula, the source, the data version, and a deterministic receipt.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
gc.pcaf(asset_class="listed_equity_corporate_bonds", holdings=[{
|
|
67
|
+
"outstanding_amount": 1_000_000,
|
|
68
|
+
"denominator": {"type": "evic", "value": 2_500_000_000_000},
|
|
69
|
+
"company_emissions": {"value": 20_000_000},
|
|
70
|
+
"data_quality_score": 2,
|
|
71
|
+
}])
|
|
72
|
+
|
|
73
|
+
gc.embodied(materials=[{
|
|
74
|
+
"material_key": "materials.concrete.ready_mix.c8_10",
|
|
75
|
+
"quantity": {"value": 50, "unit": "m3"},
|
|
76
|
+
"boundary": "A1-C",
|
|
77
|
+
}])
|
|
78
|
+
|
|
79
|
+
gc.freight(mass={"value": 1, "unit": "tonne"},
|
|
80
|
+
distance={"value": 100, "unit": "km"},
|
|
81
|
+
factor_key="freight.rail.tonne_km")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Also available: `electricity`, `spend_based`, `business_travel`, and `batch(calculations=[...])`. Any methodology works via `gc.calculate("<methodology>", **body)`.
|
|
85
|
+
|
|
86
|
+
## Reproducibility
|
|
87
|
+
|
|
88
|
+
Pin any factor to a past data version so a figure reproduces exactly in an audit:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
gc.factor("grid.gbr.electricity.location_based", as_of="2026.111")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Errors
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from greencalculus import GreenCalculusError
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
gc.factor("does.not.exist")
|
|
101
|
+
except GreenCalculusError as e:
|
|
102
|
+
print(e.status, e.code, e.message)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Links
|
|
106
|
+
|
|
107
|
+
- Docs: https://greencalculus.com/developers/docs
|
|
108
|
+
- Data rights & continuity: https://greencalculus.com/developers/trust
|
|
109
|
+
- MCP server (agents): `mcp.greencalculus.com`
|
|
110
|
+
|
|
111
|
+
MIT licensed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
greencalculus
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "greencalculus"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "The carbon-accounting API — sourced emission factors and audit-traced calculations, every value traceable to its source."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "GreenCalculus", email = "jeremiah@greencalculus.com" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"carbon", "emissions", "co2", "co2e", "ghg", "greenhouse-gas",
|
|
15
|
+
"emission-factors", "esg", "pcaf", "climate", "sustainability",
|
|
16
|
+
"carbon-accounting", "scope-3", "embodied-carbon", "defra", "ipcc",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Topic :: Scientific/Engineering",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
|
+
]
|
|
26
|
+
dependencies = []
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://greencalculus.com/developers"
|
|
30
|
+
Documentation = "https://greencalculus.com/developers/docs"
|
|
31
|
+
Source = "https://github.com/jeremiahsay/greencalculus-sdk"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["."]
|
|
35
|
+
include = ["greencalculus*"]
|