meteocatpy 0.0.11 → 0.0.13

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.
Files changed (40) hide show
  1. package/.github/workflows/release.yml +33 -33
  2. package/.gitlab-ci.yml +46 -46
  3. package/.pre-commit-config.yaml +37 -37
  4. package/.releaserc +23 -23
  5. package/.releaserc.toml +14 -14
  6. package/AUTHORS.md +12 -12
  7. package/CHANGELOG.md +187 -171
  8. package/README.md +61 -61
  9. package/filetree.py +48 -48
  10. package/filetree.txt +48 -48
  11. package/meteocatpy/README.md +61 -61
  12. package/meteocatpy/__init__.py +27 -27
  13. package/meteocatpy/const.py +10 -10
  14. package/meteocatpy/data.py +93 -93
  15. package/meteocatpy/exceptions.py +35 -35
  16. package/meteocatpy/forecast.py +137 -137
  17. package/meteocatpy/helpers.py +46 -46
  18. package/meteocatpy/stations.py +71 -71
  19. package/meteocatpy/symbols.py +89 -89
  20. package/meteocatpy/town.py +61 -61
  21. package/meteocatpy/townstations.py +99 -99
  22. package/meteocatpy/variables.py +77 -77
  23. package/meteocatpy/version.py +2 -2
  24. package/package.json +23 -23
  25. package/poetry.lock +3313 -3313
  26. package/pyproject.toml +72 -72
  27. package/releaserc.json +17 -17
  28. package/requirements.test.txt +3 -3
  29. package/setup.cfg +64 -64
  30. package/setup.py +10 -10
  31. package/tests/data_test.py +122 -122
  32. package/tests/import_test.py +18 -18
  33. package/tests/integration_test_complete.py +76 -76
  34. package/tests/integration_test_forecast.py +54 -54
  35. package/tests/integration_test_station_data.py +33 -33
  36. package/tests/integration_test_stations.py +31 -31
  37. package/tests/integration_test_symbols.py +68 -68
  38. package/tests/integration_test_town.py +32 -32
  39. package/tests/integration_test_town_stations.py +36 -36
  40. package/tests/integration_test_variables.py +32 -32
