Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 502 error on warning API #680

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/meteofrance_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,19 +232,18 @@ def get_warning_current_phenomenoms(
# Send the API request
resp = self.session.request(
"get",
"warning/currentphenomenons",
"v3/warning/currentphenomenons",
params={"domain": domain, "depth": depth},
)

# Create object with API response
phenomenoms = CurrentPhenomenons(resp.json())

# if user ask to have the coastal bulletin merged
if with_costal_bulletin:
if domain in COASTAL_DEPARTMENT_LIST:
resp = self.session.request(
"get",
"warning/currentphenomenons",
"v3/warning/currentphenomenons",
params={"domain": domain + "10"},
)
phenomenoms.merge_with_coastal_phenomenons(
Expand Down Expand Up @@ -273,7 +272,9 @@ def get_warning_full(self, domain: str, with_costal_bulletin: bool = False) -> F
# TODO: add formatDate parameter

# Send the API request
resp = self.session.request("get", "warning/full", params={"domain": domain})
resp = self.session.request(
"get", "/v3/warning/full", params={"domain": domain}
)

# Create object with API response
full_phenomenoms = Full(resp.json())
Expand All @@ -283,7 +284,7 @@ def get_warning_full(self, domain: str, with_costal_bulletin: bool = False) -> F
if domain in COASTAL_DEPARTMENT_LIST:
resp = self.session.request(
"get",
"warning/full",
"v3/warning/full",
params={"domain": domain + "10"},
)
full_phenomenoms.merge_with_coastal_phenomenons(Full(resp.json()))
Expand All @@ -302,7 +303,7 @@ def get_warning_thumbnail(self, domain: str = "france") -> str:
"""
# Return directly the URL of the gif image
return (
f"{METEOFRANCE_API_URL}/warning/thumbnail?&token={METEOFRANCE_API_TOKEN}"
f"{METEOFRANCE_API_URL}/v3/warning/thumbnail?&token={METEOFRANCE_API_TOKEN}"
f"&domain={domain}"
)

Expand Down
48 changes: 24 additions & 24 deletions src/meteofrance_api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@
ALERT_COLOR_LIST_EN = [None, "Green", "Yellow", "Orange", "Red"]

# Weather alert type
ALERT_TYPE_LIST_FR = [
None,
"Vent violent",
"Pluie-inondation",
"Orages",
"Inondation",
"Neige-verglas",
"Canicule",
"Grand-froid",
"Avalanches",
"Vagues-submersion",
]
ALERT_TYPE_DICTIONARY_FR = {
"0": None,
"1": "Vent violent",
"2": "Pluie-inondation",
"3": "Orages",
"4": "Inondation",
"5": "Neige-verglas",
"6": "Canicule",
"7": "Grand-froid",
"8": "Avalanches",
"9": "Vagues-submersion",
}

ALERT_TYPE_LIST_EN = [
None,
"Wind",
"Rain-Flood",
"Thunderstorms",
"Flood",
"Snow/Ice",
"Extreme high temperature",
"Extreme low temperature",
"Avalanches",
"Coastal Event",
]
ALERT_TYPE_DICTIONARY_EN = {
"0": None,
"1": "Wind",
"2": "Rain-Flood",
"3": "Thunderstorms",
"4": "Flood",
"5": "Snow/Ice",
"6": "Extreme high temperature",
"7": "Extreme low temperature",
"8": "Avalanches",
"9": "Coastal Event",
}
Quentame marked this conversation as resolved.
Show resolved Hide resolved


# Valide departments list for weather alert bulletin
Expand Down
13 changes: 7 additions & 6 deletions src/meteofrance_api/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@

from .const import ALERT_COLOR_LIST_EN
from .const import ALERT_COLOR_LIST_FR
from .const import ALERT_TYPE_LIST_EN
from .const import ALERT_TYPE_LIST_FR
from .const import ALERT_TYPE_DICTIONARY_EN
from .const import ALERT_TYPE_DICTIONARY_FR
from .const import COASTAL_DEPARTMENT_LIST
from .const import VALID_DEPARTMENT_LIST
from .model.place import Place
from .model.warning import PhenomenonMaxColor


def get_warning_text_status_from_indice_color(
Expand All @@ -39,7 +40,7 @@ def get_warning_text_status_from_indice_color(


def get_phenomenon_name_from_indice(
int_phenomenon: int, lang: str = "fr"
int_phenomenon: str, lang: str = "fr"
) -> Optional[str]:
"""Convert the phenomenom code in readable text (Hepler).

Expand All @@ -52,9 +53,9 @@ def get_phenomenon_name_from_indice(
Phenomenom in text. French or English according to the lang parameter.
"""
if lang == "fr":
return ALERT_TYPE_LIST_FR[int_phenomenon]
return ALERT_TYPE_DICTIONARY_FR[int_phenomenon]

return ALERT_TYPE_LIST_EN[int_phenomenon]
return ALERT_TYPE_DICTIONARY_EN[int_phenomenon]


def is_coastal_department(department_number: str) -> bool:
Expand Down Expand Up @@ -84,7 +85,7 @@ def is_valid_warning_department(department_number: str) -> bool:


def readeable_phenomenoms_dict(
list_phenomenoms: List[Dict[str, int]], language: str = "fr"
list_phenomenoms: List[PhenomenonMaxColor], language: str = "fr"
) -> Dict[Optional[str], Optional[str]]:
"""Create a dictionary with human readable keys and values (Helper).

Expand Down
30 changes: 26 additions & 4 deletions src/meteofrance_api/model/warning.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,35 @@
from typing import TypedDict


# Define a custom type for items in the phenomenons_max_colors list
class PhenomenonMaxColor(TypedDict):
"""A type definition for representing a meteorological phenomenon and its maximum color code.

Attributes:
phenomenon_id (str): A unique identifier for the meteorological phenomenon.
This is kept as a string to match the format provided by
the API and could represent various types of weather
phenomena (e.g., storms, heavy rain, etc.).

phenomenon_max_color_id (int): An integer representing the maximum alert color
code associated with the phenomenon. The color
codes typically indicate the severity or urgency
of the weather-related alerts or warnings, with
each color corresponding to a specific level of
alert.
"""

phenomenon_id: str
phenomenon_max_color_id: int


class WarnningCurrentPhenomenonsData(TypedDict):
"""Describing the data structure of CurrentPhenomenons object from the REST API."""

update_time: int
end_validity_time: int
domain_id: str
phenomenons_max_colors: List[Dict[str, int]]
phenomenons_max_colors: List[PhenomenonMaxColor]


class WarnningFullData(TypedDict):
Expand All @@ -27,7 +49,7 @@ class WarnningFullData(TypedDict):
domain_id: str
color_max: int
timelaps: List[Dict[str, Any]]
phenomenons_items: List[Dict[str, int]]
phenomenons_items: List[PhenomenonMaxColor]
advices: Optional[List[Dict[str, Any]]]
consequences: Optional[List[Dict[str, Any]]]
max_count_items: Any # Didn't see any value yet
Expand Down Expand Up @@ -79,7 +101,7 @@ def domain_id(self) -> str:
return self.raw_data["domain_id"]

@property
def phenomenons_max_colors(self) -> List[Dict[str, int]]:
def phenomenons_max_colors(self) -> List[PhenomenonMaxColor]:
"""Return the list and colors of the phenomenoms."""
return self.raw_data["phenomenons_max_colors"]

Expand Down Expand Up @@ -171,7 +193,7 @@ def timelaps(self) -> List[Dict[str, Any]]:
return self.raw_data["timelaps"]

@property
def phenomenons_items(self) -> List[Dict[str, int]]:
def phenomenons_items(self) -> List[PhenomenonMaxColor]:
"""Return the phenomenom list of the domain."""
return self.raw_data["phenomenons_items"]

Expand Down
16 changes: 9 additions & 7 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@
from meteofrance_api.helpers import sort_places_versus_distance_from_coordinates
from meteofrance_api.model import Place
from meteofrance_api.model.place import PlaceData
from meteofrance_api.model.warning import PhenomenonMaxColor


def test_text_helpers_fr() -> None:
"""Test helpers to have readable alert type and alert level in French."""
assert get_warning_text_status_from_indice_color(1) == "Vert"
assert get_phenomenon_name_from_indice(2) == "Pluie-inondation"
assert get_phenomenon_name_from_indice("2") == "Pluie-inondation"


def test_get_warning_text_status_from_indice_color_en() -> None:
"""Test helpers to have readable alert type and alert level in English."""
assert get_warning_text_status_from_indice_color(4, "en") == "Red"
assert get_phenomenon_name_from_indice(4, "en") == "Flood"
assert get_phenomenon_name_from_indice("4", "en") == "Flood"


@pytest.mark.parametrize("dep, res", [("03", False), ("06", True), ("2B", True)])
Expand All @@ -43,12 +44,13 @@ def test_is_valid_warning_department(dep: str, res: bool) -> None:
def test_readeable_phenomenoms_dict() -> None:
"""Test the helper constructing a human readable dictionary for phenomenom."""
api_list = [
{"phenomenon_id": 4, "phenomenon_max_color_id": 1},
{"phenomenon_id": 5, "phenomenon_max_color_id": 1},
{"phenomenon_id": 3, "phenomenon_max_color_id": 2},
{"phenomenon_id": 2, "phenomenon_max_color_id": 1},
{"phenomenon_id": 1, "phenomenon_max_color_id": 3},
PhenomenonMaxColor(phenomenon_id="4", phenomenon_max_color_id=1),
PhenomenonMaxColor(phenomenon_id="5", phenomenon_max_color_id=1),
PhenomenonMaxColor(phenomenon_id="3", phenomenon_max_color_id=2),
PhenomenonMaxColor(phenomenon_id="2", phenomenon_max_color_id=1),
PhenomenonMaxColor(phenomenon_id="1", phenomenon_max_color_id=3),
]

expected_dictionary = {
"Inondation": "Vert",
"Neige-verglas": "Vert",
Expand Down
1 change: 0 additions & 1 deletion tests/test_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from meteofrance_api.helpers import readeable_phenomenoms_dict


@pytest.mark.skip(reason="Returns 502 Server Error: Bad Gateway from summer 2023")
@pytest.mark.parametrize("city", ["montreal", "Foix"])
def test_workflow(city: str) -> None:
"""Test classical workflow usage with the Python library."""
Expand Down
12 changes: 6 additions & 6 deletions tests/test_picture_of_the_day.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# coding: utf-8
"""Tests Météo-France module. PictureOfTheDay class."""
from meteofrance_api import const
from meteofrance_api import MeteoFranceClient


Expand All @@ -10,9 +11,8 @@ def test_picture_of_the_day() -> None:
potd = client.get_picture_of_the_day()

assert potd.description
assert potd.image_url == (
"https://webservice.meteofrance.com/v2/report"
"?domain=france&report_type=observation"
"&report_subtype=image%20du%20jour&format=jpg"
"&token=__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__"
)
params = "?domain=france&report_type=observation&report_subtype=image%20du%20jour&format=jpg"
token_param = f"&token={const.METEOFRANCE_API_TOKEN}"
path = "/v2/report"
assert_url = f"{const.METEOFRANCE_API_URL}{path}{params}{token_param}"
assert potd.image_url == assert_url
24 changes: 10 additions & 14 deletions tests/test_warning.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@
WARNING_COLOR_LIST = [1, 2, 3, 4]


@pytest.mark.skip(reason="Returns 502 Server Error: Bad Gateway from summer 2023")
def test_currentphenomenons(requests_mock: Mock) -> None:
"""Test basic weather alert results from API."""
client = MeteoFranceClient()

requests_mock.request(
"get",
f"{METEOFRANCE_API_URL}/warning/currentphenomenons",
f"{METEOFRANCE_API_URL}/v3/warning/currentphenomenons",
json={
"update_time": 1591279200,
"end_validity_time": 1591365600,
"domain_id": "32",
"phenomenons_max_colors": [
{"phenomenon_id": 6, "phenomenon_max_color_id": 1},
{"phenomenon_id": 4, "phenomenon_max_color_id": 1},
{"phenomenon_id": 5, "phenomenon_max_color_id": 3},
{"phenomenon_id": 2, "phenomenon_max_color_id": 1},
{"phenomenon_id": 1, "phenomenon_max_color_id": 1},
{"phenomenon_id": 3, "phenomenon_max_color_id": 2},
{"phenomenon_id": "6", "phenomenon_max_color_id": 1},
{"phenomenon_id": "4", "phenomenon_max_color_id": 1},
{"phenomenon_id": "5", "phenomenon_max_color_id": 3},
{"phenomenon_id": "2", "phenomenon_max_color_id": 1},
{"phenomenon_id": "1", "phenomenon_max_color_id": 1},
{"phenomenon_id": "3", "phenomenon_max_color_id": 2},
],
},
)
Expand All @@ -42,7 +41,6 @@ def test_currentphenomenons(requests_mock: Mock) -> None:
assert current_phenomenoms.get_domain_max_color() == 3


@pytest.mark.skip(reason="Returns 502 Server Error: Bad Gateway from summer 2023")
def test_fulls() -> None:
"""Test advanced weather alert results from API."""
client = MeteoFranceClient()
Expand Down Expand Up @@ -70,13 +68,12 @@ def test_thumbnail() -> None:
thumbnail_url = client.get_warning_thumbnail()

assert thumbnail_url == (
"https://webservice.meteofrance.com/warning/thumbnail"
"https://webservice.meteofrance.com/v3/warning/thumbnail"
"?&token=__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__&"
"domain=france"
)


@pytest.mark.skip(reason="Returns 502 Server Error: Bad Gateway from summer 2023")
@pytest.mark.parametrize("dep, res", [("13", True), ("32", False)])
def test_currentphenomenons_with_coastal_bulletin(dep: str, res: bool) -> None:
"""Test getting a complete basic bulletin for coastal department."""
Expand All @@ -86,13 +83,12 @@ def test_currentphenomenons_with_coastal_bulletin(dep: str, res: bool) -> None:
domain=dep, depth=1, with_costal_bulletin=True
)
has_coastal_phenomenom = any(
phenomenom["phenomenon_id"] == 9
phenomenom["phenomenon_id"] == "9"
faizpuru marked this conversation as resolved.
Show resolved Hide resolved
for phenomenom in current_phenomenoms.phenomenons_max_colors
)
assert has_coastal_phenomenom == res


@pytest.mark.skip(reason="Returns 502 Server Error: Bad Gateway from summer 2023")
@pytest.mark.parametrize("dep, res", [("13", True), ("32", False)])
def test_full_with_coastal_bulletint(dep: str, res: bool) -> None:
"""Test getting a complete advanced bulletin for coastal department."""
Expand All @@ -101,7 +97,7 @@ def test_full_with_coastal_bulletint(dep: str, res: bool) -> None:
full_phenomenoms = client.get_warning_full(domain=dep, with_costal_bulletin=True)

has_coastal_phenomenom = any(
phenomenom["phenomenon_id"] == 9
phenomenom["phenomenon_id"] == "9"
faizpuru marked this conversation as resolved.
Show resolved Hide resolved
for phenomenom in full_phenomenoms.phenomenons_items
)
assert has_coastal_phenomenom == res