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.
@@ -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,8 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ greencalculus/__init__.py
5
+ greencalculus.egg-info/PKG-INFO
6
+ greencalculus.egg-info/SOURCES.txt
7
+ greencalculus.egg-info/dependency_links.txt
8
+ greencalculus.egg-info/top_level.txt
@@ -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*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+