python-esios 0.1.0__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.
- esios/__init__.py +0 -0
- esios/api_client.py +19 -0
- esios/endpoints/__init__.py +3 -0
- esios/endpoints/archives/__init__.py +0 -0
- esios/endpoints/archives/archives.py +32 -0
- esios/endpoints/indicators/__init__.py +143 -0
- esios/tests/__init__.py +0 -0
- esios/tests/test_api_client.py +15 -0
- esios/tests/test_indicators.py +20 -0
- python_esios-0.1.0.dist-info/LICENSE +0 -0
- python_esios-0.1.0.dist-info/METADATA +35 -0
- python_esios-0.1.0.dist-info/RECORD +14 -0
- python_esios-0.1.0.dist-info/WHEEL +5 -0
- python_esios-0.1.0.dist-info/top_level.txt +1 -0
esios/__init__.py
ADDED
|
File without changes
|
esios/api_client.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
|
|
3
|
+
class APIClient:
|
|
4
|
+
base_url = 'https://api.esios.ree.es'
|
|
5
|
+
headers = {
|
|
6
|
+
'Accept': "application/json; application/vnd.esios-api-v1+json",
|
|
7
|
+
'Content-Type': "application/json",
|
|
8
|
+
'Host': 'api.esios.ree.es',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
def __init__(self, api_key):
|
|
12
|
+
self.api_key = api_key
|
|
13
|
+
self.headers['x-api-key'] = self.api_key
|
|
14
|
+
|
|
15
|
+
def _api_call(self, method, endpoint, params=None, data=None):
|
|
16
|
+
url = self.base_url + endpoint
|
|
17
|
+
response = requests.request(method, url, headers=self.headers, params=params, json=data)
|
|
18
|
+
response.raise_for_status()
|
|
19
|
+
return response
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from esios.api_client import APIClient
|
|
4
|
+
from esios.utils import preprocessing
|
|
5
|
+
|
|
6
|
+
class Archives(APIClient):
|
|
7
|
+
def __init__(self, api_key):
|
|
8
|
+
super().__init__(api_key)
|
|
9
|
+
|
|
10
|
+
def list(self, params=None):
|
|
11
|
+
endpoint = "/archives"
|
|
12
|
+
response = self._api_call('GET', endpoint)
|
|
13
|
+
return response.json()
|
|
14
|
+
|
|
15
|
+
def get(self, archive_id, params=None, write_home=None):
|
|
16
|
+
endpoint = f"/archives/{archive_id}/download"
|
|
17
|
+
response = self._api_call('GET', endpoint, params=params)
|
|
18
|
+
|
|
19
|
+
if write_home:
|
|
20
|
+
path = os.path.join(write_home, f'{archive_id}.zip')
|
|
21
|
+
with open(path, 'wb') as f:
|
|
22
|
+
f.write(response.content)
|
|
23
|
+
preprocessing.unzip_files_and_remove(path)
|
|
24
|
+
|
|
25
|
+
return ArchiveData(response.content)
|
|
26
|
+
|
|
27
|
+
class ArchiveData:
|
|
28
|
+
def __init__(self, data):
|
|
29
|
+
self.data = data
|
|
30
|
+
|
|
31
|
+
def to_pandas(self):
|
|
32
|
+
return pd.DataFrame(self.data)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from esios.api_client import APIClient
|
|
3
|
+
import html
|
|
4
|
+
from bs4 import BeautifulSoup
|
|
5
|
+
|
|
6
|
+
class Indicators(APIClient):
|
|
7
|
+
def __init__(self, api_key):
|
|
8
|
+
super().__init__(api_key)
|
|
9
|
+
|
|
10
|
+
def list(self, df=False):
|
|
11
|
+
"""
|
|
12
|
+
Fetches a list of indicators.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
params : dict, optional
|
|
17
|
+
URL parameters to be sent with the request.
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
list
|
|
22
|
+
A list of indicators.
|
|
23
|
+
"""
|
|
24
|
+
endpoint = "/indicators"
|
|
25
|
+
response = self._api_call('GET', endpoint)
|
|
26
|
+
|
|
27
|
+
data = response.json()
|
|
28
|
+
|
|
29
|
+
if df:
|
|
30
|
+
df = pd.DataFrame(data['indicators'])
|
|
31
|
+
df['description'] = df['description'].apply(html.unescape)
|
|
32
|
+
df
|
|
33
|
+
return df.set_index('id')
|
|
34
|
+
else:
|
|
35
|
+
return data
|
|
36
|
+
|
|
37
|
+
def get(self, indicator_id, start_date=None, end_date=None, geo_ids=None, locale=None, time_agg=None, geo_agg=None, time_trunc=None, geo_trunc=None):
|
|
38
|
+
"""
|
|
39
|
+
Fetches disaggregated indicator data optionally filtered by a date range and geo_ids,
|
|
40
|
+
grouped by geo_id and month, using specified aggregation settings. All parameters except
|
|
41
|
+
the indicator_id are optional.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
indicator_id : int
|
|
46
|
+
The ID of the indicator to fetch data for.
|
|
47
|
+
start_date : str, optional
|
|
48
|
+
The start date of the data range in ISO 8601 format (YYYY-MM-DD).
|
|
49
|
+
end_date : str, optional
|
|
50
|
+
The end date of the data range in ISO 8601 format (YYYY-MM-DD).
|
|
51
|
+
geo_ids : list of int, optional
|
|
52
|
+
A list of geographic IDs to filter the data by.
|
|
53
|
+
locale : str, optional, default 'es'
|
|
54
|
+
Language for translations. Defaults to Spanish ('es'). Can be 'es' for Spanish or 'en' for English.
|
|
55
|
+
time_agg : str, optional, default 'average'
|
|
56
|
+
Specifies how to aggregate the data over time. Typical values are 'average', 'sum', etc.
|
|
57
|
+
geo_agg : str, optional, default 'average'
|
|
58
|
+
Specifies how to aggregate the data geographically. Typical values are 'average', 'sum', etc.
|
|
59
|
+
time_trunc : str, optional
|
|
60
|
+
Specifies how to truncate the data time series. Typical values are 'day', 'month', 'year', etc.
|
|
61
|
+
geo_trunc : str, optional
|
|
62
|
+
Specifies how to group data at the geolocalization level. Typical values are 'province', 'region', etc.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
IndicatorData
|
|
67
|
+
An instance of IndicatorData containing the fetched data.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
params = {}
|
|
71
|
+
if start_date:
|
|
72
|
+
params['start_date'] = start_date
|
|
73
|
+
if end_date:
|
|
74
|
+
params['end_date'] = end_date + 'T23:59:59'
|
|
75
|
+
if geo_ids:
|
|
76
|
+
params['geo_ids'] = ','.join(map(str, geo_ids))
|
|
77
|
+
if locale:
|
|
78
|
+
params['locale'] = locale
|
|
79
|
+
if time_agg:
|
|
80
|
+
params['time_agg'] = time_agg
|
|
81
|
+
if geo_agg:
|
|
82
|
+
params['geo_agg'] = geo_agg
|
|
83
|
+
if time_trunc:
|
|
84
|
+
params['time_trunc'] = time_trunc
|
|
85
|
+
if geo_trunc:
|
|
86
|
+
params['geo_trunc'] = geo_trunc
|
|
87
|
+
|
|
88
|
+
endpoint = f"/indicators/{indicator_id}"
|
|
89
|
+
response = self._api_call('GET', endpoint, params=params)
|
|
90
|
+
return IndicatorData(response.json())
|
|
91
|
+
|
|
92
|
+
class IndicatorData:
|
|
93
|
+
def __init__(self, data):
|
|
94
|
+
self.data = data
|
|
95
|
+
|
|
96
|
+
def to_dataframe(self, column_name='value'):
|
|
97
|
+
"""
|
|
98
|
+
Converts the indicator values data to a Pandas DataFrame.
|
|
99
|
+
|
|
100
|
+
Parameters
|
|
101
|
+
-------
|
|
102
|
+
column_name : {'value', 'id', 'short_name'}, default 'value'
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
pandas.DataFrame
|
|
107
|
+
A DataFrame containing the indicator values.
|
|
108
|
+
"""
|
|
109
|
+
data = self.data.get('indicator', {})
|
|
110
|
+
values = data.get('values', [])
|
|
111
|
+
|
|
112
|
+
if values:
|
|
113
|
+
df = pd.DataFrame(values)
|
|
114
|
+
df = df.set_index('datetime')
|
|
115
|
+
df.index = pd.to_datetime(df.index, utc=True)
|
|
116
|
+
|
|
117
|
+
columns = df.columns
|
|
118
|
+
mask = columns.str.contains('time')
|
|
119
|
+
|
|
120
|
+
df.drop(columns=columns[mask], inplace=True)
|
|
121
|
+
|
|
122
|
+
if column_name != 'value':
|
|
123
|
+
df = df.rename(columns={'value': data[column_name]})
|
|
124
|
+
|
|
125
|
+
return df.tz_convert('Europe/Madrid')
|
|
126
|
+
else:
|
|
127
|
+
return pd.DataFrame()
|
|
128
|
+
|
|
129
|
+
def get_metadata(self):
|
|
130
|
+
"""
|
|
131
|
+
Extracts metadata from the indicator data.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
dict
|
|
136
|
+
A dictionary containing the metadata of the indicator.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
# extract all inside indicator key, except values
|
|
140
|
+
metadata = self.data.get('indicator', {})
|
|
141
|
+
metadata.pop('values', None)
|
|
142
|
+
|
|
143
|
+
return metadata
|
esios/tests/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from esios.api_client import APIClient
|
|
3
|
+
|
|
4
|
+
class TestAPIClient(unittest.TestCase):
|
|
5
|
+
|
|
6
|
+
def setUp(self):
|
|
7
|
+
self.api_client = APIClient(api_key="test_key")
|
|
8
|
+
|
|
9
|
+
def test_api_call(self):
|
|
10
|
+
# This test is just a placeholder
|
|
11
|
+
# You would mock requests and test _api_call
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
if __name__ == '__main__':
|
|
15
|
+
unittest.main()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from esios.endpoints.indicators import Indicators
|
|
3
|
+
|
|
4
|
+
class TestIndicators(unittest.TestCase):
|
|
5
|
+
|
|
6
|
+
def setUp(self):
|
|
7
|
+
self.indicators_client = Indicators(api_key="test_key")
|
|
8
|
+
|
|
9
|
+
def test_list(self):
|
|
10
|
+
# This test is just a placeholder
|
|
11
|
+
# You would mock requests and test the list method
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
def test_get(self):
|
|
15
|
+
# This test is just a placeholder
|
|
16
|
+
# You would mock requests and test the get method
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
if __name__ == '__main__':
|
|
20
|
+
unittest.main()
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: python-esios
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python wrapper for the ESIOS API
|
|
5
|
+
Home-page: https://github.com/datons/python-esios
|
|
6
|
+
Author: Jesús López
|
|
7
|
+
Author-email: jesus.lopez@datons.ai
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests
|
|
15
|
+
Requires-Dist: pandas
|
|
16
|
+
|
|
17
|
+
# ESIOS
|
|
18
|
+
|
|
19
|
+
ESIOS is a Python library that wraps the ESIOS API and returns preprocessed data as Pandas DataFrames.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
This library provides a simple interface to interact with the ESIOS API, allowing you to fetch and process indicator data.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
You can install the library using pip:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install python-esios
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Visit the [instructions here](https://github.com/datons/python-esios/blob/main/esios/endpoints/indicators/README.ipynb) and learn how to use the library.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
esios/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
esios/api_client.py,sha256=YZFcXeAmaiebGu2CfSO0qxUidZWn2QiPOktzS-6v3Nk,629
|
|
3
|
+
esios/endpoints/__init__.py,sha256=yNcxKzZGpa_ftPZdk9AhgjzQZjmpfuhNA14Fprp6vLo,60
|
|
4
|
+
esios/endpoints/archives/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
esios/endpoints/archives/archives.py,sha256=2ynY_hE_YXZyPy_O22fJfcLWRHtDDIZ5sitRfV7C8So,943
|
|
6
|
+
esios/endpoints/indicators/__init__.py,sha256=tvXs32eIO2zWZYw_SXJyZwxeKeJQa2rqzD2OeRqe2QA,4832
|
|
7
|
+
esios/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
esios/tests/test_api_client.py,sha256=rotc2dEmKrdm_JMX76H_hmBtihlJp5tS4hGIWPUz458,360
|
|
9
|
+
esios/tests/test_indicators.py,sha256=jymdpuDYh0QCicBYsaCJCipm847xeEA2FjyjSRxS43c,520
|
|
10
|
+
python_esios-0.1.0.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
python_esios-0.1.0.dist-info/METADATA,sha256=CbIdTKQt9Hvso_pt-dGfXPtLCEd5pNoNYmycx14sHOk,995
|
|
12
|
+
python_esios-0.1.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
13
|
+
python_esios-0.1.0.dist-info/top_level.txt,sha256=73ob1QLIeSFvhLPrdMM7880xfv9FfWLkq2ZlxRRA9vs,6
|
|
14
|
+
python_esios-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
esios
|