|
1 |
| -import datetime |
| 1 | +from datetime import datetime |
2 | 2 | import functools
|
3 |
| -from typing import Dict |
| 3 | +from typing import Any, Dict |
4 | 4 |
|
5 | 5 | import httpx
|
6 | 6 |
|
7 | 7 | from app import config
|
8 | 8 |
|
9 |
| -# This feature requires an API KEY - get yours free @ www.weatherapi.com |
| 9 | +# This feature requires an API key. Get yours free at www.weatherapi.com. |
| 10 | +ASTRONOMY_URL = "https://api.weatherapi.com/v1/astronomy.json" |
| 11 | +NO_API_RESPONSE = _("No response from server.") |
10 | 12 |
|
11 |
| -ASTRONOMY_URL = "http://api.weatherapi.com/v1/astronomy.json" |
12 |
| -NO_API_RESPONSE = "No response from server" |
13 | 13 |
|
| 14 | +async def get_astronomical_data( |
| 15 | + date: datetime, location: str |
| 16 | +) -> Dict[str, Any]: |
| 17 | + """Returns astronomical data (sun and moon) for date and location. |
14 | 18 |
|
15 |
| -@functools.lru_cache(maxsize=128, typed=False) |
16 |
| -async def get_data_from_api(formatted_date: str, location: str) \ |
17 |
| - -> Dict[str, int]: |
18 |
| - """ get the relevant astronomical data by calling the "weather api" API. |
19 | 19 | Args:
|
20 |
| - formatted_date (date) - relevant date. |
21 |
| - location (str) - location name. |
| 20 | + date: The requested date for astronomical data. |
| 21 | + location: The location name. |
| 22 | +
|
| 23 | + Returns: |
| 24 | + A dictionary with the following entries: |
| 25 | + success: True or False. |
| 26 | + error: The error description. |
| 27 | + location: A dictionary of relevant data, including: |
| 28 | + name, region, country, lat, lon etc. |
| 29 | + astronomy: A dictionary of relevant data, including: |
| 30 | + sunrise, sunset, moonrise, moonset, moon_phase, and |
| 31 | + moon_illumination. |
| 32 | + """ |
| 33 | + formatted_date = date.strftime('%Y-%m-%d') |
| 34 | + return await _get_astronomical_data_from_api(formatted_date, location) |
| 35 | + |
| 36 | + |
| 37 | +@functools.lru_cache(maxsize=128) |
| 38 | +async def _get_astronomical_data_from_api( |
| 39 | + date: str, location: str |
| 40 | +) -> Dict[str, Any]: |
| 41 | + """Returns astronomical_data from a Weather API call. |
| 42 | +
|
| 43 | + Args: |
| 44 | + date: The requested date for astronomical data. |
| 45 | + location: The location name. |
| 46 | +
|
22 | 47 | Returns:
|
23 |
| - response_json (json dict) including: |
24 |
| - relevant part (data / error) of the JSON returned by the API. |
25 |
| - Success (bool) |
26 |
| - ErrorDescription (str) - error message. |
| 48 | + A dictionary with the results from the API call. |
27 | 49 | """
|
28 |
| - input_query_string = {'key': config.ASTRONOMY_API_KEY, 'q': location, |
29 |
| - 'dt': formatted_date} |
30 |
| - output = {} |
| 50 | + input_query_string = { |
| 51 | + 'key': config.ASTRONOMY_API_KEY, |
| 52 | + 'q': location, |
| 53 | + 'dt': date, |
| 54 | + } |
| 55 | + |
| 56 | + output: Dict[str, Any] = {} |
31 | 57 | try:
|
32 | 58 | async with httpx.AsyncClient() as client:
|
33 |
| - response = await client.get(ASTRONOMY_URL, |
34 |
| - params=input_query_string) |
| 59 | + response = await client.get( |
| 60 | + ASTRONOMY_URL, params=input_query_string) |
35 | 61 | except httpx.HTTPError:
|
36 |
| - output["Success"] = False |
37 |
| - output["ErrorDescription"] = NO_API_RESPONSE |
| 62 | + output["success"] = False |
| 63 | + output["error"] = NO_API_RESPONSE |
38 | 64 | return output
|
| 65 | + |
39 | 66 | if response.status_code != httpx.codes.OK:
|
40 |
| - output["Success"] = False |
41 |
| - output["ErrorDescription"] = NO_API_RESPONSE |
| 67 | + output["success"] = False |
| 68 | + output["error"] = NO_API_RESPONSE |
42 | 69 | return output
|
43 |
| - output["Success"] = True |
| 70 | + |
| 71 | + output["success"] = True |
44 | 72 | try:
|
45 | 73 | output.update(response.json()['location'])
|
46 | 74 | return output
|
47 | 75 | except KeyError:
|
48 |
| - output["Success"] = False |
49 |
| - output["ErrorDescription"] = response.json()['error']['message'] |
| 76 | + output["success"] = False |
| 77 | + output["error"] = response.json()['error']['message'] |
50 | 78 | return output
|
51 |
| - |
52 |
| - |
53 |
| -async def get_astronomical_data(requested_date: datetime.datetime, |
54 |
| - location: str) -> Dict[str, int]: |
55 |
| - """ get astronomical data (Sun & Moon) for date & location - |
56 |
| - main function. |
57 |
| - Args: |
58 |
| - requested_date (date) - date requested for astronomical data. |
59 |
| - location (str) - location name. |
60 |
| - Returns: dictionary with the following entries: |
61 |
| - Status - success / failure. |
62 |
| - ErrorDescription - error description (relevant only in case of error). |
63 |
| - location - relevant location values(relevant only in case of success). |
64 |
| - name, region, country, lat, lon etc. |
65 |
| - astronomy - relevant astronomy values, all time in local time - |
66 |
| - (relevant only in case of success): |
67 |
| - sunrise, sunset, moonrise, moonset, moon_phase, moon_illumination. |
68 |
| - """ |
69 |
| - formatted_date = requested_date.strftime('%Y-%m-%d') |
70 |
| - return await get_data_from_api(formatted_date, location) |
|
0 commit comments