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.
- package/.github/workflows/release.yml +33 -33
- package/.gitlab-ci.yml +46 -46
- package/.pre-commit-config.yaml +37 -37
- package/.releaserc +23 -23
- package/.releaserc.toml +14 -14
- package/AUTHORS.md +12 -12
- package/CHANGELOG.md +187 -171
- package/README.md +61 -61
- package/filetree.py +48 -48
- package/filetree.txt +48 -48
- package/meteocatpy/README.md +61 -61
- package/meteocatpy/__init__.py +27 -27
- package/meteocatpy/const.py +10 -10
- package/meteocatpy/data.py +93 -93
- package/meteocatpy/exceptions.py +35 -35
- package/meteocatpy/forecast.py +137 -137
- package/meteocatpy/helpers.py +46 -46
- package/meteocatpy/stations.py +71 -71
- package/meteocatpy/symbols.py +89 -89
- package/meteocatpy/town.py +61 -61
- package/meteocatpy/townstations.py +99 -99
- package/meteocatpy/variables.py +77 -77
- package/meteocatpy/version.py +2 -2
- package/package.json +23 -23
- package/poetry.lock +3313 -3313
- package/pyproject.toml +72 -72
- package/releaserc.json +17 -17
- package/requirements.test.txt +3 -3
- package/setup.cfg +64 -64
- package/setup.py +10 -10
- package/tests/data_test.py +122 -122
- package/tests/import_test.py +18 -18
- package/tests/integration_test_complete.py +76 -76
- package/tests/integration_test_forecast.py +54 -54
- package/tests/integration_test_station_data.py +33 -33
- package/tests/integration_test_stations.py +31 -31
- package/tests/integration_test_symbols.py +68 -68
- package/tests/integration_test_town.py +32 -32
- package/tests/integration_test_town_stations.py +36 -36
- package/tests/integration_test_variables.py +32 -32
package/pyproject.toml
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "meteocatpy"
|
|
3
|
-
version = "0.0.
|
|
4
|
-
description = "Script para obtener datos meteorológicos de la API de Meteocat"
|
|
5
|
-
authors = ["figorr <jdcuartero@yahoo.es>"]
|
|
6
|
-
license = "Apache-2.0"
|
|
7
|
-
readme = "README.md"
|
|
8
|
-
repository = "https://gitlab.com/figorr/meteocatpy"
|
|
9
|
-
keywords = ['meteocatpy', 'meteocat']
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
[tool.poetry.dependencies]
|
|
13
|
-
python = ">=3.12,<3.14"
|
|
14
|
-
requests = "^2.32.3"
|
|
15
|
-
python-dotenv = "^1.0.1"
|
|
16
|
-
simplejson = "^3.19.3"
|
|
17
|
-
setuptools = "^75.5.0"
|
|
18
|
-
python-semantic-release = "^7.28.1"
|
|
19
|
-
twine = ">=3,<4"
|
|
20
|
-
aiofiles = "^24.1.0"
|
|
21
|
-
voluptuous = "^0.15.2"
|
|
22
|
-
geopy = "^2.4.1"
|
|
23
|
-
tzdata = "^2024.2"
|
|
24
|
-
aiohttp = ">=3.10.11,<4.0.0"
|
|
25
|
-
diskcache = "^5.6.3"
|
|
26
|
-
semantic-release = "^0.1.0"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
[tool.semantic_release]
|
|
30
|
-
branch = "master" # Define la rama desde la que se harán los lanzamientos
|
|
31
|
-
version_source = "commit" # Determina la versión basada en los commits
|
|
32
|
-
version_variable = "meteocatpy/version.py:__version__" # Ubicación de la variable de versión
|
|
33
|
-
changelog = { file = "CHANGELOG.md" } # Genera el changelog en el archivo especificado
|
|
34
|
-
upload_to_pypi = false # Sube automáticamente la versión a PyPI
|
|
35
|
-
ci = false # Cambiar a false si no usas CI/CD
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
[build-system]
|
|
39
|
-
requires = ["poetry-core"]
|
|
40
|
-
build-backend = "poetry.core.masonry.api"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
[tool.poetry.dev-dependencies]
|
|
44
|
-
aresponses = "*"
|
|
45
|
-
detox = "*"
|
|
46
|
-
flake8 = "*"
|
|
47
|
-
mypy = "*"
|
|
48
|
-
pydocstyle = "*"
|
|
49
|
-
pylint = "*"
|
|
50
|
-
pytest-aiohttp = "*"
|
|
51
|
-
pytest-cov = "*"
|
|
52
|
-
python-semantic-release = "^7.28.1"
|
|
53
|
-
tox = "*"
|
|
54
|
-
safety = ">=1.8.7"
|
|
55
|
-
black = { version = ">19.10b0", allow-prereleases = true }
|
|
56
|
-
Sphinx = ">=3.5.0,<7.0.0"
|
|
57
|
-
autoapi = ">=2.0.1"
|
|
58
|
-
sphinx-rtd-theme = "^0.5.1"
|
|
59
|
-
m2r2 = ">=0.2.7"
|
|
60
|
-
tomlkit = ">=0.7.0"
|
|
61
|
-
sphinx-autoapi = ">=1.7.0"
|
|
62
|
-
sphinx-copybutton = ">=0.3.1"
|
|
63
|
-
pipdeptree = "^2.2.1"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
[tool.poetry.group.dev.dependencies]
|
|
67
|
-
pyupgrade = "^3.4.0"
|
|
68
|
-
pre-commit = "^3.3.1"
|
|
69
|
-
pytest = "^8.3.3"
|
|
70
|
-
pytest-asyncio = "^0.24.0"
|
|
71
|
-
syrupy = "^4.7.2"
|
|
72
|
-
aioresponses = "^0.7.7"
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "meteocatpy"
|
|
3
|
+
version = "0.0.13"
|
|
4
|
+
description = "Script para obtener datos meteorológicos de la API de Meteocat"
|
|
5
|
+
authors = ["figorr <jdcuartero@yahoo.es>"]
|
|
6
|
+
license = "Apache-2.0"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
repository = "https://gitlab.com/figorr/meteocatpy"
|
|
9
|
+
keywords = ['meteocatpy', 'meteocat']
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
[tool.poetry.dependencies]
|
|
13
|
+
python = ">=3.12,<3.14"
|
|
14
|
+
requests = "^2.32.3"
|
|
15
|
+
python-dotenv = "^1.0.1"
|
|
16
|
+
simplejson = "^3.19.3"
|
|
17
|
+
setuptools = "^75.5.0"
|
|
18
|
+
python-semantic-release = "^7.28.1"
|
|
19
|
+
twine = ">=3,<4"
|
|
20
|
+
aiofiles = "^24.1.0"
|
|
21
|
+
voluptuous = "^0.15.2"
|
|
22
|
+
geopy = "^2.4.1"
|
|
23
|
+
tzdata = "^2024.2"
|
|
24
|
+
aiohttp = ">=3.10.11,<4.0.0"
|
|
25
|
+
diskcache = "^5.6.3"
|
|
26
|
+
semantic-release = "^0.1.0"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
[tool.semantic_release]
|
|
30
|
+
branch = "master" # Define la rama desde la que se harán los lanzamientos
|
|
31
|
+
version_source = "commit" # Determina la versión basada en los commits
|
|
32
|
+
version_variable = "meteocatpy/version.py:__version__" # Ubicación de la variable de versión
|
|
33
|
+
changelog = { file = "CHANGELOG.md" } # Genera el changelog en el archivo especificado
|
|
34
|
+
upload_to_pypi = false # Sube automáticamente la versión a PyPI
|
|
35
|
+
ci = false # Cambiar a false si no usas CI/CD
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["poetry-core"]
|
|
40
|
+
build-backend = "poetry.core.masonry.api"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
[tool.poetry.dev-dependencies]
|
|
44
|
+
aresponses = "*"
|
|
45
|
+
detox = "*"
|
|
46
|
+
flake8 = "*"
|
|
47
|
+
mypy = "*"
|
|
48
|
+
pydocstyle = "*"
|
|
49
|
+
pylint = "*"
|
|
50
|
+
pytest-aiohttp = "*"
|
|
51
|
+
pytest-cov = "*"
|
|
52
|
+
python-semantic-release = "^7.28.1"
|
|
53
|
+
tox = "*"
|
|
54
|
+
safety = ">=1.8.7"
|
|
55
|
+
black = { version = ">19.10b0", allow-prereleases = true }
|
|
56
|
+
Sphinx = ">=3.5.0,<7.0.0"
|
|
57
|
+
autoapi = ">=2.0.1"
|
|
58
|
+
sphinx-rtd-theme = "^0.5.1"
|
|
59
|
+
m2r2 = ">=0.2.7"
|
|
60
|
+
tomlkit = ">=0.7.0"
|
|
61
|
+
sphinx-autoapi = ">=1.7.0"
|
|
62
|
+
sphinx-copybutton = ">=0.3.1"
|
|
63
|
+
pipdeptree = "^2.2.1"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
[tool.poetry.group.dev.dependencies]
|
|
67
|
+
pyupgrade = "^3.4.0"
|
|
68
|
+
pre-commit = "^3.3.1"
|
|
69
|
+
pytest = "^8.3.3"
|
|
70
|
+
pytest-asyncio = "^0.24.0"
|
|
71
|
+
syrupy = "^4.7.2"
|
|
72
|
+
aioresponses = "^0.7.7"
|
package/releaserc.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
"branches": ["master"],
|
|
3
|
-
"plugins": [
|
|
4
|
-
"@semantic-release/commit-analyzer",
|
|
5
|
-
"@semantic-release/release-notes-generator",
|
|
6
|
-
"@semantic-release/changelog",
|
|
7
|
-
[
|
|
8
|
-
"@semantic-release/exec",
|
|
9
|
-
{
|
|
10
|
-
"prepareCmd": "python setup.py sdist bdist_wheel",
|
|
11
|
-
"publishCmd": "twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD}"
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"@semantic-release/github",
|
|
15
|
-
"@semantic-release/git"
|
|
16
|
-
]
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"branches": ["master"],
|
|
3
|
+
"plugins": [
|
|
4
|
+
"@semantic-release/commit-analyzer",
|
|
5
|
+
"@semantic-release/release-notes-generator",
|
|
6
|
+
"@semantic-release/changelog",
|
|
7
|
+
[
|
|
8
|
+
"@semantic-release/exec",
|
|
9
|
+
{
|
|
10
|
+
"prepareCmd": "python setup.py sdist bdist_wheel",
|
|
11
|
+
"publishCmd": "twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD}"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"@semantic-release/github",
|
|
15
|
+
"@semantic-release/git"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
18
|
|
package/requirements.test.txt
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
pytest
|
|
2
|
-
pytest-cov
|
|
3
|
-
pytest-homeassistant-custom-component
|
|
1
|
+
pytest
|
|
2
|
+
pytest-cov
|
|
3
|
+
pytest-homeassistant-custom-component
|
package/setup.cfg
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
[coverage:run]
|
|
2
|
-
source =
|
|
3
|
-
meteocatpy
|
|
4
|
-
|
|
5
|
-
[coverage:report]
|
|
6
|
-
exclude_lines =
|
|
7
|
-
pragma: no cover
|
|
8
|
-
raise NotImplemented()
|
|
9
|
-
if __name__ == '__main__':
|
|
10
|
-
main()
|
|
11
|
-
show_missing = true
|
|
12
|
-
|
|
13
|
-
[tool:pytest]
|
|
14
|
-
testpaths = tests
|
|
15
|
-
norecursedirs = .git
|
|
16
|
-
asyncio_mode = auto
|
|
17
|
-
addopts =
|
|
18
|
-
-p syrupy
|
|
19
|
-
--strict
|
|
20
|
-
--cov=meteocatpy
|
|
21
|
-
|
|
22
|
-
[flake8]
|
|
23
|
-
# https://github.com/ambv/black#line-length
|
|
24
|
-
max-line-length = 88
|
|
25
|
-
# E501: line too long
|
|
26
|
-
# W503: Line break occurred before a binary operator
|
|
27
|
-
# E203: Whitespace before ':'
|
|
28
|
-
# D202 No blank lines allowed after function docstring
|
|
29
|
-
# W504 line break after binary operator
|
|
30
|
-
ignore =
|
|
31
|
-
E501,
|
|
32
|
-
W503,
|
|
33
|
-
E203,
|
|
34
|
-
D202,
|
|
35
|
-
W504
|
|
36
|
-
|
|
37
|
-
[isort]
|
|
38
|
-
# https://github.com/timothycrosley/isort
|
|
39
|
-
# https://github.com/timothycrosley/isort/wiki/isort-Settings
|
|
40
|
-
# splits long import on multiple lines indented by 4 spaces
|
|
41
|
-
multi_line_output = 3
|
|
42
|
-
include_trailing_comma=True
|
|
43
|
-
force_grid_wrap=0
|
|
44
|
-
use_parentheses=True
|
|
45
|
-
line_length=88
|
|
46
|
-
indent = " "
|
|
47
|
-
# by default isort don't check module indexes
|
|
48
|
-
not_skip = __init__.py
|
|
49
|
-
# will group `import x` and `from x import` of the same module.
|
|
50
|
-
force_sort_within_sections = true
|
|
51
|
-
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
|
|
52
|
-
default_section = THIRDPARTY
|
|
53
|
-
known_first_party = custom_components,tests
|
|
54
|
-
forced_separate = tests
|
|
55
|
-
combine_as_imports = true
|
|
56
|
-
|
|
57
|
-
[mypy]
|
|
58
|
-
python_version = 3.7
|
|
59
|
-
ignore_errors = true
|
|
60
|
-
follow_imports = silent
|
|
61
|
-
ignore_missing_imports = true
|
|
62
|
-
warn_incomplete_stub = true
|
|
63
|
-
warn_redundant_casts = true
|
|
64
|
-
warn_unused_configs = true
|
|
1
|
+
[coverage:run]
|
|
2
|
+
source =
|
|
3
|
+
meteocatpy
|
|
4
|
+
|
|
5
|
+
[coverage:report]
|
|
6
|
+
exclude_lines =
|
|
7
|
+
pragma: no cover
|
|
8
|
+
raise NotImplemented()
|
|
9
|
+
if __name__ == '__main__':
|
|
10
|
+
main()
|
|
11
|
+
show_missing = true
|
|
12
|
+
|
|
13
|
+
[tool:pytest]
|
|
14
|
+
testpaths = tests
|
|
15
|
+
norecursedirs = .git
|
|
16
|
+
asyncio_mode = auto
|
|
17
|
+
addopts =
|
|
18
|
+
-p syrupy
|
|
19
|
+
--strict
|
|
20
|
+
--cov=meteocatpy
|
|
21
|
+
|
|
22
|
+
[flake8]
|
|
23
|
+
# https://github.com/ambv/black#line-length
|
|
24
|
+
max-line-length = 88
|
|
25
|
+
# E501: line too long
|
|
26
|
+
# W503: Line break occurred before a binary operator
|
|
27
|
+
# E203: Whitespace before ':'
|
|
28
|
+
# D202 No blank lines allowed after function docstring
|
|
29
|
+
# W504 line break after binary operator
|
|
30
|
+
ignore =
|
|
31
|
+
E501,
|
|
32
|
+
W503,
|
|
33
|
+
E203,
|
|
34
|
+
D202,
|
|
35
|
+
W504
|
|
36
|
+
|
|
37
|
+
[isort]
|
|
38
|
+
# https://github.com/timothycrosley/isort
|
|
39
|
+
# https://github.com/timothycrosley/isort/wiki/isort-Settings
|
|
40
|
+
# splits long import on multiple lines indented by 4 spaces
|
|
41
|
+
multi_line_output = 3
|
|
42
|
+
include_trailing_comma=True
|
|
43
|
+
force_grid_wrap=0
|
|
44
|
+
use_parentheses=True
|
|
45
|
+
line_length=88
|
|
46
|
+
indent = " "
|
|
47
|
+
# by default isort don't check module indexes
|
|
48
|
+
not_skip = __init__.py
|
|
49
|
+
# will group `import x` and `from x import` of the same module.
|
|
50
|
+
force_sort_within_sections = true
|
|
51
|
+
sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
|
|
52
|
+
default_section = THIRDPARTY
|
|
53
|
+
known_first_party = custom_components,tests
|
|
54
|
+
forced_separate = tests
|
|
55
|
+
combine_as_imports = true
|
|
56
|
+
|
|
57
|
+
[mypy]
|
|
58
|
+
python_version = 3.7
|
|
59
|
+
ignore_errors = true
|
|
60
|
+
follow_imports = silent
|
|
61
|
+
ignore_missing_imports = true
|
|
62
|
+
warn_incomplete_stub = true
|
|
63
|
+
warn_redundant_casts = true
|
|
64
|
+
warn_unused_configs = true
|
package/setup.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
from setuptools import setup
|
|
2
|
-
|
|
3
|
-
# Leer la versión desde el archivo version.py
|
|
4
|
-
with open("meteocatpy/version.py") as f:
|
|
5
|
-
exec(f.read()) # Ejecuta el archivo version.py para cargar la variable __version__
|
|
6
|
-
|
|
7
|
-
setup(
|
|
8
|
-
name="meteocatpy",
|
|
9
|
-
version=__version__, # Usa la versión cargada dinámicamente # type: ignore
|
|
10
|
-
)
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
# Leer la versión desde el archivo version.py
|
|
4
|
+
with open("meteocatpy/version.py") as f:
|
|
5
|
+
exec(f.read()) # Ejecuta el archivo version.py para cargar la variable __version__
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name="meteocatpy",
|
|
9
|
+
version=__version__, # Usa la versión cargada dinámicamente # type: ignore
|
|
10
|
+
)
|
package/tests/data_test.py
CHANGED
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pytest
|
|
3
|
-
from aioresponses import aioresponses
|
|
4
|
-
from meteocatpy.data import MeteocatStationData
|
|
5
|
-
from meteocatpy.exceptions import (
|
|
6
|
-
BadRequestError,
|
|
7
|
-
ForbiddenError,
|
|
8
|
-
TooManyRequestsError,
|
|
9
|
-
InternalServerError,
|
|
10
|
-
UnknownAPIError,
|
|
11
|
-
)
|
|
12
|
-
from meteocatpy.const import BASE_URL, STATION_DATA_URL
|
|
13
|
-
from dotenv import load_dotenv
|
|
14
|
-
|
|
15
|
-
# Cargar variables desde el archivo .env
|
|
16
|
-
load_dotenv()
|
|
17
|
-
|
|
18
|
-
# Obtener los valores del archivo .env
|
|
19
|
-
API_KEY = os.getenv("METEOCAT_API_KEY")
|
|
20
|
-
STATION_CODI_TEST = os.getenv("STATION_CODI_TEST")
|
|
21
|
-
|
|
22
|
-
# Asegúrate de que las variables estén definidas
|
|
23
|
-
assert API_KEY, "API Key is required"
|
|
24
|
-
assert STATION_CODI_TEST, "Station codi test is required"
|
|
25
|
-
|
|
26
|
-
@pytest.mark.asyncio
|
|
27
|
-
async def test_get_station_data():
|
|
28
|
-
# Simular la respuesta de la API
|
|
29
|
-
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
30
|
-
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
31
|
-
)
|
|
32
|
-
mock_response = {
|
|
33
|
-
"lectures": [
|
|
34
|
-
{"codi_variable": 32, "data": "2024-12-04T12:00:00Z", "valor": 15.2},
|
|
35
|
-
{"codi_variable": 33, "data": "2024-12-04T12:00:00Z", "valor": 80},
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
with aioresponses() as mock:
|
|
40
|
-
mock.get(test_url, payload=mock_response)
|
|
41
|
-
|
|
42
|
-
station_data = MeteocatStationData(API_KEY)
|
|
43
|
-
result = await station_data.get_station_data(STATION_CODI_TEST)
|
|
44
|
-
|
|
45
|
-
assert result == mock_response
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@pytest.mark.asyncio
|
|
49
|
-
async def test_get_station_data_with_variables(mocker):
|
|
50
|
-
# Simular la respuesta de la API y las variables
|
|
51
|
-
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
52
|
-
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
53
|
-
)
|
|
54
|
-
mock_station_response = {
|
|
55
|
-
"lectures": [
|
|
56
|
-
{"codi_variable": 32, "data": "2024-12-04T12:00:00Z", "valor": 15.2},
|
|
57
|
-
{"codi_variable": 33, "data": "2024-12-04T12:00:00Z", "valor": 80},
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
mock_variables_response = [
|
|
61
|
-
{"codi": 32, "nom": "Temperatura"},
|
|
62
|
-
{"codi": 33, "nom": "Humedad relativa"},
|
|
63
|
-
]
|
|
64
|
-
|
|
65
|
-
# Mockear la llamada a la API y las variables
|
|
66
|
-
with aioresponses() as mock:
|
|
67
|
-
mock.get(test_url, payload=mock_station_response)
|
|
68
|
-
mocker.patch(
|
|
69
|
-
"meteocatpy.data.MeteocatVariables.get_variables",
|
|
70
|
-
return_value=mock_variables_response,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
station_data = MeteocatStationData(API_KEY)
|
|
74
|
-
result = await station_data.get_station_data_with_variables(STATION_CODI_TEST)
|
|
75
|
-
|
|
76
|
-
# Validar los datos organizados por variables
|
|
77
|
-
expected_result = {
|
|
78
|
-
"Temperatura": [
|
|
79
|
-
{
|
|
80
|
-
"data": "2024-12-04T12:00:00Z",
|
|
81
|
-
"valor": 15.2,
|
|
82
|
-
"estat": "",
|
|
83
|
-
"base_horaria": "",
|
|
84
|
-
}
|
|
85
|
-
],
|
|
86
|
-
"Humedad relativa": [
|
|
87
|
-
{
|
|
88
|
-
"data": "2024-12-04T12:00:00Z",
|
|
89
|
-
"valor": 80,
|
|
90
|
-
"estat": "",
|
|
91
|
-
"base_horaria": "",
|
|
92
|
-
}
|
|
93
|
-
],
|
|
94
|
-
}
|
|
95
|
-
assert result == expected_result
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@pytest.mark.asyncio
|
|
99
|
-
async def test_get_station_data_errors():
|
|
100
|
-
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
101
|
-
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
# Simular errores de la API
|
|
105
|
-
with aioresponses() as mock:
|
|
106
|
-
mock.get(test_url, status=400, payload={"message": "Bad Request"})
|
|
107
|
-
station_data = MeteocatStationData(API_KEY)
|
|
108
|
-
|
|
109
|
-
with pytest.raises(BadRequestError):
|
|
110
|
-
await station_data.get_station_data(STATION_CODI_TEST)
|
|
111
|
-
|
|
112
|
-
mock.get(test_url, status=403, payload={"message": "Forbidden"})
|
|
113
|
-
with pytest.raises(ForbiddenError):
|
|
114
|
-
await station_data.get_station_data(STATION_CODI_TEST)
|
|
115
|
-
|
|
116
|
-
mock.get(test_url, status=429, payload={"message": "Too Many Requests"})
|
|
117
|
-
with pytest.raises(TooManyRequestsError):
|
|
118
|
-
await station_data.get_station_data(STATION_CODI_TEST)
|
|
119
|
-
|
|
120
|
-
mock.get(test_url, status=500, payload={"message": "Internal Server Error"})
|
|
121
|
-
with pytest.raises(InternalServerError):
|
|
122
|
-
await station_data.get_station_data(STATION_CODI_TEST)
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
from aioresponses import aioresponses
|
|
4
|
+
from meteocatpy.data import MeteocatStationData
|
|
5
|
+
from meteocatpy.exceptions import (
|
|
6
|
+
BadRequestError,
|
|
7
|
+
ForbiddenError,
|
|
8
|
+
TooManyRequestsError,
|
|
9
|
+
InternalServerError,
|
|
10
|
+
UnknownAPIError,
|
|
11
|
+
)
|
|
12
|
+
from meteocatpy.const import BASE_URL, STATION_DATA_URL
|
|
13
|
+
from dotenv import load_dotenv
|
|
14
|
+
|
|
15
|
+
# Cargar variables desde el archivo .env
|
|
16
|
+
load_dotenv()
|
|
17
|
+
|
|
18
|
+
# Obtener los valores del archivo .env
|
|
19
|
+
API_KEY = os.getenv("METEOCAT_API_KEY")
|
|
20
|
+
STATION_CODI_TEST = os.getenv("STATION_CODI_TEST")
|
|
21
|
+
|
|
22
|
+
# Asegúrate de que las variables estén definidas
|
|
23
|
+
assert API_KEY, "API Key is required"
|
|
24
|
+
assert STATION_CODI_TEST, "Station codi test is required"
|
|
25
|
+
|
|
26
|
+
@pytest.mark.asyncio
|
|
27
|
+
async def test_get_station_data():
|
|
28
|
+
# Simular la respuesta de la API
|
|
29
|
+
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
30
|
+
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
31
|
+
)
|
|
32
|
+
mock_response = {
|
|
33
|
+
"lectures": [
|
|
34
|
+
{"codi_variable": 32, "data": "2024-12-04T12:00:00Z", "valor": 15.2},
|
|
35
|
+
{"codi_variable": 33, "data": "2024-12-04T12:00:00Z", "valor": 80},
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
with aioresponses() as mock:
|
|
40
|
+
mock.get(test_url, payload=mock_response)
|
|
41
|
+
|
|
42
|
+
station_data = MeteocatStationData(API_KEY)
|
|
43
|
+
result = await station_data.get_station_data(STATION_CODI_TEST)
|
|
44
|
+
|
|
45
|
+
assert result == mock_response
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@pytest.mark.asyncio
|
|
49
|
+
async def test_get_station_data_with_variables(mocker):
|
|
50
|
+
# Simular la respuesta de la API y las variables
|
|
51
|
+
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
52
|
+
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
53
|
+
)
|
|
54
|
+
mock_station_response = {
|
|
55
|
+
"lectures": [
|
|
56
|
+
{"codi_variable": 32, "data": "2024-12-04T12:00:00Z", "valor": 15.2},
|
|
57
|
+
{"codi_variable": 33, "data": "2024-12-04T12:00:00Z", "valor": 80},
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
mock_variables_response = [
|
|
61
|
+
{"codi": 32, "nom": "Temperatura"},
|
|
62
|
+
{"codi": 33, "nom": "Humedad relativa"},
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
# Mockear la llamada a la API y las variables
|
|
66
|
+
with aioresponses() as mock:
|
|
67
|
+
mock.get(test_url, payload=mock_station_response)
|
|
68
|
+
mocker.patch(
|
|
69
|
+
"meteocatpy.data.MeteocatVariables.get_variables",
|
|
70
|
+
return_value=mock_variables_response,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
station_data = MeteocatStationData(API_KEY)
|
|
74
|
+
result = await station_data.get_station_data_with_variables(STATION_CODI_TEST)
|
|
75
|
+
|
|
76
|
+
# Validar los datos organizados por variables
|
|
77
|
+
expected_result = {
|
|
78
|
+
"Temperatura": [
|
|
79
|
+
{
|
|
80
|
+
"data": "2024-12-04T12:00:00Z",
|
|
81
|
+
"valor": 15.2,
|
|
82
|
+
"estat": "",
|
|
83
|
+
"base_horaria": "",
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"Humedad relativa": [
|
|
87
|
+
{
|
|
88
|
+
"data": "2024-12-04T12:00:00Z",
|
|
89
|
+
"valor": 80,
|
|
90
|
+
"estat": "",
|
|
91
|
+
"base_horaria": "",
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
}
|
|
95
|
+
assert result == expected_result
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@pytest.mark.asyncio
|
|
99
|
+
async def test_get_station_data_errors():
|
|
100
|
+
test_url = f"{BASE_URL}{STATION_DATA_URL}".format(
|
|
101
|
+
codiEstacio=STATION_CODI_TEST, any=2024, mes="12", dia="04"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Simular errores de la API
|
|
105
|
+
with aioresponses() as mock:
|
|
106
|
+
mock.get(test_url, status=400, payload={"message": "Bad Request"})
|
|
107
|
+
station_data = MeteocatStationData(API_KEY)
|
|
108
|
+
|
|
109
|
+
with pytest.raises(BadRequestError):
|
|
110
|
+
await station_data.get_station_data(STATION_CODI_TEST)
|
|
111
|
+
|
|
112
|
+
mock.get(test_url, status=403, payload={"message": "Forbidden"})
|
|
113
|
+
with pytest.raises(ForbiddenError):
|
|
114
|
+
await station_data.get_station_data(STATION_CODI_TEST)
|
|
115
|
+
|
|
116
|
+
mock.get(test_url, status=429, payload={"message": "Too Many Requests"})
|
|
117
|
+
with pytest.raises(TooManyRequestsError):
|
|
118
|
+
await station_data.get_station_data(STATION_CODI_TEST)
|
|
119
|
+
|
|
120
|
+
mock.get(test_url, status=500, payload={"message": "Internal Server Error"})
|
|
121
|
+
with pytest.raises(InternalServerError):
|
|
122
|
+
await station_data.get_station_data(STATION_CODI_TEST)
|
package/tests/import_test.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
def test_imports():
|
|
2
|
-
from meteocatpy import (
|
|
3
|
-
MeteocatTown,
|
|
4
|
-
MeteocatForecast,
|
|
5
|
-
MeteocatSymbols,
|
|
6
|
-
MeteocatStations,
|
|
7
|
-
MeteocatTownStations,
|
|
8
|
-
MeteocatStationData,
|
|
9
|
-
MeteocatVariables,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
assert MeteocatTown is not None
|
|
13
|
-
assert MeteocatForecast is not None
|
|
14
|
-
assert MeteocatSymbols is not None
|
|
15
|
-
assert MeteocatStations is not None
|
|
16
|
-
assert MeteocatTownStations is not None
|
|
17
|
-
assert MeteocatStationData is not None
|
|
18
|
-
assert MeteocatVariables is not None
|
|
1
|
+
def test_imports():
|
|
2
|
+
from meteocatpy import (
|
|
3
|
+
MeteocatTown,
|
|
4
|
+
MeteocatForecast,
|
|
5
|
+
MeteocatSymbols,
|
|
6
|
+
MeteocatStations,
|
|
7
|
+
MeteocatTownStations,
|
|
8
|
+
MeteocatStationData,
|
|
9
|
+
MeteocatVariables,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
assert MeteocatTown is not None
|
|
13
|
+
assert MeteocatForecast is not None
|
|
14
|
+
assert MeteocatSymbols is not None
|
|
15
|
+
assert MeteocatStations is not None
|
|
16
|
+
assert MeteocatTownStations is not None
|
|
17
|
+
assert MeteocatStationData is not None
|
|
18
|
+
assert MeteocatVariables is not None
|