API & Client - remove DarkSky weather provider
This commit is contained in:
parent
ef65689263
commit
642b15d521
@ -9,7 +9,6 @@ from gpxpy.gpx import GPXTrackPoint
|
|||||||
|
|
||||||
from fittrackee.tests.mixins import CallArgsMixin
|
from fittrackee.tests.mixins import CallArgsMixin
|
||||||
from fittrackee.tests.utils import random_string
|
from fittrackee.tests.utils import random_string
|
||||||
from fittrackee.workouts.utils.weather.dark_sky import DarkSky
|
|
||||||
from fittrackee.workouts.utils.weather.visual_crossing import VisualCrossing
|
from fittrackee.workouts.utils.weather.visual_crossing import VisualCrossing
|
||||||
from fittrackee.workouts.utils.weather.weather_service import WeatherService
|
from fittrackee.workouts.utils.weather.weather_service import WeatherService
|
||||||
|
|
||||||
@ -55,82 +54,6 @@ class WeatherTestCase:
|
|||||||
return GPXTrackPoint(latitude=48.866667, longitude=2.333333, time=time)
|
return GPXTrackPoint(latitude=48.866667, longitude=2.333333, time=time)
|
||||||
|
|
||||||
|
|
||||||
class TestDarksky(WeatherTestCase):
|
|
||||||
def test_it_calls_forecast_io_with_datetime_in_utc_when_naive_datetime_is_provided( # noqa
|
|
||||||
self,
|
|
||||||
) -> None:
|
|
||||||
naive_point_time = datetime(
|
|
||||||
year=2022, month=6, day=11, hour=10, minute=23, second=00
|
|
||||||
)
|
|
||||||
point = self.get_gpx_point(naive_point_time)
|
|
||||||
darksky = DarkSky(api_key=self.api_key)
|
|
||||||
with patch(
|
|
||||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
|
||||||
) as forecast_io_mock:
|
|
||||||
darksky.get_weather(point)
|
|
||||||
|
|
||||||
forecast_io_mock.load_forecast.assert_called_with(
|
|
||||||
self.api_key,
|
|
||||||
point.latitude,
|
|
||||||
point.longitude,
|
|
||||||
time=datetime(
|
|
||||||
year=2022,
|
|
||||||
month=6,
|
|
||||||
day=11,
|
|
||||||
hour=10,
|
|
||||||
minute=23,
|
|
||||||
second=00,
|
|
||||||
tzinfo=pytz.utc,
|
|
||||||
),
|
|
||||||
units='si',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_it_calls_forecast_io_with_provided_datetime_when_with_timezone(
|
|
||||||
self,
|
|
||||||
) -> None:
|
|
||||||
paris_point_time = datetime(
|
|
||||||
year=2022,
|
|
||||||
month=6,
|
|
||||||
day=11,
|
|
||||||
hour=10,
|
|
||||||
minute=23,
|
|
||||||
second=00,
|
|
||||||
).astimezone(pytz.timezone('Europe/Paris'))
|
|
||||||
point = self.get_gpx_point(paris_point_time)
|
|
||||||
darksky = DarkSky(api_key=self.api_key)
|
|
||||||
with patch(
|
|
||||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
|
||||||
) as forecast_io_mock:
|
|
||||||
darksky.get_weather(point)
|
|
||||||
|
|
||||||
forecast_io_mock.load_forecast.assert_called_with(
|
|
||||||
self.api_key,
|
|
||||||
point.latitude,
|
|
||||||
point.longitude,
|
|
||||||
time=paris_point_time,
|
|
||||||
units='si',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_it_returns_forecast_currently_data(self) -> None:
|
|
||||||
darksky = DarkSky(api_key=self.api_key)
|
|
||||||
with patch(
|
|
||||||
'fittrackee.workouts.utils.weather.dark_sky.forecastio'
|
|
||||||
) as forecast_io_mock:
|
|
||||||
forecast_io_mock.load_forecast().currently.return_value = sentinel
|
|
||||||
|
|
||||||
weather_data = darksky.get_weather(
|
|
||||||
self.get_gpx_point(datetime.utcnow())
|
|
||||||
)
|
|
||||||
|
|
||||||
assert weather_data == {
|
|
||||||
'icon': sentinel.icon,
|
|
||||||
'temperature': sentinel.temperature,
|
|
||||||
'humidity': sentinel.humidity,
|
|
||||||
'wind': sentinel.windSpeed,
|
|
||||||
'windBearing': sentinel.windBearing,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TestVisualCrossingGetTimestamp(WeatherTestCase):
|
class TestVisualCrossingGetTimestamp(WeatherTestCase):
|
||||||
def test_it_returns_expected_timestamp_as_integer(self) -> None:
|
def test_it_returns_expected_timestamp_as_integer(self) -> None:
|
||||||
time = datetime.utcnow()
|
time = datetime.utcnow()
|
||||||
@ -246,9 +169,10 @@ class TestWeatherService(WeatherTestCase):
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'input_api_key,input_provider',
|
'input_api_key,input_provider',
|
||||||
[
|
[
|
||||||
('', 'darksky'),
|
('', 'visualcrossing'),
|
||||||
('valid_api_key', ''),
|
('valid_api_key', ''),
|
||||||
('valid_api_key', 'invalid_provider'),
|
('valid_api_key', 'invalid_provider'),
|
||||||
|
('valid_api_key', 'darksky'), # removed provider
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_weather_api_is_none_when_configuration_is_invalid(
|
def test_weather_api_is_none_when_configuration_is_invalid(
|
||||||
@ -264,22 +188,6 @@ class TestWeatherService(WeatherTestCase):
|
|||||||
|
|
||||||
assert weather_service.weather_api is None
|
assert weather_service.weather_api is None
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
'input_provider',
|
|
||||||
['darksky', 'DARKSKY'],
|
|
||||||
)
|
|
||||||
def test_weather_api_is_darksky_when_configured(
|
|
||||||
self,
|
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
|
||||||
input_provider: str,
|
|
||||||
) -> None:
|
|
||||||
monkeypatch.setenv('WEATHER_API_KEY', 'valid_api_key')
|
|
||||||
monkeypatch.setenv('WEATHER_API_PROVIDER', input_provider)
|
|
||||||
|
|
||||||
weather_service = WeatherService()
|
|
||||||
|
|
||||||
assert isinstance(weather_service.weather_api, DarkSky)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'input_provider',
|
'input_provider',
|
||||||
['visualcrossing', 'VisualCrossing'],
|
['visualcrossing', 'VisualCrossing'],
|
||||||
@ -307,7 +215,7 @@ class TestWeatherService(WeatherTestCase):
|
|||||||
|
|
||||||
def test_it_returns_none_when_point_time_is_none(self) -> None:
|
def test_it_returns_none_when_point_time_is_none(self) -> None:
|
||||||
weather_service = WeatherService()
|
weather_service = WeatherService()
|
||||||
weather_service.weather_api = DarkSky('api_key')
|
weather_service.weather_api = VisualCrossing('api_key')
|
||||||
point = self.get_gpx_point(None)
|
point = self.get_gpx_point(None)
|
||||||
|
|
||||||
weather_data = weather_service.get_weather(point)
|
weather_data = weather_service.get_weather(point)
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
from typing import Dict, Optional
|
|
||||||
|
|
||||||
import forecastio
|
|
||||||
import pytz
|
|
||||||
|
|
||||||
from .base_weather import BaseWeather
|
|
||||||
|
|
||||||
|
|
||||||
class DarkSky(BaseWeather):
|
|
||||||
# Deprecated (API will end on March 31st, 2023)
|
|
||||||
|
|
||||||
def _get_data(
|
|
||||||
self, latitude: float, longitude: float, time: datetime
|
|
||||||
) -> Optional[Dict]:
|
|
||||||
# get point time in UTC
|
|
||||||
point_time = (
|
|
||||||
pytz.utc.localize(time)
|
|
||||||
if time.tzinfo is None # naive datetime
|
|
||||||
else time
|
|
||||||
)
|
|
||||||
|
|
||||||
forecast = forecastio.load_forecast(
|
|
||||||
self.api_key,
|
|
||||||
latitude,
|
|
||||||
longitude,
|
|
||||||
time=point_time,
|
|
||||||
units='si',
|
|
||||||
)
|
|
||||||
weather = forecast.currently()
|
|
||||||
return {
|
|
||||||
'humidity': weather.humidity,
|
|
||||||
'icon': weather.icon,
|
|
||||||
'temperature': weather.temperature,
|
|
||||||
'wind': weather.windSpeed,
|
|
||||||
'windBearing': weather.windBearing,
|
|
||||||
}
|
|
@ -5,14 +5,12 @@ from gpxpy.gpx import GPXTrackPoint
|
|||||||
|
|
||||||
from fittrackee import appLog
|
from fittrackee import appLog
|
||||||
|
|
||||||
from .dark_sky import DarkSky
|
|
||||||
from .visual_crossing import VisualCrossing
|
from .visual_crossing import VisualCrossing
|
||||||
|
|
||||||
|
|
||||||
class WeatherService:
|
class WeatherService:
|
||||||
"""
|
"""
|
||||||
Available API:
|
Available API:
|
||||||
- DarkSky (deprecated, will end on March 31st, 2023)
|
|
||||||
- VisualCrossing
|
- VisualCrossing
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -20,7 +18,7 @@ class WeatherService:
|
|||||||
self.weather_api = self._get_weather_api()
|
self.weather_api = self._get_weather_api()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_weather_api() -> Union[DarkSky, VisualCrossing, None]:
|
def _get_weather_api() -> Union[VisualCrossing, None]:
|
||||||
weather_api_key: str = os.getenv('WEATHER_API_KEY', '')
|
weather_api_key: str = os.getenv('WEATHER_API_KEY', '')
|
||||||
weather_api_provider: str = os.getenv(
|
weather_api_provider: str = os.getenv(
|
||||||
'WEATHER_API_PROVIDER', ''
|
'WEATHER_API_PROVIDER', ''
|
||||||
@ -28,8 +26,6 @@ class WeatherService:
|
|||||||
|
|
||||||
if not weather_api_key:
|
if not weather_api_key:
|
||||||
return None
|
return None
|
||||||
if weather_api_provider == 'darksky': # deprecated
|
|
||||||
return DarkSky(weather_api_key)
|
|
||||||
if weather_api_provider == 'visualcrossing':
|
if weather_api_provider == 'visualcrossing':
|
||||||
return VisualCrossing(weather_api_key)
|
return VisualCrossing(weather_api_key)
|
||||||
return None
|
return None
|
||||||
|
@ -75,10 +75,6 @@
|
|||||||
|
|
||||||
function get_weather_provider() {
|
function get_weather_provider() {
|
||||||
const weather_provider: Record<string, string> = {}
|
const weather_provider: Record<string, string> = {}
|
||||||
if (appConfig.value.weather_provider === 'darksky') {
|
|
||||||
weather_provider['name'] = 'Dark Sky'
|
|
||||||
weather_provider['url'] = 'https://darksky.net'
|
|
||||||
}
|
|
||||||
if (appConfig.value.weather_provider === 'visualcrossing') {
|
if (appConfig.value.weather_provider === 'visualcrossing') {
|
||||||
weather_provider['name'] = 'Visual Crossing'
|
weather_provider['name'] = 'Visual Crossing'
|
||||||
weather_provider['url'] = 'https://www.visualcrossing.com'
|
weather_provider['url'] = 'https://www.visualcrossing.com'
|
||||||
|
53
poetry.lock
generated
53
poetry.lock
generated
@ -1944,21 +1944,6 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
six = ">=1.5"
|
six = ">=1.5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "python-forecastio"
|
|
||||||
version = "1.4.0"
|
|
||||||
description = "A thin Python Wrapper for the Dark Sky (formerly Forecast.io) weather API"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "python-forecastio-1.4.0.tar.gz", hash = "sha256:144419d65e3b46961f38853f959a91f6e6cfa9e6d5b6f47aa9dc5e431471d454"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
requests = ">=1.6"
|
|
||||||
responses = "*"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytz"
|
name = "pytz"
|
||||||
version = "2023.3"
|
version = "2023.3"
|
||||||
@ -1975,7 +1960,7 @@ files = [
|
|||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
version = "6.0"
|
version = "6.0"
|
||||||
description = "YAML parser and emitter for Python"
|
description = "YAML parser and emitter for Python"
|
||||||
category = "main"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@ -2081,28 +2066,6 @@ urllib3 = ">=1.21.1,<1.27"
|
|||||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "responses"
|
|
||||||
version = "0.23.1"
|
|
||||||
description = "A utility library for mocking out the `requests` Python library."
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "responses-0.23.1-py3-none-any.whl", hash = "sha256:8a3a5915713483bf353b6f4079ba8b2a29029d1d1090a503c70b0dc5d9d0c7bd"},
|
|
||||||
{file = "responses-0.23.1.tar.gz", hash = "sha256:c4d9aa9fc888188f0c673eff79a8dadbe2e75b7fe879dc80a221a06e0a68138f"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pyyaml = "*"
|
|
||||||
requests = ">=2.22.0,<3.0"
|
|
||||||
types-PyYAML = "*"
|
|
||||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
urllib3 = ">=1.25.10"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-requests"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "13.3.3"
|
version = "13.3.3"
|
||||||
@ -2650,18 +2613,6 @@ files = [
|
|||||||
{file = "types_pytz-2023.3.0.0-py3-none-any.whl", hash = "sha256:4fc2a7fbbc315f0b6630e0b899fd6c743705abe1094d007b0e612d10da15e0f3"},
|
{file = "types_pytz-2023.3.0.0-py3-none-any.whl", hash = "sha256:4fc2a7fbbc315f0b6630e0b899fd6c743705abe1094d007b0e612d10da15e0f3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "types-pyyaml"
|
|
||||||
version = "6.0.12.9"
|
|
||||||
description = "Typing stubs for PyYAML"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "types-PyYAML-6.0.12.9.tar.gz", hash = "sha256:c51b1bd6d99ddf0aa2884a7a328810ebf70a4262c292195d3f4f9a0005f9eeb6"},
|
|
||||||
{file = "types_PyYAML-6.0.12.9-py3-none-any.whl", hash = "sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "types-redis"
|
name = "types-redis"
|
||||||
version = "4.5.4.1"
|
version = "4.5.4.1"
|
||||||
@ -2886,4 +2837,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
content-hash = "a2bb6c51cd1e0e3cc88e09ec8c598109b2fab9b1cfbdccf73e95496577959710"
|
content-hash = "2a735d57527529962e3b55820d8e236d14399f077247ff208a8507838d1bcbec"
|
||||||
|
@ -39,7 +39,6 @@ humanize = "^4.6"
|
|||||||
psycopg2-binary = "^2.9"
|
psycopg2-binary = "^2.9"
|
||||||
pyjwt = "^2.6"
|
pyjwt = "^2.6"
|
||||||
pyopenssl = "^23.0"
|
pyopenssl = "^23.0"
|
||||||
python-forecastio = "^1.4"
|
|
||||||
pytz = "^2023.3"
|
pytz = "^2023.3"
|
||||||
shortuuid = "^1.0.11"
|
shortuuid = "^1.0.11"
|
||||||
staticmap = "^0.5.5"
|
staticmap = "^0.5.5"
|
||||||
|
Loading…
Reference in New Issue
Block a user