meteocatpy 0.0.14 → 0.0.16

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## [0.0.16](https://github.com/figorr/meteocatpy/compare/v0.0.15...v0.0.16) (2024-12-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * 0.0.16 ([a59edbc](https://github.com/figorr/meteocatpy/commit/a59edbcff6297346113b411405122b9fe6e9fe14))
7
+ * fix installation at README ([15e4651](https://github.com/figorr/meteocatpy/commit/15e46517254c0f9bdd82adf8038a17ae6e4339d5))
8
+ * ignore uvi test json file ([87189ce](https://github.com/figorr/meteocatpy/commit/87189cea76510a75fa41c015aa522075ba71d19f))
9
+ * improve data recovery when invalid date ([3b72e7e](https://github.com/figorr/meteocatpy/commit/3b72e7e1aeb34485e1226c56f2b6cce385b19f38))
10
+ * json file name ([6e97de1](https://github.com/figorr/meteocatpy/commit/6e97de1d585c17936b316eb1fcc1b5ac2b5275d9))
11
+
12
+ ## [0.0.15](https://github.com/figorr/meteocatpy/compare/v0.0.14...v0.0.15) (2024-12-13)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * 0.0.15 ([e4362bf](https://github.com/figorr/meteocatpy/commit/e4362bf9830c8eb5f9aa6fd803d06bf6bb64c2c8))
18
+ * add MeteocatUviData ([49807fe](https://github.com/figorr/meteocatpy/commit/49807fe195098db59a654d015942352cb3705b93))
19
+ * add MeteocatUviData class ([16e5eaf](https://github.com/figorr/meteocatpy/commit/16e5eaf7c918c673ab4648d1c3194144605d3249))
20
+ * add uvi url ([b6a42c5](https://github.com/figorr/meteocatpy/commit/b6a42c5f2bc405359c49c7c5f106d576f5c70d9e))
21
+ * ignore uvi test json ([4df4501](https://github.com/figorr/meteocatpy/commit/4df450166c4d01b67e096a754506d6d939ba09a5))
22
+
1
23
  ## [0.0.14](https://github.com/figorr/meteocatpy/compare/v0.0.13...v0.0.14) (2024-12-12)
2
24
 
3
25
 
package/README.md CHANGED
@@ -17,14 +17,14 @@ pip install meteocatpy
17
17
  ```
18
18
 
19
19
  ```bash
20
- from meteocatpy.client import MeteocatClient
20
+ from meteocatpy.town import MeteocatTown
21
21
 
22
22
  # Replace 'tu_api_key' with your actual API key
23
23
  api_key = "tu_api_key"
24
- client = MeteocatClient(api_key)
24
+ town_client = MeteocatTown(api_key)
25
25
 
26
26
  # Get a list of municipalities (asynchronous call)
27
- municipis = await client.get_municipis()
27
+ municipios_data = await town_client.get_municipis()
28
28
  print(municipis)
29
29
  ```
30
30
 
@@ -15,6 +15,7 @@ from .stations import MeteocatStations
15
15
  from .townstations import MeteocatTownStations
16
16
  from .data import MeteocatStationData
17
17
  from .variables import MeteocatVariables
18
+ from .uvi import MeteocatUviData
18
19
 
19
20
  __all__ = [
20
21
  "MeteocatTown",
@@ -23,5 +24,6 @@ __all__ = [
23
24
  "MeteocatStations",
24
25
  "MeteocatTownStations",
25
26
  "MeteocatStationData",
26
- "MeteocatVariables"
27
+ "MeteocatVariables",
28
+ "MeteocatUviData"
27
29
  ]
@@ -8,3 +8,4 @@ STATIONS_LIST_URL = "/xema/v1/estacions/metadades"
8
8
  STATIONS_MUNICIPI_URL = "/xema/v1/representatives/metadades/municipis/{codi_municipi}/variables/{codi_variable}"
9
9
  VARIABLES_URL = "/xema/v1/variables/mesurades/metadades"
10
10
  STATION_DATA_URL = "/xema/v1/estacions/mesurades/{codiEstacio}/{any}/{mes}/{dia}"
11
+ UVI_DATA_URL = "/pronostic/v1/uvi/{codi_municipi}"
@@ -1,5 +1,6 @@
1
1
  import aiohttp
2
2
  import logging
3
+ import re
3
4
  from datetime import datetime
4
5
  from .variables import MeteocatVariables
5
6
  from .const import BASE_URL, STATION_DATA_URL
@@ -64,6 +65,23 @@ class MeteocatStationData:
64
65
 
65
66
  # Gestionar errores según el código de estado
66
67
  if response.status == 400:
68
+ error_data = await response.json()
69
+ # Intentar extraer la última fecha válida del mensaje de error
70
+ if "message" in error_data:
71
+ match = re.search(r'entre (\d{2}-\d{2}-\d{4}) i', error_data["message"])
72
+ if match:
73
+ last_valid_date = match.group(1) # Captura la última fecha válida
74
+ dia, mes, any = map(int, last_valid_date.split('-'))
75
+ # Intentar nuevamente con la última fecha válida
76
+ new_url = f"{BASE_URL}{STATION_DATA_URL}".format(
77
+ codiEstacio=station_id, any=any, mes=f"{mes:02d}", dia=f"{dia:02d}"
78
+ )
79
+ async with session.get(new_url, headers=self.headers) as new_response:
80
+ if new_response.status == 200:
81
+ return await new_response.json()
82
+ raise UnknownAPIError(
83
+ f"Failed with the valid date {last_valid_date}: {await new_response.text()}"
84
+ )
67
85
  raise BadRequestError(await response.json())
68
86
  elif response.status == 403:
69
87
  error_data = await response.json()
@@ -0,0 +1,84 @@
1
+ import aiohttp
2
+ import logging
3
+ from .const import (
4
+ BASE_URL,
5
+ UVI_DATA_URL
6
+ )
7
+ from .exceptions import (
8
+ BadRequestError,
9
+ ForbiddenError,
10
+ TooManyRequestsError,
11
+ InternalServerError,
12
+ UnknownAPIError,
13
+ )
14
+
15
+ _LOGGER = logging.getLogger(__name__)
16
+
17
+ class MeteocatUviData:
18
+ """Clase para interactuar con los datos del índice UVI de la API de Meteocat."""
19
+
20
+ def __init__(self, api_key: str):
21
+ """
22
+ Inicializa la clase MeteocatUviData.
23
+
24
+ Args:
25
+ api_key (str): Clave de API para autenticar las solicitudes.
26
+ """
27
+ self.api_key = api_key
28
+ self.headers = {
29
+ "Content-Type": "application/json",
30
+ "X-Api-Key": self.api_key,
31
+ }
32
+
33
+ async def get_uvi_index(self, town_id: str):
34
+ """
35
+ Obtiene los datos del índice UVI para un municipio.
36
+
37
+ Args:
38
+ town_id (str): Código del municipio.
39
+
40
+ Returns:
41
+ dict: Datos del índice UVI del municipio.
42
+ """
43
+ if not town_id:
44
+ raise ValueError("El parámetro 'town_id' no puede estar vacío.")
45
+
46
+ url = f"{BASE_URL}{UVI_DATA_URL}".format(
47
+ codi_municipi=town_id
48
+ )
49
+
50
+ async with aiohttp.ClientSession() as session:
51
+ try:
52
+ async with session.get(url, headers=self.headers) as response:
53
+ if response.status == 200:
54
+ return await response.json()
55
+
56
+ # Gestionar errores según el código de estado
57
+ if response.status == 400:
58
+ raise BadRequestError(await response.json())
59
+ elif response.status == 403:
60
+ error_data = await response.json()
61
+ if error_data.get("message") == "Forbidden":
62
+ raise ForbiddenError(error_data)
63
+ elif error_data.get("message") == "Missing Authentication Token":
64
+ raise ForbiddenError(error_data)
65
+ elif response.status == 429:
66
+ raise TooManyRequestsError(await response.json())
67
+ elif response.status == 500:
68
+ raise InternalServerError(await response.json())
69
+ else:
70
+ raise UnknownAPIError(
71
+ f"Unexpected error {response.status}: {await response.text()}"
72
+ )
73
+
74
+ except aiohttp.ClientError as e:
75
+ raise UnknownAPIError(
76
+ message=f"Error al conectar con la API de Meteocat: {str(e)}",
77
+ status_code=0,
78
+ )
79
+
80
+ except Exception as ex:
81
+ raise UnknownAPIError(
82
+ message=f"Error inesperado: {str(ex)}",
83
+ status_code=0,
84
+ )
@@ -1,2 +1,2 @@
1
1
  # version.py
2
- __version__ = "0.0.14"
2
+ __version__ = "0.0.16"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meteocatpy",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\r [![Python version compatibility](https://img.shields.io/pypi/pyversions/meteocatpy)](https://pypi.org/project/meteocatpy)\r [![pipeline status](https://gitlab.com/figorr/meteocatpy/badges/master/pipeline.svg)](https://gitlab.com/figorr/meteocatpy/commits/master)",
5
5
  "main": "index.js",
6
6
  "directories": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "meteocatpy"
3
- version = "0.0.14"
3
+ version = "0.0.16"
4
4
  description = "Script para obtener datos meteorológicos de la API de Meteocat"
5
5
  authors = ["figorr <jdcuartero@yahoo.es>"]
6
6
  license = "Apache-2.0"
@@ -0,0 +1,34 @@
1
+ import os
2
+ import pytest
3
+ import json
4
+ from dotenv import load_dotenv
5
+ from meteocatpy.uvi import MeteocatUviData
6
+
7
+ # Cargar variables desde el archivo .env
8
+ load_dotenv()
9
+
10
+ # Obtener los valores del archivo .env
11
+ API_KEY = os.getenv("METEOCAT_API_KEY_TEST")
12
+ MUNICIPI_CODI_TEST = os.getenv("MUNICIPI_CODI_TEST")
13
+
14
+ # Asegúrate de que las variables estén definidas
15
+ assert API_KEY, "API Key is required"
16
+ assert MUNICIPI_CODI_TEST, "Station codi test is required"
17
+
18
+ @pytest.mark.asyncio
19
+ async def test_municipis():
20
+ # Crear una instancia de MeteocatUviData con la API Key
21
+ uvi_client = MeteocatUviData(API_KEY)
22
+
23
+ # Obtener los datos del índice UVI
24
+ uvi_data = await uvi_client.get_uvi_index(MUNICIPI_CODI_TEST)
25
+
26
+ # Crear la carpeta si no existe
27
+ os.makedirs('tests/files', exist_ok=True)
28
+
29
+ # Guardar los datos del índice UVI en un archivo JSON
30
+ with open(f'tests/files/uvi_{MUNICIPI_CODI_TEST}_data.json', 'w', encoding='utf-8') as f:
31
+ json.dump(uvi_data, f, ensure_ascii=False, indent=4)
32
+
33
+ # Verificar que los datos del índice UVI no estén vacíos
34
+ assert uvi_data, "UVI data is empty"