From 8f90c0c8d3bc235d85264ac305fb82383d58294d Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Wed, 27 Jan 2021 18:05:42 +0200 Subject: [PATCH 01/21] feat: astronomy --- app/config.py.example | 1 + app/internal/astronomy.py | 88 +++++++++++++++++++++++++++++++++++++++ tests/test_astronomy.py | 63 ++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 app/internal/astronomy.py create mode 100644 tests/test_astronomy.py diff --git a/app/config.py.example b/app/config.py.example index 5b499142..e88ae624 100644 --- a/app/config.py.example +++ b/app/config.py.example @@ -17,6 +17,7 @@ PICTURE_EXTENSION = '.png' AVATAR_SIZE = (120, 120) # API-KEYS +ASTRONOMY_API_KEY = os.getenv('ASTRONOMY_API_KEY') WEATHER_API_KEY = os.getenv('WEATHER_API_KEY') # export diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py new file mode 100644 index 00000000..b19cb31f --- /dev/null +++ b/app/internal/astronomy.py @@ -0,0 +1,88 @@ +import datetime +import functools +import frozendict +import requests +from typing import Dict, Tuple, Union + +from app import config + + +# This feature requires an API KEY - get yours free @ www.weatherapi.com + +SUCCESS_STATUS = 0 +ERROR_STATUS = -1 +ASTRONOMY_URL = "http://api.weatherapi.com/v1/astronomy.json" +NO_API_RESPONSE = "No response from server" + + +def freezeargs(func): + """Transform mutable dictionary into immutable + Credit to 'fast_cen' from 'stackoverflow' + https://stackoverflow.com/questions/6358481/ + using-functools-lru-cache-with-dictionary-arguments + """ + @functools.wraps(func) + def wrapped(*args, **kwargs): + args = tuple([frozendict.frozendict(arg) + if isinstance(arg, dict) else arg for arg in args]) + kwargs = {k: frozendict.frozendict(v) if isinstance(v, dict) else v + for k, v in kwargs.items()} + return func(*args, **kwargs) + return wrapped + + +@freezeargs +@functools.lru_cache(maxsize=128, typed=False) +def get_data_from_api(formatted_date: str, location: str)\ + -> Union[Tuple[None, str], Tuple[dict, None]]: + """ get the relevant astronomical data by calling the "weather api" API. + Args: + formatted_date (date) - relevant date. + location (str) - location name. + Returns: + response_json (json dict) - relevant part (data / error) of the + JSON returned by the API. + error_text (str) - error message. + """ + input_query_string = dict(key=config.ASTRONOMY_API_KEY, q=location, + dt=formatted_date) + try: + response = requests.request("GET", ASTRONOMY_URL, + params=input_query_string) + except requests.exceptions.RequestException: + return None, NO_API_RESPONSE + if response.ok: + try: + return response.json()['location'], None + except KeyError: + return None, response.json()['error']['message'] + return None, NO_API_RESPONSE + + +def get_astronomical_data(requested_date: datetime.datetime, location: str)\ + -> Dict[str, int]: + """ get astronomical data (Sun & Moon) for date & location - + main function. + Args: + requested_date (date) - date requested for astronomical data. + location (str) - location name. + Returns: dictionary with the following entries: + Status - success / failure. + ErrorDescription - error description (relevant only in case of error). + location - relevant location values(relevant only in case of success). + name, region, country, lat, lon etc. + astronomy - relevant astronomy values, all time in local time - + (relevant only in case of success): + sunrise, sunset, moonrise, moonset, moon_phase, moon_illumination. + """ + output = {} + formatted_date = requested_date.strftime('%Y-%m-%d') + astronomical_data, error_text = get_data_from_api(formatted_date, + location) + if astronomical_data: + output["Status"] = SUCCESS_STATUS + output.update(astronomical_data) + else: + output["Status"] = ERROR_STATUS + output["ErrorDescription"] = error_text + return output diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py new file mode 100644 index 00000000..85a76749 --- /dev/null +++ b/tests/test_astronomy.py @@ -0,0 +1,63 @@ +import datetime +import pytest +import requests +import responses + +from app.internal.astronomy import get_astronomical_data + + +ASTRONOMY_URL = "http://api.weatherapi.com/v1/astronomy.json" +RESPONSE_FROM_MOCK = {"location": { + "name": "Tel Aviv-Yafo", + "region": "Tel Aviv", + "country": "Israel", + "lat": 32.07, + "lon": 34.76, + "tz_id": "Asia/Jerusalem", + "localtime_epoch": 1611399607, + "localtime": "2021-01-23 13:00" + }, + "astronomy": { + "astro": { + "sunrise": "05:25 AM", + "sunset": "06:03 PM", + "moonrise": "01:56 PM", + "moonset": "03:04 AM", + "moon_phase": "Waxing Gibbous", + "moon_illumination": "79" + } + } +} +ERROR_RESPONSE_FROM_MOCK = {"error": {"message": "Error Text"}} + + +def test_get_astronomical_data(requests_mock): + requested_date = datetime.datetime(day=4, month=4, year=2020) + requests_mock.get(ASTRONOMY_URL, json=RESPONSE_FROM_MOCK) + output = get_astronomical_data(requested_date, "tel aviv") + assert output['Status'] == 0 + + +def test_astronomical_data_error_from_api(requests_mock): + requested_date = datetime.datetime(day=4, month=4, year=2021) + requests_mock.get(ASTRONOMY_URL, json=ERROR_RESPONSE_FROM_MOCK) + output = get_astronomical_data(requested_date, "123") + assert output['Status'] == -1 + + +@responses.activate +def test_astronomical_exception_from_api(): + requested_date = datetime.datetime.now() + datetime.timedelta(days=3) + with pytest.raises(requests.exceptions.ConnectionError): + requests.get(ASTRONOMY_URL) + output = get_astronomical_data(requested_date, "456") + assert output['Status'] == -1 + + +@responses.activate +def test_astronomical_no_response_from_api(): + requested_date = datetime.datetime(day=11, month=1, year=2020) + responses.add(responses.GET, ASTRONOMY_URL, status=500) + requests.get(ASTRONOMY_URL) + output = get_astronomical_data(requested_date, "789") + assert output['Status'] == -1 From 2f62fe00bfcfacd93b74e1753af62ffe2117ff40 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sun, 31 Jan 2021 00:52:41 +0200 Subject: [PATCH 02/21] feat: astronomy - async support & fixes --- app/config.py.example | 1 + app/internal/astronomy.py | 80 +++++++++++++++------------------------ tests/test_astronomy.py | 8 ++-- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/app/config.py.example b/app/config.py.example index e3ee9bee..fd356bbb 100644 --- a/app/config.py.example +++ b/app/config.py.example @@ -27,6 +27,7 @@ PICTURE_EXTENSION = '.png' AVATAR_SIZE = (120, 120) # API-KEYS +# Get a free API KEY for Astronomy feature @ www.weatherapi.com/signup.aspx ASTRONOMY_API_KEY = os.getenv('ASTRONOMY_API_KEY') WEATHER_API_KEY = os.getenv('WEATHER_API_KEY') diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index b19cb31f..eefe3daf 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -1,62 +1,52 @@ +import asyncio import datetime import functools -import frozendict -import requests -from typing import Dict, Tuple, Union +import httpx +from typing import Dict from app import config # This feature requires an API KEY - get yours free @ www.weatherapi.com -SUCCESS_STATUS = 0 -ERROR_STATUS = -1 ASTRONOMY_URL = "http://api.weatherapi.com/v1/astronomy.json" NO_API_RESPONSE = "No response from server" -def freezeargs(func): - """Transform mutable dictionary into immutable - Credit to 'fast_cen' from 'stackoverflow' - https://stackoverflow.com/questions/6358481/ - using-functools-lru-cache-with-dictionary-arguments - """ - @functools.wraps(func) - def wrapped(*args, **kwargs): - args = tuple([frozendict.frozendict(arg) - if isinstance(arg, dict) else arg for arg in args]) - kwargs = {k: frozendict.frozendict(v) if isinstance(v, dict) else v - for k, v in kwargs.items()} - return func(*args, **kwargs) - return wrapped - - -@freezeargs @functools.lru_cache(maxsize=128, typed=False) -def get_data_from_api(formatted_date: str, location: str)\ - -> Union[Tuple[None, str], Tuple[dict, None]]: +async def get_data_from_api(formatted_date: str, location: str) -> Dict[str, int]: """ get the relevant astronomical data by calling the "weather api" API. Args: formatted_date (date) - relevant date. location (str) - location name. Returns: - response_json (json dict) - relevant part (data / error) of the - JSON returned by the API. - error_text (str) - error message. + response_json (json dict) including: + relevant part (data / error) of the JSON returned by the API. + Success (bool) + ErrorDescription (str) - error message. """ - input_query_string = dict(key=config.ASTRONOMY_API_KEY, q=location, - dt=formatted_date) + input_query_string = {'key': config.ASTRONOMY_API_KEY, 'q': location, + 'dt': formatted_date} + output = {} + try: + async with httpx.AsyncClient() as client: + response = await client.get(ASTRONOMY_URL, params=input_query_string) + except httpx.HTTPError: + output["Success"] = False + output["ErrorDescription"] = NO_API_RESPONSE + return output + if response.status_code != httpx.codes.OK: + output["Success"] = False + output["ErrorDescription"] = NO_API_RESPONSE + return output + output["Success"] = True try: - response = requests.request("GET", ASTRONOMY_URL, - params=input_query_string) - except requests.exceptions.RequestException: - return None, NO_API_RESPONSE - if response.ok: - try: - return response.json()['location'], None - except KeyError: - return None, response.json()['error']['message'] - return None, NO_API_RESPONSE + output.update(response.json()['location']) + return output + except KeyError: + output["Success"] = False + output["ErrorDescription"] = response.json()['error']['message'] + return output def get_astronomical_data(requested_date: datetime.datetime, location: str)\ @@ -75,14 +65,6 @@ def get_astronomical_data(requested_date: datetime.datetime, location: str)\ (relevant only in case of success): sunrise, sunset, moonrise, moonset, moon_phase, moon_illumination. """ - output = {} formatted_date = requested_date.strftime('%Y-%m-%d') - astronomical_data, error_text = get_data_from_api(formatted_date, - location) - if astronomical_data: - output["Status"] = SUCCESS_STATUS - output.update(astronomical_data) - else: - output["Status"] = ERROR_STATUS - output["ErrorDescription"] = error_text - return output + loop = asyncio.get_event_loop() + return loop.run_until_complete(get_data_from_api(formatted_date, location)) diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index 85a76749..10a8e161 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -35,14 +35,14 @@ def test_get_astronomical_data(requests_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) requests_mock.get(ASTRONOMY_URL, json=RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "tel aviv") - assert output['Status'] == 0 + assert output['Success'] is True def test_astronomical_data_error_from_api(requests_mock): requested_date = datetime.datetime(day=4, month=4, year=2021) requests_mock.get(ASTRONOMY_URL, json=ERROR_RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "123") - assert output['Status'] == -1 + assert output['Success'] is False @responses.activate @@ -51,7 +51,7 @@ def test_astronomical_exception_from_api(): with pytest.raises(requests.exceptions.ConnectionError): requests.get(ASTRONOMY_URL) output = get_astronomical_data(requested_date, "456") - assert output['Status'] == -1 + assert output['Success'] is False @responses.activate @@ -60,4 +60,4 @@ def test_astronomical_no_response_from_api(): responses.add(responses.GET, ASTRONOMY_URL, status=500) requests.get(ASTRONOMY_URL) output = get_astronomical_data(requested_date, "789") - assert output['Status'] == -1 + assert output['Success'] is False From e4bd1647db1c35e69a0ce64eae4e674b5d3a73cf Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sun, 31 Jan 2021 00:56:04 +0200 Subject: [PATCH 03/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index eefe3daf..c3cc6d35 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -14,7 +14,8 @@ @functools.lru_cache(maxsize=128, typed=False) -async def get_data_from_api(formatted_date: str, location: str) -> Dict[str, int]: +async def get_data_from_api(formatted_date: str, location: str)\ + -> Dict[str, int]: """ get the relevant astronomical data by calling the "weather api" API. Args: formatted_date (date) - relevant date. @@ -30,7 +31,8 @@ async def get_data_from_api(formatted_date: str, location: str) -> Dict[str, int output = {} try: async with httpx.AsyncClient() as client: - response = await client.get(ASTRONOMY_URL, params=input_query_string) + response = await client.get(ASTRONOMY_URL, + params=input_query_string) except httpx.HTTPError: output["Success"] = False output["ErrorDescription"] = NO_API_RESPONSE @@ -67,4 +69,5 @@ def get_astronomical_data(requested_date: datetime.datetime, location: str)\ """ formatted_date = requested_date.strftime('%Y-%m-%d') loop = asyncio.get_event_loop() - return loop.run_until_complete(get_data_from_api(formatted_date, location)) + return loop.run_until_complete(get_data_from_api(formatted_date, + location)) From 73e68b03d6f4b91962021bdc586cf39ceaa97442 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sun, 31 Jan 2021 01:06:58 +0200 Subject: [PATCH 04/21] feat: astronomy - async support & fixes --- tests/test_astronomy.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index 10a8e161..976a7500 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -35,14 +35,14 @@ def test_get_astronomical_data(requests_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) requests_mock.get(ASTRONOMY_URL, json=RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "tel aviv") - assert output['Success'] is True + assert output['Success'] def test_astronomical_data_error_from_api(requests_mock): requested_date = datetime.datetime(day=4, month=4, year=2021) requests_mock.get(ASTRONOMY_URL, json=ERROR_RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "123") - assert output['Success'] is False + assert not output['Success'] @responses.activate @@ -51,7 +51,7 @@ def test_astronomical_exception_from_api(): with pytest.raises(requests.exceptions.ConnectionError): requests.get(ASTRONOMY_URL) output = get_astronomical_data(requested_date, "456") - assert output['Success'] is False + assert not output['Success'] @responses.activate @@ -60,4 +60,4 @@ def test_astronomical_no_response_from_api(): responses.add(responses.GET, ASTRONOMY_URL, status=500) requests.get(ASTRONOMY_URL) output = get_astronomical_data(requested_date, "789") - assert output['Success'] is False + assert not output['Success'] From ec19dd075d87cb730369ffbe960190119b5a0a6f Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Mon, 1 Feb 2021 19:48:54 +0200 Subject: [PATCH 05/21] feat: astronomy - async support & fixes --- tests/test_astronomy.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index 976a7500..c0ad0734 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -4,9 +4,8 @@ import responses from app.internal.astronomy import get_astronomical_data +from app.internal.astronomy import ASTRONOMY_URL - -ASTRONOMY_URL = "http://api.weatherapi.com/v1/astronomy.json" RESPONSE_FROM_MOCK = {"location": { "name": "Tel Aviv-Yafo", "region": "Tel Aviv", @@ -31,9 +30,10 @@ ERROR_RESPONSE_FROM_MOCK = {"error": {"message": "Error Text"}} -def test_get_astronomical_data(requests_mock): +@pytest.mark.asyncio +def test_get_astronomical_data(httpx_mock, assert_all_responses_were_requested): requested_date = datetime.datetime(day=4, month=4, year=2020) - requests_mock.get(ASTRONOMY_URL, json=RESPONSE_FROM_MOCK) + httpx_mock.add_response(method="GET", json=RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "tel aviv") assert output['Success'] From c62261cbdeae05907471b19d12c346d0b13d0297 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Mon, 1 Feb 2021 19:51:35 +0200 Subject: [PATCH 06/21] feat: astronomy - async support & fixes --- tests/test_astronomy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index c0ad0734..d5231377 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -31,7 +31,7 @@ @pytest.mark.asyncio -def test_get_astronomical_data(httpx_mock, assert_all_responses_were_requested): +def test_get_astronomical_data(httpx_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) httpx_mock.add_response(method="GET", json=RESPONSE_FROM_MOCK) output = get_astronomical_data(requested_date, "tel aviv") From 0ad43442c971aa9ccfe804562ba09b77224a34ac Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Mon, 1 Feb 2021 20:05:08 +0200 Subject: [PATCH 07/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3266 -> 1576 bytes tests/test_astronomy.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 68490a7615502d74a5842e5a8ff2781513bfa092..f877307e37df65298124b12fcd58fe4fa20b5ab3 100644 GIT binary patch delta 190 zcmX>kxq@ec%ESdSlUW$GCi^i;Og_dqZ!#aVl6oRTF+&MMB0~W~CPO?!E|8VUki%dL zga!iRMN`SUhz|A%U+h92PB!}^2F;0caC7g1TWw<0J Xf8g?&oWd+Hl3nPVp5(i-E&I|- z2YckR_|iV*8~IqAbkKVrK6;(^EUWgZ>8}n)U|1y(C-dw2Cw6@BYMt@nt;nI|w~FwBd&wovZ!qWp9RN z;oos4qfMv$meNRu$b6xbdEi>B1_$}x1PE+S`r#;9SSt!>=t^d%?jJPB=U1I}QRpN%X9DlFAqIUJ$x}8F2XJm1B3x@{ zkb9mt^8Y0N@V!$$WLq~qe6TZr7p6h|aFDOh`u}ds$xN7yPB`{s&%iQMlYPYW!<9Mo z_PLS#lTJ5*-+P>i!6yiNogZXze};Z~ng-Yat+#UJgvhpL%Tv8x9%kZi5eUe`+Ej~p zR}rgvn94qV*aKUUDSZ|q*AiQIEjXW}!#Zi?_9q9n4%{KH+ad1&--1R;g}?>>l_PIa zI^O%y7^p9i-D}^=8hOdPEpI;W0?+Yi-40?gH1<^*%?{C_`$&cCGh( ztp)qt_#1VbUkjc%BJ(8^c@H$>)GpNn@Vbf4M$v|N}aDl zW}eRbgc$4__GYV|`XCOjB0APtTVkBsv;S)4(1bbIK$Bb7v(EpOF?Yg$#iCQ4i}8aH z&-s?S71GpzSG+Q3JM}j&5u|>ZVW0KqeM2?qA@5zbH#5PVQ5ng;%J&dxmhsN0y-ckC z=k0U(LpA-V&fqn~yQA&|BF^-KS1=8+3ApL%Zuf2?OHSFTjjBn$><{wcF9^w*iu-lx z&i3q?DO)9h8$2o{R6aN5Y%IlE; diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index d5231377..08c51a3b 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -29,7 +29,7 @@ } ERROR_RESPONSE_FROM_MOCK = {"error": {"message": "Error Text"}} - +#, assert_all_responses_were_requested @pytest.mark.asyncio def test_get_astronomical_data(httpx_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) From 692f871dd99c06b5b052474736453d76da981124 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Mon, 1 Feb 2021 20:06:51 +0200 Subject: [PATCH 08/21] feat: astronomy - async support & fixes --- tests/test_astronomy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index 08c51a3b..d5231377 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -29,7 +29,7 @@ } ERROR_RESPONSE_FROM_MOCK = {"error": {"message": "Error Text"}} -#, assert_all_responses_were_requested + @pytest.mark.asyncio def test_get_astronomical_data(httpx_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) From 7c07cc71f2cca127409c70215c6f771592017df4 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Mon, 1 Feb 2021 20:11:53 +0200 Subject: [PATCH 09/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 1576 -> 3310 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index f877307e37df65298124b12fcd58fe4fa20b5ab3..6088b4ce2b1c6b56854b6a6f216b2dca440caad3 100644 GIT binary patch literal 3310 zcmb7`OK%%T5QOK<|FVHeSq~p_@Fj;J0UY?0Be|kP$|SX3k|w1eZ>PSlZ4NCd2m)ax zVfs~F{h0aj{m1udS(e9gr{AkGFWd5~e%_T|%9Xx%WmGKhCA*c5vQZCRIH z>7;`_@=1JYpYoM_%uYJ!y$>Iq&b#uZ+@EBZao(3+=nioTs&Tp2Z{ymQr?M%nEFVJ- zqWAhP!ZM|ea4m&yF0H-(2OpaD2ELsnYw5I#)9df<#Dno=Jo4KMJvp@Dha8=&{p@6K zh9=?PaYlp9M)}R9kqnXfOefR8wNwrE^1Th5oiag>d_D|0Ir3Xx+VD%B)Db)48^bs% z0h?`EC|0i;%?BRv4iE6z4taeEdsxoQS|M8L>t(&xhkvZFCI{r-0>M=En}_^Tvh0vs zRcR~ko)mQ<-A!mDcf_8DUplanr)eO$)n6)8`AR(Va+F0YKbZ#-BOaCCWLJ3x2c0}o zl)IDUWiOKn456`A)Tz*#NAkQH`UUxF@NpA4kl~F!Sg79N=VjdLwK?UQJmMv}x>LT7 z})dSVwn zGE=`W*;LH^VvA(dHk+s$9pmYTqhw*JD4?M$nVq_S&>)}Rb-F1JieQF~ChM`5Ex9nq z$x|}%Ag`X;y76+_=%Z&b)r8K2tU=c(JL-Rw1aCy4li-{Qyw`^4^<^Ya*+?9~xowDW zt(`&cdEUtXQU2k3t9;0|ZhH7&XZ|Tnz4~D z=Fr>cM)FTOT?KycaV7?zAnbI$m&N@V`tfNRU<0(?%9Rr$+nOy;^*VW&h`(7NAP;L( zE#h58tm-RxUR1EIjTk(QVX_g zz2|E!*zd;QytyIXj(n6a-W8rrF!Cj5d1Exge9zS_RA3b|fTp`C^YQ(H_G6&g=swA5 z8OJQW_Pmx)x|$aV6*3a{M|L>5Jr6PSW~KK(sqTN5kD8r7Lh6Y$cR%mmWR-3~!cFP@ zd45-W)>7xIkeSi*jv@w|i4EJT`#y++tB8(ub^$TY?b(#I#%RJEY@o^g?5)86l`;3s zf5oDwos02<5YPGQyA{&ZfLFXSky}jyZx*C}!(pHG=Osin=r(U?_B_+W?NS-Z4$PMm zXy)-Esa;R3|L5&<`AaqZsLtTs#0#Zv4n-3dMwXnieH&GieAzVQ z!(R}RGZptc)Sc~FF;_^wN_!pJ)c5kVm)KX_wzu-`w@Z3N4}{k6&iVIyfQ;B>Sb>Fm zhMmo8{o;gjGHfN}-y|c8UOCl%!4LKaq1gp<_mOF8z{f#&XHgF}4!5^!nUj17uVmzX fvmWH`MR(RgXTB?8EpztFjx?#vau??y@=W{#@Lu#j delta 157 zcmV;O0Al~{8K?}A0wj^59FqnCDw9wF7?a2Wo|6y*A`M{xa{zPzVE}LdX#ii7bps!h zP6HT|UBJpeHPE&wqAHIo$!Q Date: Mon, 1 Feb 2021 20:38:23 +0200 Subject: [PATCH 10/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3310 -> 3310 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6088b4ce2b1c6b56854b6a6f216b2dca440caad3..66077b5e7df8313b958f092b332325437783a05a 100644 GIT binary patch delta 11 ScmaDS`A%{p(;FTpE(QP|E(68@ delta 10 RcmaDS`A(AQ|Gy1ycmN+s1-1YH From 64e49c4c6242eba6a3ae5b700e5ada58ebdec245 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Tue, 2 Feb 2021 17:51:48 +0200 Subject: [PATCH 11/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index c3cc6d35..7b77e8da 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -69,5 +69,5 @@ def get_astronomical_data(requested_date: datetime.datetime, location: str)\ """ formatted_date = requested_date.strftime('%Y-%m-%d') loop = asyncio.get_event_loop() - return loop.run_until_complete(get_data_from_api(formatted_date, - location)) + output = loop.run_until_complete(get_data_from_api(formatted_date, location)) + return output From 69a722be3212406c2c7c0f4414ac9a31e21a3cdf Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Tue, 2 Feb 2021 17:53:37 +0200 Subject: [PATCH 12/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index 7b77e8da..150ce878 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -69,5 +69,6 @@ def get_astronomical_data(requested_date: datetime.datetime, location: str)\ """ formatted_date = requested_date.strftime('%Y-%m-%d') loop = asyncio.get_event_loop() - output = loop.run_until_complete(get_data_from_api(formatted_date, location)) + output = loop.run_until_complete(get_data_from_api(formatted_date, + location)) return output From 0c03aa7aabbae476f8a5b87ade502161b27e3a9e Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Tue, 2 Feb 2021 18:21:32 +0200 Subject: [PATCH 13/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3244 -> 3242 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index cfc80370863b9644c2d888ce250e8343d23a598d..f4f3f375c473a2b678923034a2f6bdff71a7e31d 100644 GIT binary patch delta 7 OcmZ1@xk_@wDjom~cLMJK delta 10 RcmZ1_xkhrsDjp^-1^^XW0{Z{} From b748f2e5a5fd30895299e19fa37ca94ba3417807 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Tue, 2 Feb 2021 18:22:45 +0200 Subject: [PATCH 14/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3242 -> 3244 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index f4f3f375c473a2b678923034a2f6bdff71a7e31d..cfc80370863b9644c2d888ce250e8343d23a598d 100644 GIT binary patch delta 10 RcmZ1_xkhrsDjp^-1^^XW0{Z{} delta 7 OcmZ1@xk_@wDjom~cLMJK From 220eab768baa5b3a4f5cf542a22b0e4ac245a5a3 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Tue, 2 Feb 2021 18:33:50 +0200 Subject: [PATCH 15/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3244 -> 3242 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index cfc80370863b9644c2d888ce250e8343d23a598d..f4f3f375c473a2b678923034a2f6bdff71a7e31d 100644 GIT binary patch delta 7 OcmZ1@xk_@wDjom~cLMJK delta 10 RcmZ1_xkhrsDjp^-1^^XW0{Z{} From 9bbce1af5d2d6c283a26356d9731f327b31e5bb5 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Fri, 5 Feb 2021 10:20:09 +0200 Subject: [PATCH 16/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3244 -> 3244 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index cfc80370863b9644c2d888ce250e8343d23a598d..e81d4e8868dbe171ff4b071d7e6891d56ab15eeb 100644 GIT binary patch delta 28 kcmZ1@xkhqB1N-DM4zbDS*f}OQvA>(Vi-T+PG!8Kq0G+Q2EdT%j delta 24 gcmZ1@xkhqB1N-DT>>nmqvCB-}#lf|C8iyDQ0DL$I;s5{u From 4542974c8ac6d98607a5d20d409a386bdce3c2a6 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sat, 6 Feb 2021 18:00:30 +0200 Subject: [PATCH 17/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 6 ------ requirements.txt | Bin 3244 -> 3272 bytes tests/test_astronomy.py | 31 +++++++++++++++++++------------ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index 67b31671..2a046512 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -68,10 +68,4 @@ async def get_astronomical_data(requested_date: datetime.datetime, location: str sunrise, sunset, moonrise, moonset, moon_phase, moon_illumination. """ formatted_date = requested_date.strftime('%Y-%m-%d') - """ - loop = asyncio.get_event_loop() - output = loop.run_until_complete(get_data_from_api(formatted_date, - location)) - return output - """ return await get_data_from_api(formatted_date, location) diff --git a/requirements.txt b/requirements.txt index cfc80370863b9644c2d888ce250e8343d23a598d..28a895574376f66e64855017a03ad12fcfa8705d 100644 GIT binary patch delta 36 pcmZ1@c|vl-H%{?XhGK>Sh6)B-AT(gmV=!be1Cqv@KXUG70sy-A2{!-$ delta 12 TcmX>hxkhrsH_pvMT-%rcBijVs diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index d5231377..87000cb6 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -1,7 +1,10 @@ import datetime +import httpx import pytest import requests import responses +import respx + from app.internal.astronomy import get_astronomical_data from app.internal.astronomy import ASTRONOMY_URL @@ -31,33 +34,37 @@ @pytest.mark.asyncio -def test_get_astronomical_data(httpx_mock): +async def test_get_astronomical_data(httpx_mock): requested_date = datetime.datetime(day=4, month=4, year=2020) httpx_mock.add_response(method="GET", json=RESPONSE_FROM_MOCK) - output = get_astronomical_data(requested_date, "tel aviv") + output = await get_astronomical_data(requested_date, "tel aviv") assert output['Success'] -def test_astronomical_data_error_from_api(requests_mock): +@pytest.mark.asyncio +@respx.mock +async def test_astronomical_data_error_from_api(): requested_date = datetime.datetime(day=4, month=4, year=2021) - requests_mock.get(ASTRONOMY_URL, json=ERROR_RESPONSE_FROM_MOCK) - output = get_astronomical_data(requested_date, "123") + route = respx.get(ASTRONOMY_URL) + route.return_value = httpx.Response(200, json=ERROR_RESPONSE_FROM_MOCK) + output = await get_astronomical_data(requested_date, "123") assert not output['Success'] -@responses.activate -def test_astronomical_exception_from_api(): +@pytest.mark.asyncio +@respx.mock +async def test_astronomical_exception_from_api(httpx_mock): requested_date = datetime.datetime.now() + datetime.timedelta(days=3) - with pytest.raises(requests.exceptions.ConnectionError): - requests.get(ASTRONOMY_URL) - output = get_astronomical_data(requested_date, "456") + respx.get(ASTRONOMY_URL).mock(return_value=httpx.Response(500)) + output = await get_astronomical_data(requested_date, "456") assert not output['Success'] @responses.activate -def test_astronomical_no_response_from_api(): +@pytest.mark.asyncio +async def test_astronomical_no_response_from_api(): requested_date = datetime.datetime(day=11, month=1, year=2020) responses.add(responses.GET, ASTRONOMY_URL, status=500) requests.get(ASTRONOMY_URL) - output = get_astronomical_data(requested_date, "789") + output = await get_astronomical_data(requested_date, "789") assert not output['Success'] From b11d6db4191e2ea91c061f1ff92a04f290af40b5 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sat, 6 Feb 2021 18:03:09 +0200 Subject: [PATCH 18/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index 2a046512..92d65d32 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -51,8 +51,8 @@ async def get_data_from_api(formatted_date: str, location: str)\ return output -async def get_astronomical_data(requested_date: datetime.datetime, location: str)\ - -> Dict[str, int]: +async def get_astronomical_data(requested_date: datetime.datetime, + location: str) -> Dict[str, int]: """ get astronomical data (Sun & Moon) for date & location - main function. Args: From 56a5147b9e42c8746a9c5fd44a76b913737009f1 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sat, 6 Feb 2021 18:04:58 +0200 Subject: [PATCH 19/21] feat: astronomy - async support & fixes --- app/internal/astronomy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/internal/astronomy.py b/app/internal/astronomy.py index 92d65d32..515d1d57 100644 --- a/app/internal/astronomy.py +++ b/app/internal/astronomy.py @@ -1,4 +1,3 @@ -import asyncio import datetime import functools import httpx From dd221312a64263477cf621846fa52c2634614646 Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sun, 7 Feb 2021 00:21:14 +0200 Subject: [PATCH 20/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3272 -> 3228 bytes tests/test_astronomy.py | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 28a895574376f66e64855017a03ad12fcfa8705d..520151fcc5062f772edfaefaef9e7fec30627e6c 100644 GIT binary patch delta 18 acmX>hIY)BC1a?N7$&=Z0H*0asV*vm_ss=m& delta 28 kcmbOuc|vl-1a@Xy2HVLK*>fi|v4~9G$1b+{ANxEO0EjpVXaE2J diff --git a/tests/test_astronomy.py b/tests/test_astronomy.py index 87000cb6..fc614322 100644 --- a/tests/test_astronomy.py +++ b/tests/test_astronomy.py @@ -41,8 +41,8 @@ async def test_get_astronomical_data(httpx_mock): assert output['Success'] -@pytest.mark.asyncio @respx.mock +@pytest.mark.asyncio async def test_astronomical_data_error_from_api(): requested_date = datetime.datetime(day=4, month=4, year=2021) route = respx.get(ASTRONOMY_URL) @@ -51,8 +51,8 @@ async def test_astronomical_data_error_from_api(): assert not output['Success'] -@pytest.mark.asyncio @respx.mock +@pytest.mark.asyncio async def test_astronomical_exception_from_api(httpx_mock): requested_date = datetime.datetime.now() + datetime.timedelta(days=3) respx.get(ASTRONOMY_URL).mock(return_value=httpx.Response(500)) From 39d91e5615ca9068e0a70c1c670a91fd93ffaa9a Mon Sep 17 00:00:00 2001 From: Hadas Kedar Date: Sun, 7 Feb 2021 00:30:46 +0200 Subject: [PATCH 21/21] feat: astronomy - async support & fixes --- requirements.txt | Bin 3228 -> 3270 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index 520151fcc5062f772edfaefaef9e7fec30627e6c..9038c58fb7649471ef5415d5b4bd408489593893 100644 GIT binary patch delta 20 ccmbOuc}#M{KlaH?EFzQlv5Rf~$3Bk*096+UzW@LL delta 12 TcmX>mIY)BCKlaTU9P?NJBXb1L