@@ -1,89 +1,89 @@
1
- import aiohttp
2
- from .const import BASE_URL, SYMBOLS_URL
3
- from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
4
-
5
-
6
- class MeteocatSymbols:
7
- """Clase para interactuar con la API de símbolos de Meteocat."""
8
-
9
- def __init__(self, api_key: str):
10
- """
11
- Inicializa la clase MeteocatSymbols.
12
-
13
- Args:
14
- api_key (str): Clave de API para autenticar las solicitudes.
15
- """
16
- self.api_key = api_key
17
- self.headers = {
18
- "Content-Type": "application/json",
19
- "X-Api-Key": self.api_key,
20
- }
21
- self.symbols_map = {}
22
-
23
- async def fetch_symbols(self):
24
- url = f"{BASE_URL}{SYMBOLS_URL}"
25
- async with aiohttp.ClientSession() as session:
26
- try:
27
- async with session.get(url, headers=self.headers) as response:
28
- if response.status == 200:
29
- data = await response.json()
30
- print(data) # Esto te mostrará la estructura completa en la consola
31
-
32
- # Asegurarse de que `data` sea una lista de categorías
33
- if isinstance(data, list):
34
- self.symbols_map = {}
35
- for category in data:
36
- if "valors" in category:
37
- # Guardamos los valores de cada categoría
38
- self.symbols_map[category["nom"]] = category["valors"]
39
- return data # Devolvemos todo el conjunto de datos
40
-
41
- else:
42
- raise UnknownAPIError(f"Unexpected structure of data: {data}", status_code=response.status)
43
-
44
- # Gestionar errores de respuesta
45
- if response.status == 400:
46
- raise BadRequestError(await response.json())
47
- elif response.status == 403:
48
- error_data = await response.json()
49
- if error_data.get("message") == "Forbidden":
50
- raise ForbiddenError(error_data)
51
- elif error_data.get("message") == "Missing Authentication Token":
52
- raise ForbiddenError(error_data)
53
- elif response.status == 429:
54
- raise TooManyRequestsError(await response.json())
55
- elif response.status == 500:
56
- raise InternalServerError(await response.json())
57
- else:
58
- raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}", status_code=response.status)
59
-
60
- except aiohttp.ClientError as e:
61
- raise UnknownAPIError(
62
- message=f"Error al conectar con la API de Meteocat: {str(e)}",
63
- status_code=0,
64
- )
65
-
66
- except Exception as ex:
67
- raise UnknownAPIError(
68
- message=f"Error inesperado: {str(ex)}",
69
- status_code=0,
70
- )
71
-
72
-
73
-
74
- def get_description(self, category: str, code: int) -> str:
75
- """
76
- Obtiene la descripción de un código de símbolo dentro de una categoría.
77
-
78
- Args:
79
- category (str): Nombre de la categoría (e.g., "cel").
80
- code (int): Código del símbolo.
81
-
82
- Returns:
83
- str: Descripción del símbolo. Retorna 'Desconocido' si el código no está en el mapeo.
84
- """
85
- category_symbols = self.symbols_map.get(category, [])
86
- for symbol in category_symbols:
87
- if symbol["codi"] == str(code): # El código es devuelto como string por la API
88
- return symbol["descripcio"]
89
- return "Desconocido"
1
+ import aiohttp
2
+ from .const import BASE_URL, SYMBOLS_URL
3
+ from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
4
+
5
+
6
+ class MeteocatSymbols:
7
+ """Clase para interactuar con la API de símbolos de Meteocat."""
8
+
9
+ def __init__(self, api_key: str):
10
+ """
11
+ Inicializa la clase MeteocatSymbols.
12
+
13
+ Args:
14
+ api_key (str): Clave de API para autenticar las solicitudes.
15
+ """
16
+ self.api_key = api_key
17
+ self.headers = {
18
+ "Content-Type": "application/json",
19
+ "X-Api-Key": self.api_key,
20
+ }
21
+ self.symbols_map = {}
22
+
23
+ async def fetch_symbols(self):
24
+ url = f"{BASE_URL}{SYMBOLS_URL}"
25
+ async with aiohttp.ClientSession() as session:
26
+ try:
27
+ async with session.get(url, headers=self.headers) as response:
28
+ if response.status == 200:
29
+ data = await response.json()
30
+ print(data) # Esto te mostrará la estructura completa en la consola
31
+
32
+ # Asegurarse de que `data` sea una lista de categorías
33
+ if isinstance(data, list):
34
+ self.symbols_map = {}
35
+ for category in data:
36
+ if "valors" in category:
37
+ # Guardamos los valores de cada categoría
38
+ self.symbols_map[category["nom"]] = category["valors"]
39
+ return data # Devolvemos todo el conjunto de datos
40
+
41
+ else:
42
+ raise UnknownAPIError(f"Unexpected structure of data: {data}", status_code=response.status)
43
+
44
+ # Gestionar errores de respuesta
45
+ if response.status == 400:
46
+ raise BadRequestError(await response.json())
47
+ elif response.status == 403:
48
+ error_data = await response.json()
49
+ if error_data.get("message") == "Forbidden":
50
+ raise ForbiddenError(error_data)
51
+ elif error_data.get("message") == "Missing Authentication Token":
52
+ raise ForbiddenError(error_data)
53
+ elif response.status == 429:
54
+ raise TooManyRequestsError(await response.json())
55
+ elif response.status == 500:
56
+ raise InternalServerError(await response.json())
57
+ else:
58
+ raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}", status_code=response.status)
59
+
60
+ except aiohttp.ClientError as e:
61
+ raise UnknownAPIError(
62
+ message=f"Error al conectar con la API de Meteocat: {str(e)}",
63
+ status_code=0,
64
+ )
65
+
66
+ except Exception as ex:
67
+ raise UnknownAPIError(
68
+ message=f"Error inesperado: {str(ex)}",
69
+ status_code=0,
70
+ )
71
+
72
+
73
+
74
+ def get_description(self, category: str, code: int) -> str:
75
+ """
76
+ Obtiene la descripción de un código de símbolo dentro de una categoría.
77
+
78
+ Args:
79
+ category (str): Nombre de la categoría (e.g., "cel").
80
+ code (int): Código del símbolo.
81
+
82
+ Returns:
83
+ str: Descripción del símbolo. Retorna 'Desconocido' si el código no está en el mapeo.
84
+ """
85
+ category_symbols = self.symbols_map.get(category, [])
86
+ for symbol in category_symbols:
87
+ if symbol["codi"] == str(code): # El código es devuelto como string por la API
88
+ return symbol["descripcio"]
89
+ return "Desconocido"
@@ -1,61 +1,61 @@
1
- import aiohttp
2
- from .const import BASE_URL, MUNICIPIS_LIST_URL
3
- from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
4
-
5
- class MeteocatTown:
6
- """Clase para interactuar con la lista de municipios de la API de Meteocat."""
7
-
8
- def __init__(self, api_key: str):
9
- """
10
- Inicializa la clase MeteocatTown.
11
-
12
- Args:
13
- api_key (str): Clave de API para autenticar las solicitudes.
14
- """
15
- self.api_key = api_key
16
- self.headers = {
17
- "Content-Type": "application/json",
18
- "X-Api-Key": self.api_key,
19
- }
20
-
21
- async def get_municipis(self):
22
- """
23
- Obtiene la lista de municipios desde la API de Meteocat.
24
-
25
- Returns:
26
- dict: Datos de los municipios.
27
- """
28
- url = f"{BASE_URL}{MUNICIPIS_LIST_URL}"
29
- async with aiohttp.ClientSession() as session:
30
- try:
31
- async with session.get(url, headers=self.headers) as response:
32
- if response.status == 200:
33
- return await response.json()
34
-
35
- # Gestionar errores según el código de estado
36
- if response.status == 400:
37
- raise BadRequestError(await response.json())
38
- elif response.status == 403:
39
- error_data = await response.json()
40
- if error_data.get("message") == "Forbidden":
41
- raise ForbiddenError(error_data)
42
- elif error_data.get("message") == "Missing Authentication Token":
43
- raise ForbiddenError(error_data)
44
- elif response.status == 429:
45
- raise TooManyRequestsError(await response.json())
46
- elif response.status == 500:
47
- raise InternalServerError(await response.json())
48
- else:
49
- raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}")
50
-
51
- except aiohttp.ClientError as e:
52
- raise UnknownAPIError(
53
- message=f"Error al conectar con la API de Meteocat: {str(e)}",
54
- status_code=0,
55
- )
56
-
57
- except Exception as ex:
58
- raise UnknownAPIError(
59
- message=f"Error inesperado: {str(ex)}",
60
- status_code=0,
61
- )
1
+ import aiohttp
2
+ from .const import BASE_URL, MUNICIPIS_LIST_URL
3
+ from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
4
+
5
+ class MeteocatTown:
6
+ """Clase para interactuar con la lista de municipios de la API de Meteocat."""
7
+
8
+ def __init__(self, api_key: str):
9
+ """
10
+ Inicializa la clase MeteocatTown.
11
+
12
+ Args:
13
+ api_key (str): Clave de API para autenticar las solicitudes.
14
+ """
15
+ self.api_key = api_key
16
+ self.headers = {
17
+ "Content-Type": "application/json",
18
+ "X-Api-Key": self.api_key,
19
+ }
20
+
21
+ async def get_municipis(self):
22
+ """
23
+ Obtiene la lista de municipios desde la API de Meteocat.
24
+
25
+ Returns:
26
+ dict: Datos de los municipios.
27
+ """
28
+ url = f"{BASE_URL}{MUNICIPIS_LIST_URL}"
29
+ async with aiohttp.ClientSession() as session:
30
+ try:
31
+ async with session.get(url, headers=self.headers) as response:
32
+ if response.status == 200:
33
+ return await response.json()
34
+
35
+ # Gestionar errores según el código de estado
36
+ if response.status == 400:
37
+ raise BadRequestError(await response.json())
38
+ elif response.status == 403:
39
+ error_data = await response.json()
40
+ if error_data.get("message") == "Forbidden":
41
+ raise ForbiddenError(error_data)
42
+ elif error_data.get("message") == "Missing Authentication Token":
43
+ raise ForbiddenError(error_data)
44
+ elif response.status == 429:
45
+ raise TooManyRequestsError(await response.json())
46
+ elif response.status == 500:
47
+ raise InternalServerError(await response.json())
48
+ else:
49
+ raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}")
50
+
51
+ except aiohttp.ClientError as e:
52
+ raise UnknownAPIError(
53
+ message=f"Error al conectar con la API de Meteocat: {str(e)}",
54
+ status_code=0,
55
+ )
56
+
57
+ except Exception as ex:
58
+ raise UnknownAPIError(
59
+ message=f"Error inesperado: {str(ex)}",
60
+ status_code=0,
61
+ )
@@ -1,99 +1,99 @@
1
- import aiohttp
2
- from .stations import MeteocatStations # Importamos la clase MeteocatStations
3
- from .const import BASE_URL, STATIONS_MUNICIPI_URL
4
- from .exceptions import (
5
- BadRequestError,
6
- ForbiddenError,
7
- TooManyRequestsError,
8
- InternalServerError,
9
- UnknownAPIError,
10
- )
11
-
12
- class MeteocatTownStations:
13
- """
14
- Clase para interactuar con la API de Meteocat y obtener
15
- las estaciones representativas de un municipio para una variable específica.
16
- """
17
-
18
- def __init__(self, api_key: str):
19
- """
20
- Inicializa la clase MeteocatTownStations.
21
-
22
- Args:
23
- api_key (str): Clave de API para autenticar las solicitudes.
24
- """
25
- self.api_key = api_key
26
- self.headers = {
27
- "Content-Type": "application/json",
28
- "X-Api-Key": self.api_key,
29
- }
30
- self.stations_service = MeteocatStations(api_key) # Instancia de MeteocatStations
31
-
32
- async def get_town_stations(self, town_id: str, variable_id: str):
33
- """
34
- Obtiene la lista de estaciones representativas para un municipio y una variable específica,
35
- enriqueciendo los datos con el nombre de las estaciones.
36
-
37
- Args:
38
- codi_municipi (str): Código del municipio.
39
- codi_variable (str): Código de la variable.
40
-
41
- Returns:
42
- list: Datos de las estaciones representativas con nombres añadidos.
43
- """
44
- # Obtener la lista completa de estaciones
45
- all_stations = await self.stations_service.get_stations()
46
-
47
- # Crear un diccionario para acceder rápidamente a los nombres por código
48
- station_names = {station["codi"]: station["nom"] for station in all_stations}
49
-
50
- # URL para obtener las estaciones del municipio y la variable
51
- url = f"{BASE_URL}{STATIONS_MUNICIPI_URL}".format(
52
- codi_municipi=town_id, codi_variable=variable_id
53
- )
54
-
55
- async with aiohttp.ClientSession() as session:
56
- try:
57
- async with session.get(url, headers=self.headers) as response:
58
- if response.status == 200:
59
- data = await response.json()
60
-
61
- # Enriquecer el JSON con los nombres de las estaciones
62
- for town in data:
63
- for variable in town.get("variables", []):
64
- for station in variable.get("estacions", []):
65
- codi = station["codi"]
66
- station["nom"] = station_names.get(codi, "Nombre desconocido")
67
-
68
- return data
69
-
70
- # Gestionar errores según el código de estado
71
- if response.status == 400:
72
- raise BadRequestError(await response.json())
73
- elif response.status == 403:
74
- error_data = await response.json()
75
- if error_data.get("message") == "Forbidden":
76
- raise ForbiddenError(error_data)
77
- elif error_data.get("message") == "Missing Authentication Token":
78
- raise ForbiddenError(error_data)
79
- elif response.status == 429:
80
- raise TooManyRequestsError(await response.json())
81
- elif response.status == 500:
82
- raise InternalServerError(await response.json())
83
- else:
84
- raise UnknownAPIError(
85
- f"Unexpected error {response.status}: {await response.text()}"
86
- )
87
-
88
- except aiohttp.ClientError as e:
89
- raise UnknownAPIError(
90
- message=f"Error al conectar con la API de Meteocat: {str(e)}",
91
- status_code=0,
92
- )
93
-
94
- except Exception as ex:
95
- raise UnknownAPIError(
96
- message=f"Error inesperado: {str(ex)}",
97
- status_code=0,
98
- )
99
-
1
+ import aiohttp
2
+ from .stations import MeteocatStations # Importamos la clase MeteocatStations
3
+ from .const import BASE_URL, STATIONS_MUNICIPI_URL
4
+ from .exceptions import (
5
+ BadRequestError,
6
+ ForbiddenError,
7
+ TooManyRequestsError,
8
+ InternalServerError,
9
+ UnknownAPIError,
10
+ )
11
+
12
+ class MeteocatTownStations:
13
+ """
14
+ Clase para interactuar con la API de Meteocat y obtener
15
+ las estaciones representativas de un municipio para una variable específica.
16
+ """
17
+
18
+ def __init__(self, api_key: str):
19
+ """
20
+ Inicializa la clase MeteocatTownStations.
21
+
22
+ Args:
23
+ api_key (str): Clave de API para autenticar las solicitudes.
24
+ """
25
+ self.api_key = api_key
26
+ self.headers = {
27
+ "Content-Type": "application/json",
28
+ "X-Api-Key": self.api_key,
29
+ }
30
+ self.stations_service = MeteocatStations(api_key) # Instancia de MeteocatStations
31
+
32
+ async def get_town_stations(self, town_id: str, variable_id: str):
33
+ """
34
+ Obtiene la lista de estaciones representativas para un municipio y una variable específica,
35
+ enriqueciendo los datos con el nombre de las estaciones.
36
+
37
+ Args:
38
+ codi_municipi (str): Código del municipio.
39
+ codi_variable (str): Código de la variable.
40
+
41
+ Returns:
42
+ list: Datos de las estaciones representativas con nombres añadidos.
43
+ """
44
+ # Obtener la lista completa de estaciones
45
+ all_stations = await self.stations_service.get_stations()
46
+
47
+ # Crear un diccionario para acceder rápidamente a los nombres por código
48
+ station_names = {station["codi"]: station["nom"] for station in all_stations}
49
+
50
+ # URL para obtener las estaciones del municipio y la variable
51
+ url = f"{BASE_URL}{STATIONS_MUNICIPI_URL}".format(
52
+ codi_municipi=town_id, codi_variable=variable_id
53
+ )
54
+
55
+ async with aiohttp.ClientSession() as session:
56
+ try:
57
+ async with session.get(url, headers=self.headers) as response:
58
+ if response.status == 200:
59
+ data = await response.json()
60
+
61
+ # Enriquecer el JSON con los nombres de las estaciones
62
+ for town in data:
63
+ for variable in town.get("variables", []):
64
+ for station in variable.get("estacions", []):
65
+ codi = station["codi"]
66
+ station["nom"] = station_names.get(codi, "Nombre desconocido")
67
+
68
+ return data
69
+
70
+ # Gestionar errores según el código de estado
71
+ if response.status == 400:
72
+ raise BadRequestError(await response.json())
73
+ elif response.status == 403:
74
+ error_data = await response.json()
75
+ if error_data.get("message") == "Forbidden":
76
+ raise ForbiddenError(error_data)
77
+ elif error_data.get("message") == "Missing Authentication Token":
78
+ raise ForbiddenError(error_data)
79
+ elif response.status == 429:
80
+ raise TooManyRequestsError(await response.json())
81
+ elif response.status == 500:
82
+ raise InternalServerError(await response.json())
83
+ else:
84
+ raise UnknownAPIError(
85
+ f"Unexpected error {response.status}: {await response.text()}"
86
+ )
87
+
88
+ except aiohttp.ClientError as e:
89
+ raise UnknownAPIError(
90
+ message=f"Error al conectar con la API de Meteocat: {str(e)}",
91
+ status_code=0,
92
+ )
93
+
94
+ except Exception as ex:
95
+ raise UnknownAPIError(
96
+ message=f"Error inesperado: {str(ex)}",
97
+ status_code=0,
98
+ )
99
+
@@ -1,77 +1,77 @@
1
- import aiohttp
2
- from diskcache import Cache
3
- import os
4
- from .const import BASE_URL, VARIABLES_URL
5
- from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
6
-
7
- class MeteocatVariables:
8
- """Clase para interactuar con la lista de variables de la API de Meteocat."""
9
-
10
- def __init__(self, api_key: str, cache_dir: str = None):
11
- """
12
- Inicializa la clase MeteocatVariables.
13
-
14
- Args:
15
- api_key (str): Clave de API para autenticar las solicitudes.
16
- """
17
- self.api_key = api_key
18
- self.headers = {
19
- "Content-Type": "application/json",
20
- "X-Api-Key": self.api_key,
21
- }
22
-
23
- # Configurar la ruta de caché
24
- self._cache_dir = cache_dir or ".meteocat_cache"
25
- self._cache = Cache(self._cache_dir)
26
-
27
- async def get_variables(self, force_update=False):
28
- """
29
- Obtiene la lista de variables desde la API de Meteocat. Usa la caché si está disponible.
30
-
31
- Args:
32
- force_update (bool): Si es True, fuerza la actualización desde la API.
33
-
34
- Returns:
35
- list: Datos de las variables.
36
- """
37
- # Verificar si las variables están en caché y no se solicita actualización forzada
38
- if not force_update and "variables" in self._cache:
39
- return self._cache["variables"]
40
-
41
- # Hacer la solicitud a la API para obtener las variables
42
- url = f"{BASE_URL}{VARIABLES_URL}"
43
- async with aiohttp.ClientSession() as session:
44
- try:
45
- async with session.get(url, headers=self.headers) as response:
46
- if response.status == 200:
47
- variables = await response.json()
48
- self._cache["variables"] = variables # Guardar en caché
49
- return variables
50
-
51
- # Gestionar errores según el código de estado
52
- if response.status == 400:
53
- raise BadRequestError(await response.json())
54
- elif response.status == 403:
55
- error_data = await response.json()
56
- if error_data.get("message") == "Forbidden":
57
- raise ForbiddenError(error_data)
58
- elif error_data.get("message") == "Missing Authentication Token":
59
- raise ForbiddenError(error_data)
60
- elif response.status == 429:
61
- raise TooManyRequestsError(await response.json())
62
- elif response.status == 500:
63
- raise InternalServerError(await response.json())
64
- else:
65
- raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}")
66
-
67
- except aiohttp.ClientError as e:
68
- raise UnknownAPIError(
69
- message=f"Error al conectar con la API de Meteocat: {str(e)}",
70
- status_code=0,
71
- )
72
-
73
- except Exception as ex:
74
- raise UnknownAPIError(
75
- message=f"Error inesperado: {str(ex)}",
76
- status_code=0,
77
- )
1
+ import aiohttp
2
+ from diskcache import Cache
3
+ import os
4
+ from .const import BASE_URL, VARIABLES_URL
5
+ from .exceptions import BadRequestError, ForbiddenError, TooManyRequestsError, InternalServerError, UnknownAPIError
6
+
7
+ class MeteocatVariables:
8
+ """Clase para interactuar con la lista de variables de la API de Meteocat."""
9
+
10
+ def __init__(self, api_key: str, cache_dir: str = None):
11
+ """
12
+ Inicializa la clase MeteocatVariables.
13
+
14
+ Args:
15
+ api_key (str): Clave de API para autenticar las solicitudes.
16
+ """
17
+ self.api_key = api_key
18
+ self.headers = {
19
+ "Content-Type": "application/json",
20
+ "X-Api-Key": self.api_key,
21
+ }
22
+
23
+ # Configurar la ruta de caché
24
+ self._cache_dir = os.path.join("custom_components", "meteocat", ".meteocat_cache")
25
+ self._cache = Cache(self._cache_dir)
26
+
27
+ async def get_variables(self, force_update=False):
28
+ """
29
+ Obtiene la lista de variables desde la API de Meteocat. Usa la caché si está disponible.
30
+
31
+ Args:
32
+ force_update (bool): Si es True, fuerza la actualización desde la API.
33
+
34
+ Returns:
35
+ list: Datos de las variables.
36
+ """
37
+ # Verificar si las variables están en caché y no se solicita actualización forzada
38
+ if not force_update and "variables" in self._cache:
39
+ return self._cache["variables"]
40
+
41
+ # Hacer la solicitud a la API para obtener las variables
42
+ url = f"{BASE_URL}{VARIABLES_URL}"
43
+ async with aiohttp.ClientSession() as session:
44
+ try:
45
+ async with session.get(url, headers=self.headers) as response:
46
+ if response.status == 200:
47
+ variables = await response.json()
48
+ self._cache["variables"] = variables # Guardar en caché
49
+ return variables
50
+
51
+ # Gestionar errores según el código de estado
52
+ if response.status == 400:
53
+ raise BadRequestError(await response.json())
54
+ elif response.status == 403:
55
+ error_data = await response.json()
56
+ if error_data.get("message") == "Forbidden":
57
+ raise ForbiddenError(error_data)
58
+ elif error_data.get("message") == "Missing Authentication Token":
59
+ raise ForbiddenError(error_data)
60
+ elif response.status == 429:
61
+ raise TooManyRequestsError(await response.json())
62
+ elif response.status == 500:
63
+ raise InternalServerError(await response.json())
64
+ else:
65
+ raise UnknownAPIError(f"Unexpected error {response.status}: {await response.text()}")
66
+
67
+ except aiohttp.ClientError as e:
68
+ raise UnknownAPIError(
69
+ message=f"Error al conectar con la API de Meteocat: {str(e)}",
70
+ status_code=0,
71
+ )
72
+
73
+ except Exception as ex:
74
+ raise UnknownAPIError(
75
+ message=f"Error inesperado: {str(ex)}",
76
+ status_code=0,
77
+ )