ledgerdata 0.1.0.dev6__py3-none-any.whl
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.
- ledgerdata/__init__.py +15 -0
- ledgerdata/actors.py +204 -0
- ledgerdata/base.py +23 -0
- ledgerdata/client.py +225 -0
- ledgerdata/datasource.py +37 -0
- ledgerdata/emissions.py +64 -0
- ledgerdata/gdp.py +36 -0
- ledgerdata/gwp.py +38 -0
- ledgerdata/initiatives.py +37 -0
- ledgerdata/population.py +37 -0
- ledgerdata/sector.py +34 -0
- ledgerdata/targets.py +36 -0
- ledgerdata-0.1.0.dev6.dist-info/METADATA +34 -0
- ledgerdata-0.1.0.dev6.dist-info/RECORD +17 -0
- ledgerdata-0.1.0.dev6.dist-info/WHEEL +4 -0
- ledgerdata-0.1.0.dev6.dist-info/entry_points.txt +2 -0
- ledgerdata-0.1.0.dev6.dist-info/licenses/LICENSE +21 -0
ledgerdata/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Set up module access for the base package
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .actors import Actors
|
|
6
|
+
from .client import Client
|
|
7
|
+
from .datasource import Datasource
|
|
8
|
+
from .emissions import Emissions
|
|
9
|
+
from .gdp import GDP
|
|
10
|
+
from .initiatives import Initiatives
|
|
11
|
+
from .population import Population
|
|
12
|
+
from .sector import Sector
|
|
13
|
+
from .targets import Targets
|
|
14
|
+
|
|
15
|
+
__all__ = ["GDP", "Actors", "Client", "Datasource", "Emissions", "Initiatives", "Population", "Sector", "Targets"]
|
ledgerdata/actors.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import requests
|
|
5
|
+
from pydantic.dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from .base import Base
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class Actors(Base):
|
|
12
|
+
"""Provides methods to retrieve actor and actor-part data from the LEDGER API."""
|
|
13
|
+
|
|
14
|
+
def get_all_actors(self, *args, **kwargs):
|
|
15
|
+
"""Retrieve all actors.
|
|
16
|
+
|
|
17
|
+
Sends a GET request to the `/actors` endpoint and returns the response
|
|
18
|
+
as a JSON dictionary.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
dict: A JSON response containing actor data.
|
|
22
|
+
"""
|
|
23
|
+
endpoint = "/actor"
|
|
24
|
+
url = f"{self.server}{endpoint}"
|
|
25
|
+
headers = {"Accept": "application/json"}
|
|
26
|
+
# Add query parameters as a dict
|
|
27
|
+
response = requests.get(url, headers=headers).json()
|
|
28
|
+
# data_list = response.get("data", None)
|
|
29
|
+
return response
|
|
30
|
+
|
|
31
|
+
def parts_of_actor(self, actor_id=str, type: str | None = None, *args, **kwargs):
|
|
32
|
+
"""Retrieve parts (sub-actors) of a given actor.
|
|
33
|
+
|
|
34
|
+
Sends a GET request to the `/parts_of/{actor_id}` endpoint and returns
|
|
35
|
+
the response as a JSON dictionary.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
39
|
+
type (Optional[str]): Optional filter for part type.
|
|
40
|
+
*args: Additional positional arguments (currently unused).
|
|
41
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
dict: A JSON response containing actor-part data.
|
|
45
|
+
"""
|
|
46
|
+
endpoint = f"/actor/{actor_id}/parts"
|
|
47
|
+
url = f"{self.server}{endpoint}"
|
|
48
|
+
headers = {"Accept": "application/json"}
|
|
49
|
+
params = {"type": type} if type else {}
|
|
50
|
+
response = requests.get(url, headers=headers, params=params).json()
|
|
51
|
+
# data_list = response.get("data", None)
|
|
52
|
+
return response
|
|
53
|
+
|
|
54
|
+
def population(self, actor_id=str, *args, **kwargs):
|
|
55
|
+
"""Retrieve actor population
|
|
56
|
+
|
|
57
|
+
Sends a GET request to the `/actor/{actor_id}/population` endpoint and returns
|
|
58
|
+
the response as a JSON dictionary.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
62
|
+
*args: Additional positional arguments (currently unused).
|
|
63
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
dict: A JSON response containing actor-part data.
|
|
67
|
+
"""
|
|
68
|
+
endpoint = f"/actor/{actor_id}/population"
|
|
69
|
+
url = f"{self.server}{endpoint}"
|
|
70
|
+
headers = {"Accept": "application/json"}
|
|
71
|
+
response = requests.get(url, headers=headers).json()
|
|
72
|
+
return response
|
|
73
|
+
|
|
74
|
+
def gdp(self, actor_id=str, *args, **kwargs):
|
|
75
|
+
"""Retrieve actor population
|
|
76
|
+
|
|
77
|
+
Sends a GET request to the `/actor/{actor_id}/gdp` endpoint and returns
|
|
78
|
+
the response as a JSON dictionary.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
82
|
+
*args: Additional positional arguments (currently unused).
|
|
83
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
dict: A JSON response containing actor-part data.
|
|
87
|
+
"""
|
|
88
|
+
endpoint = f"/actor/{actor_id}/gdp"
|
|
89
|
+
url = f"{self.server}{endpoint}"
|
|
90
|
+
headers = {"Accept": "application/json"}
|
|
91
|
+
response = requests.get(url, headers=headers).json()
|
|
92
|
+
return response
|
|
93
|
+
|
|
94
|
+
def energy_consumption(self, actor_id=str, *args, **kwargs):
|
|
95
|
+
"""Retrieve actor population
|
|
96
|
+
|
|
97
|
+
Sends a GET request to the `/actor/{actor_id}/energy_consumption` endpoint and returns
|
|
98
|
+
the response as a JSON dictionary.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
102
|
+
*args: Additional positional arguments (currently unused).
|
|
103
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
dict: A JSON response containing actor-part data.
|
|
107
|
+
"""
|
|
108
|
+
endpoint = f"/actor/{actor_id}/energy_consumption"
|
|
109
|
+
url = f"{self.server}{endpoint}"
|
|
110
|
+
headers = {"Accept": "application/json"}
|
|
111
|
+
response = requests.get(url, headers=headers).json()
|
|
112
|
+
return response
|
|
113
|
+
|
|
114
|
+
def targets(self, actor_id=str, *args, **kwargs):
|
|
115
|
+
"""Retrieve actor population
|
|
116
|
+
|
|
117
|
+
Sends a GET request to the `/actor/{actor_id}/targets` endpoint and returns
|
|
118
|
+
the response as a JSON dictionary.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
122
|
+
*args: Additional positional arguments (currently unused).
|
|
123
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
dict: A JSON response containing actor-part data.
|
|
127
|
+
"""
|
|
128
|
+
endpoint = f"/actor/{actor_id}/targets"
|
|
129
|
+
url = f"{self.server}{endpoint}"
|
|
130
|
+
headers = {"Accept": "application/json"}
|
|
131
|
+
response = requests.get(url, headers=headers).json()
|
|
132
|
+
return response
|
|
133
|
+
|
|
134
|
+
def emissions(self, actor_id=str, ignore_warnings: bool = False, *args, **kwargs):
|
|
135
|
+
"""Retrieve actor population
|
|
136
|
+
|
|
137
|
+
Sends a GET request to the `/actor/{actor_id}/emissions` endpoint and returns
|
|
138
|
+
the response as a JSON dictionary.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
142
|
+
*args: Additional positional arguments (currently unused).
|
|
143
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
dict: A JSON response containing actor-part data.
|
|
147
|
+
"""
|
|
148
|
+
(
|
|
149
|
+
warnings.simplefilter("ignore")
|
|
150
|
+
if ignore_warnings
|
|
151
|
+
else warnings.simplefilter("default")
|
|
152
|
+
)
|
|
153
|
+
endpoint = f"/actor/{actor_id}/emissions"
|
|
154
|
+
url = f"{self.server}{endpoint}"
|
|
155
|
+
headers = {"Accept": "application/json"}
|
|
156
|
+
response = requests.get(url, headers=headers).json()
|
|
157
|
+
return response
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def emissions_total_sector(self, actor_id=str, ignore_warnings: bool = False, *args, **kwargs):
|
|
161
|
+
"""Retrieve actor population
|
|
162
|
+
|
|
163
|
+
Sends a GET request to the `/actor/{actor_id}/emissions_total_sector` endpoint and returns
|
|
164
|
+
the response as a JSON dictionary.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
actor_id (str): The code for the actor whose parts you want to retrieve.
|
|
168
|
+
*args: Additional positional arguments (currently unused).
|
|
169
|
+
**kwargs: Additional keyword arguments (currently unused).
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
dict: A JSON response containing actor-part data.
|
|
173
|
+
"""
|
|
174
|
+
(
|
|
175
|
+
warnings.simplefilter("ignore")
|
|
176
|
+
if ignore_warnings
|
|
177
|
+
else warnings.simplefilter("default")
|
|
178
|
+
)
|
|
179
|
+
endpoint = f"/actor/{actor_id}/emissions_total_sector"
|
|
180
|
+
url = f"{self.server}{endpoint}"
|
|
181
|
+
headers = {"Accept": "application/json"}
|
|
182
|
+
response = requests.get(url, headers=headers).json()
|
|
183
|
+
return response
|
|
184
|
+
|
|
185
|
+
async def emissions_async(
|
|
186
|
+
self, actor_id: str, ignore_warnings: bool = False, *args, **kwargs
|
|
187
|
+
):
|
|
188
|
+
"""Retrieve actor emissions asynchronously."""
|
|
189
|
+
if ignore_warnings:
|
|
190
|
+
warnings.simplefilter("ignore")
|
|
191
|
+
else:
|
|
192
|
+
warnings.simplefilter("default")
|
|
193
|
+
|
|
194
|
+
endpoint = f"/actor/{actor_id}/emissions"
|
|
195
|
+
url = f"{self.server}{endpoint}"
|
|
196
|
+
headers = {
|
|
197
|
+
"Accept": "application/json",
|
|
198
|
+
"User-Agent": "python-httpx/1.0",
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async with httpx.AsyncClient() as client:
|
|
202
|
+
response = await client.get(url, headers=headers)
|
|
203
|
+
response.raise_for_status()
|
|
204
|
+
return response.json()
|
ledgerdata/base.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
from pydantic import HttpUrl
|
|
4
|
+
from pydantic.dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Env(str, Enum):
|
|
8
|
+
dev = "dev"
|
|
9
|
+
prod = "prod"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class Base:
|
|
14
|
+
version: str = "/api/v0"
|
|
15
|
+
env: Env = Env.prod
|
|
16
|
+
|
|
17
|
+
def __post_init__(self):
|
|
18
|
+
urls = {
|
|
19
|
+
Env.dev: "http://127.0.0.1:8000",
|
|
20
|
+
Env.prod: "https://orca-app-5ivtt.ondigitalocean.app",
|
|
21
|
+
}
|
|
22
|
+
self.base_url: HttpUrl = urls[self.env]
|
|
23
|
+
self.server = f"{self.base_url}{self.version}"
|
ledgerdata/client.py
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
from .actors import Actors
|
|
7
|
+
from .base import Base
|
|
8
|
+
from .datasource import Datasource
|
|
9
|
+
from .gwp import GWP
|
|
10
|
+
from .initiatives import Initiatives
|
|
11
|
+
from .sector import Sector
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class Client(Base):
|
|
16
|
+
"""ledgerdata client class
|
|
17
|
+
|
|
18
|
+
a high-level class to interact with the ledger database
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
version: str = API version (default "/api/v0)
|
|
22
|
+
env: str = "prod" for production server or "dev" for local development (default "prod")
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Limit concurrency to 10 requests at once, adjust as needed
|
|
26
|
+
_sem = asyncio.Semaphore(10)
|
|
27
|
+
|
|
28
|
+
def get_all_actors(
|
|
29
|
+
self,
|
|
30
|
+
) -> pd.DataFrame:
|
|
31
|
+
"""retreive all actors
|
|
32
|
+
|
|
33
|
+
this method is used to retriece a dataframe of all actors and their codes
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
DataFrame: data of all actors
|
|
37
|
+
"""
|
|
38
|
+
return pd.DataFrame(Actors(env=self.env, version=self.version).get_all_actors())
|
|
39
|
+
|
|
40
|
+
def parts_of_actor(
|
|
41
|
+
self, actor_id: str, part_type: str | None = None, *args, **kwargs
|
|
42
|
+
) -> pd.DataFrame:
|
|
43
|
+
"""retreive actor parts
|
|
44
|
+
|
|
45
|
+
returns subnational, cities, companies, etc. within an actor_id
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
49
|
+
part_type (str): retrieve actors from administrative part ['planet', 'country', 'adm1', 'adm2', 'city', 'organization', 'site']
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
DataFrame: dataframe of actors parts
|
|
53
|
+
"""
|
|
54
|
+
return pd.DataFrame(
|
|
55
|
+
Actors(env=self.env, version=self.version).parts_of_actor(
|
|
56
|
+
actor_id=actor_id, type=part_type
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def gwp(
|
|
61
|
+
self,
|
|
62
|
+
assessment_report=None,
|
|
63
|
+
) -> pd.DataFrame:
|
|
64
|
+
"""retreive global warming potentials
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
DataFrame: data for GWPs
|
|
71
|
+
"""
|
|
72
|
+
return pd.DataFrame(
|
|
73
|
+
GWP(env=self.env, version=self.version).gwp(
|
|
74
|
+
assessment_report=assessment_report
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def datasource(
|
|
79
|
+
self,
|
|
80
|
+
datasource_id=None,
|
|
81
|
+
) -> pd.DataFrame:
|
|
82
|
+
"""retrieve data sources
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
datasource_id (str|List[str]): code for datasource
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
DataFrame: data for datasources
|
|
89
|
+
"""
|
|
90
|
+
return pd.DataFrame(
|
|
91
|
+
Datasource(env=self.env, version=self.version).datasource(
|
|
92
|
+
datasource_id=datasource_id
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def sector(self) -> pd.DataFrame:
|
|
97
|
+
"""retrieve sectors
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
DataFrame: data for sectors
|
|
101
|
+
"""
|
|
102
|
+
return pd.DataFrame(Sector(env=self.env, version=self.version).sector())
|
|
103
|
+
|
|
104
|
+
def emissions(
|
|
105
|
+
self,
|
|
106
|
+
actor_id: str,
|
|
107
|
+
) -> pd.DataFrame:
|
|
108
|
+
"""retreive actor emissions
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
DataFrame: data for each emissions dataset
|
|
115
|
+
"""
|
|
116
|
+
return pd.DataFrame(
|
|
117
|
+
Actors(env=self.env, version=self.version).emissions(actor_id=actor_id)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def emissions_total_sector(
|
|
122
|
+
self,
|
|
123
|
+
actor_id: str,
|
|
124
|
+
) -> pd.DataFrame:
|
|
125
|
+
"""retreive actor emissions by sector
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
DataFrame: data for each emissions dataset
|
|
132
|
+
"""
|
|
133
|
+
return pd.DataFrame(
|
|
134
|
+
Actors(env=self.env, version=self.version).emissions_total_sector(actor_id=actor_id)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def emissions_raw(
|
|
138
|
+
self,
|
|
139
|
+
actor_id: str,
|
|
140
|
+
) -> pd.DataFrame:
|
|
141
|
+
"""retreive actor emissions raw
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
DataFrame: data for each emissions dataset
|
|
148
|
+
"""
|
|
149
|
+
return Actors(env=self.env, version=self.version).emissions(actor_id=actor_id)
|
|
150
|
+
|
|
151
|
+
def targets(self, actor_id: str) -> pd.DataFrame:
|
|
152
|
+
"""retreive actor targets
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
DataFrame: dataframe of targets
|
|
159
|
+
"""
|
|
160
|
+
return pd.DataFrame(
|
|
161
|
+
Actors(env=self.env, version=self.version).targets(actor_id=actor_id)
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def initiatives(self, initiative: str) -> pd.DataFrame:
|
|
166
|
+
"""retrieve initiatives
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
initiative (str|List[str]): initiative namme
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
DataFrame: dataframe of initiatives
|
|
173
|
+
"""
|
|
174
|
+
return pd.DataFrame(
|
|
175
|
+
Initiatives(env=self.env, version=self.version).initiatives(initiative=initiative)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def population(self, actor_id: str) -> pd.DataFrame:
|
|
179
|
+
"""retreive actor population
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
183
|
+
ignore_warnings (bool): ignore warning messages
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
DataFrame: dataframe of population
|
|
187
|
+
"""
|
|
188
|
+
return pd.DataFrame(
|
|
189
|
+
Actors(env=self.env, version=self.version).population(actor_id=actor_id)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def gdp(self, actor_id: str) -> pd.DataFrame:
|
|
193
|
+
"""retreive actor gdp
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
actor_id (str|List[str]): code for actor your want to retrieve
|
|
197
|
+
ignore_warnings (bool): ignore warning messages
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
DataFrame: dataframe of gdp
|
|
201
|
+
"""
|
|
202
|
+
return pd.DataFrame(
|
|
203
|
+
Actors(env=self.env, version=self.version).gdp(actor_id=actor_id)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
async def emissions_async(self, actor_id: str) -> pd.DataFrame:
|
|
207
|
+
data = await Actors(env=self.env, version=self.version).emissions_async(
|
|
208
|
+
actor_id=actor_id
|
|
209
|
+
)
|
|
210
|
+
return pd.DataFrame(data)
|
|
211
|
+
|
|
212
|
+
async def _emissions_with_sem(self, actor_id: str) -> pd.DataFrame:
|
|
213
|
+
async with self._sem:
|
|
214
|
+
return await self.emissions_async(actor_id)
|
|
215
|
+
|
|
216
|
+
async def emissions_many(self, actor_ids: list[str]) -> list[pd.DataFrame]:
|
|
217
|
+
tasks = [self._emissions_with_sem(actor_id) for actor_id in actor_ids]
|
|
218
|
+
return await asyncio.gather(*tasks)
|
|
219
|
+
|
|
220
|
+
# sync wrappers that run the async code in an event loop
|
|
221
|
+
def emissions_sync(self, actor_id: str) -> pd.DataFrame:
|
|
222
|
+
return asyncio.run(self.emissions_async(actor_id))
|
|
223
|
+
|
|
224
|
+
def emissions_many_sync(self, actor_ids: list[str]) -> list[pd.DataFrame]:
|
|
225
|
+
return asyncio.run(self.emissions_many(actor_ids))
|
ledgerdata/datasource.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from pydantic.dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from .base import Base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Datasource(Base):
|
|
9
|
+
"""retrieve emissions
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
object
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def datasource(self, datasource_id=None, *args, **kwargs):
|
|
16
|
+
"""retrieve actor emissions
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
datasource_id (str): code for datasource
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
DataFrame:
|
|
23
|
+
"""
|
|
24
|
+
endpoint = "/datasource/"
|
|
25
|
+
url = f"{self.server}{endpoint}"
|
|
26
|
+
headers = {
|
|
27
|
+
"Accept": "application/json",
|
|
28
|
+
"User-Agent": "python-httpx/1.0",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Add query parameters
|
|
32
|
+
params = {}
|
|
33
|
+
if datasource_id:
|
|
34
|
+
params["datasource_id"] = datasource_id
|
|
35
|
+
|
|
36
|
+
response = requests.get(url, headers=headers, params=params).json()
|
|
37
|
+
return response
|
ledgerdata/emissions.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import requests
|
|
5
|
+
from pydantic.dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from .base import Base
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class Emissions(Base):
|
|
12
|
+
"""retrieve emissions
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
object
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def emissions(self, actor_id: str, ignore_warnings: bool = False, *args, **kwargs):
|
|
19
|
+
"""retreive actor emissions
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
actor_id (str): code for actor your want to retrieve
|
|
23
|
+
ignore_warnings (bool): ignore warning messages
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
DataFrame: data for each emissions dataset
|
|
27
|
+
"""
|
|
28
|
+
(
|
|
29
|
+
warnings.simplefilter("ignore")
|
|
30
|
+
if ignore_warnings
|
|
31
|
+
else warnings.simplefilter("default")
|
|
32
|
+
)
|
|
33
|
+
endpoint = f"/actor/{actor_id}/emissions"
|
|
34
|
+
url = f"{self.server}{endpoint}"
|
|
35
|
+
headers = {
|
|
36
|
+
"Accept": "application/json",
|
|
37
|
+
"User-Agent": "python-httpx/1.0",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
response = requests.get(url, headers=headers).json()
|
|
41
|
+
# data_list = response.get("data", None)
|
|
42
|
+
# df = pd.DataFrame(response).sort_values(by=["year"])
|
|
43
|
+
return response
|
|
44
|
+
|
|
45
|
+
async def emissions_async(
|
|
46
|
+
self, actor_id: str, ignore_warnings: bool = False, *args, **kwargs
|
|
47
|
+
):
|
|
48
|
+
"""Retrieve actor emissions asynchronously."""
|
|
49
|
+
if ignore_warnings:
|
|
50
|
+
warnings.simplefilter("ignore")
|
|
51
|
+
else:
|
|
52
|
+
warnings.simplefilter("default")
|
|
53
|
+
|
|
54
|
+
endpoint = f"/actor/{actor_id}/emissions"
|
|
55
|
+
url = f"{self.server}{endpoint}"
|
|
56
|
+
headers = {
|
|
57
|
+
"Accept": "application/json",
|
|
58
|
+
"User-Agent": "python-httpx/1.0",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async with httpx.AsyncClient() as client:
|
|
62
|
+
response = await client.get(url, headers=headers)
|
|
63
|
+
response.raise_for_status()
|
|
64
|
+
return response.json()
|
ledgerdata/gdp.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import ClassVar
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import requests
|
|
6
|
+
from pydantic.dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from .base import Base
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ActorData(Base):
|
|
13
|
+
endpoint: ClassVar[str]
|
|
14
|
+
|
|
15
|
+
def fetch(
|
|
16
|
+
self,
|
|
17
|
+
actor_id: str,
|
|
18
|
+
ignore_warnings: bool = False,
|
|
19
|
+
*args,
|
|
20
|
+
**kwargs,
|
|
21
|
+
):
|
|
22
|
+
"""Retrieve actor data for the given endpoint."""
|
|
23
|
+
if ignore_warnings:
|
|
24
|
+
warnings.simplefilter("ignore")
|
|
25
|
+
else:
|
|
26
|
+
warnings.simplefilter("default")
|
|
27
|
+
|
|
28
|
+
url = f"{self.server}{self.endpoint}/{actor_id}"
|
|
29
|
+
headers = {"Accept": "application/json"}
|
|
30
|
+
response = requests.get(url, headers=headers).json()
|
|
31
|
+
return pd.DataFrame(response)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class GDP(ActorData):
|
|
36
|
+
endpoint: ClassVar[str] = "/gdp"
|
ledgerdata/gwp.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from pydantic.dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from .base import Base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class GWP(Base):
|
|
9
|
+
"""retrieve emissions
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
object
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def gwp(self, assessment_report=None, *args, **kwargs):
|
|
16
|
+
"""retreive actor emissions
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
actor_id (str): code for actor your want to retrieve
|
|
20
|
+
ignore_warnings (bool): ignore warning messages
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
DataFrame: data for each emissions dataset
|
|
24
|
+
"""
|
|
25
|
+
endpoint = "/gwp/"
|
|
26
|
+
url = f"{self.server}{endpoint}"
|
|
27
|
+
headers = {
|
|
28
|
+
"Accept": "application/json",
|
|
29
|
+
"User-Agent": "python-httpx/1.0",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Add query parameters
|
|
33
|
+
params = {}
|
|
34
|
+
if assessment_report:
|
|
35
|
+
params["assessment_report"] = assessment_report
|
|
36
|
+
|
|
37
|
+
response = requests.get(url, headers=headers, params=params).json()
|
|
38
|
+
return response
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from pydantic.dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from .base import Base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Initiatives(Base):
|
|
9
|
+
"""retrieve emissions
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
object
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def initiatives(self, initiative="us_climate_alliance", *args, **kwargs):
|
|
16
|
+
"""retreive actors part of an initiative
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
initiative (str): InitiativeType
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
DataFrame: data for selected initiative
|
|
23
|
+
"""
|
|
24
|
+
endpoint = "/initiatives/"
|
|
25
|
+
url = f"{self.server}{endpoint}"
|
|
26
|
+
headers = {
|
|
27
|
+
"Accept": "application/json",
|
|
28
|
+
"User-Agent": "python-httpx/1.0",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Add query parameters
|
|
32
|
+
params = {}
|
|
33
|
+
if initiative:
|
|
34
|
+
params["initiative"] = initiative
|
|
35
|
+
|
|
36
|
+
response = requests.get(url, headers=headers, params=params).json()
|
|
37
|
+
return response
|
ledgerdata/population.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from pydantic.dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from .base import Base
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class Population(Base):
|
|
11
|
+
"""ActorOveriew API class
|
|
12
|
+
get overview information of an actor
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
object
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def population(self, actor_id: str, ignore_warnings: bool = False, *args, **kwargs):
|
|
19
|
+
"""retrieve population data
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
actor_id (str): code for actor your want to retrieve
|
|
23
|
+
ignore_warnings (bool): ignore warning messages
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
DataFrame: data for each emissions dataset
|
|
27
|
+
"""
|
|
28
|
+
(
|
|
29
|
+
warnings.simplefilter("ignore")
|
|
30
|
+
if ignore_warnings
|
|
31
|
+
else warnings.simplefilter("default")
|
|
32
|
+
)
|
|
33
|
+
endpoint = f"/population/{actor_id}"
|
|
34
|
+
url = f"{self.server}{endpoint}"
|
|
35
|
+
headers = {"Accept": "application/json"}
|
|
36
|
+
response = requests.get(url, headers=headers).json()
|
|
37
|
+
return response
|
ledgerdata/sector.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from pydantic.dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from .base import Base
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Sector(Base):
|
|
9
|
+
"""retrieve sectors
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
object
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def sector(self, *args, **kwargs):
|
|
16
|
+
"""retrieve sectors
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
DataFrame:
|
|
20
|
+
"""
|
|
21
|
+
endpoint = "/sector/"
|
|
22
|
+
url = f"{self.server}{endpoint}"
|
|
23
|
+
headers = {
|
|
24
|
+
"Accept": "application/json",
|
|
25
|
+
"User-Agent": "python-httpx/1.0",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Add query parameters
|
|
29
|
+
params = {}
|
|
30
|
+
# if datasource_id:
|
|
31
|
+
# params["datasource_id"] = datasource_id
|
|
32
|
+
|
|
33
|
+
response = requests.get(url, headers=headers, params=params).json()
|
|
34
|
+
return response
|
ledgerdata/targets.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from pydantic.dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from .base import Base
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class Targets(Base):
|
|
11
|
+
"""retrieve emission targets
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
object
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def targets(self, actor_id: str, ignore_warnings: bool = False, *args, **kwargs):
|
|
18
|
+
"""retreive actor emissions
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
actor_id (str): code for actor your want to retrieve
|
|
22
|
+
ignore_warnings (bool): ignore warning messages
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
DataFrame: data for each emissions dataset
|
|
26
|
+
"""
|
|
27
|
+
(
|
|
28
|
+
warnings.simplefilter("ignore")
|
|
29
|
+
if ignore_warnings
|
|
30
|
+
else warnings.simplefilter("default")
|
|
31
|
+
)
|
|
32
|
+
endpoint = f"/targets/{actor_id}"
|
|
33
|
+
url = f"{self.server}{endpoint}"
|
|
34
|
+
headers = {"Accept": "application/json"}
|
|
35
|
+
response = requests.get(url, headers=headers).json()
|
|
36
|
+
return response
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: ledgerdata
|
|
3
|
+
Version: 0.1.0.dev6
|
|
4
|
+
Summary: Python client for LEDGER database
|
|
5
|
+
Author-email: Luke Gloege <lucas.gloege@yale.edu>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
|
+
Requires-Dist: httpx>=0.28.1
|
|
9
|
+
Requires-Dist: pandas>=3.0.6
|
|
10
|
+
Requires-Dist: psycopg>=3.3.6
|
|
11
|
+
Requires-Dist: pydantic>=2.14.1
|
|
12
|
+
Requires-Dist: requests>=2.34.2
|
|
13
|
+
Requires-Dist: ruff>=0.17.2
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# ledgerdata: The LEDGER Python Client
|
|
17
|
+
|
|
18
|
+
This Repo contains the LEDGER Python Client
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv add git+https://github.com/LEDGER-project/ledgerdata.git@main
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
or with pip
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install git+https://github.com/LEDGER-project/ledgerdata.git@main
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Documentation
|
|
33
|
+
|
|
34
|
+
The official documentation for the entire LEDGER project is available at: [https://ledger-project.github.io/](https://ledger-project.github.io/)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
ledgerdata/__init__.py,sha256=kQkuE0d_JWQxmbZUPRLUeB2Y0QSg045ejs3WMI8oKpU,438
|
|
2
|
+
ledgerdata/actors.py,sha256=fJLKa40Hu9OSS8yDmH9BYaejv9nYBejjJp6dwFwSNj0,7600
|
|
3
|
+
ledgerdata/base.py,sha256=yzbVcouYXPDcyf5SqhbXIZ7CigE-tjMGWjX9hoUuspM,504
|
|
4
|
+
ledgerdata/client.py,sha256=4vhnSyo5T0fHnijlm4FAs5tibnDAiCsQJ4XGygBfjrs,6577
|
|
5
|
+
ledgerdata/datasource.py,sha256=n-0qQILAXxjDBS2ckdY67uoqnk142ozvfg4EpPYALG8,828
|
|
6
|
+
ledgerdata/emissions.py,sha256=6P_vuMpNsF0EhL5qKhlDSUwnmNM0zu65FQHXSwuaeCg,1813
|
|
7
|
+
ledgerdata/gdp.py,sha256=O0u03vvF8Y7aoivHdQF9obngbrkXikYYXxVRz4depKQ,811
|
|
8
|
+
ledgerdata/gwp.py,sha256=YhjvlO5kPynt5IsD5qyg2r16LcnOufihWI1gOWbOX4Y,927
|
|
9
|
+
ledgerdata/initiatives.py,sha256=L1UfrQAPtts95-GA3llFf7sU46c3UfyYEuwwdd2uYBU,871
|
|
10
|
+
ledgerdata/population.py,sha256=Plo-IfvrnAmwTUjAGhztprvWcPU8sj50bX0wpKGb9Xc,961
|
|
11
|
+
ledgerdata/sector.py,sha256=KKF0SsgMgP5OH1C_OyLD2CBQ9yax3SkQQyahsx1wp4A,721
|
|
12
|
+
ledgerdata/targets.py,sha256=P9fMl4C9lAN0GtkvUBL20AnMWgw4qKMTGQ4UvkaqKT8,914
|
|
13
|
+
ledgerdata-0.1.0.dev6.dist-info/METADATA,sha256=3OvPuUAqpgV60qfajpc4aUmJN_Looaed_VKjsAkewTE,858
|
|
14
|
+
ledgerdata-0.1.0.dev6.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
15
|
+
ledgerdata-0.1.0.dev6.dist-info/entry_points.txt,sha256=-jmCqcPPOqamUodczh91vTv1zMG_kQyDUOQmt3eO5MI,47
|
|
16
|
+
ledgerdata-0.1.0.dev6.dist-info/licenses/LICENSE,sha256=vFovm9NfuoM4HokZBt6sYh7tTXwUSRNCYp_ugpqGzk0,1071
|
|
17
|
+
ledgerdata-0.1.0.dev6.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LEDGER-project
|
|
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.
|