Skip to content

Commit

Permalink
refactor: implement DRY principle in unit usage
Browse files Browse the repository at this point in the history
  • Loading branch information
null8626 committed Oct 28, 2024
1 parent 7e837ef commit 8a6f20d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 34 deletions.
26 changes: 8 additions & 18 deletions python_weather/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from enum import auto, Enum

from .enums import WindDirection, Kind, Locale, Ultraviolet
from .constants import METRIC, VALID_UNITS
from .constants import _Unit

class CustomizableBase:
__slots__ = ('__unit', '__locale')
Expand Down Expand Up @@ -56,7 +56,7 @@ def unit(self, to: auto):
If the ``to`` argument is not either :attr:`METRIC` or :attr:`IMPERIAL`.
"""

if to not in VALID_UNITS:
if not isinstance(to, _Unit):
raise Error('Invalid measuring unit specified!')

self.__unit = to
Expand Down Expand Up @@ -107,8 +107,7 @@ def feels_like(self) -> int:
""":class:`int`: What it felt like, in Celcius or Fahrenheit."""

return int(
self.__inner[
f'FeelsLike{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self.__inner[f'FeelsLike{self._CustomizableBase__unit.temperature}']
)

@property
Expand All @@ -121,47 +120,38 @@ def humidity(self) -> int:
def temperature(self) -> int:
""":class:`int`: The weather temperature in either Celcius or Fahrenheit."""

return int(
self.
__inner[f'temp_{"C" if self._CustomizableBase__unit == METRIC else "F"}']
)
return int(self.__inner[f'temp_{self._CustomizableBase__unit.temperature}'])

@property
def precipitation(self) -> float:
""":class:`float`: The precipitation in either Millimeters or Inches."""

return float(
self.__inner[
f'precip{"MM" if self._CustomizableBase__unit == METRIC else "Inches"}']
self.__inner[f'precip{self._CustomizableBase__unit.precipitation}']
)

@property
def pressure(self) -> float:
""":class:`float`: The pressure in either Pascal or Inches."""

return float(
self.__inner[
f'pressure{"" if self._CustomizableBase__unit == METRIC else "Inches"}']
self.__inner[f'pressure{self._CustomizableBase__unit.pressure}']
)

@property
def visibility(self) -> int:
""":class:`int`: The visibility distance in either Kilometers or Miles."""

return int(
self.__inner[
f'visibility{"" if self._CustomizableBase__unit == METRIC else "Miles"}'
]
self.__inner[f'visibility{self._CustomizableBase__unit.visibility}']
)

@property
def wind_speed(self) -> int:
""":class:`int`: The wind speeds in either Kilometers per hour or Miles per hour."""

return int(
self.__inner[
f'windspeed{"Kmph" if self._CustomizableBase__unit == METRIC else "Miles"}'
]
self.__inner[f'windspeed{self._CustomizableBase__unit.velocity}']
)

@property
Expand Down
4 changes: 2 additions & 2 deletions python_weather/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from asyncio import sleep
from enum import auto

from .constants import METRIC, VALID_UNITS
from .constants import _Unit, METRIC
from .base import CustomizableBase
from .forecast import Weather
from .errors import Error
Expand Down Expand Up @@ -115,7 +115,7 @@ async def get(
elif self.__session.closed:
raise Error('Client is already closed')

if unit not in VALID_UNITS:
if not isinstance(unit, _Unit):
unit = self._CustomizableBase__unit

if not isinstance(locale, Locale):
Expand Down
31 changes: 28 additions & 3 deletions python_weather/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,36 @@
SOFTWARE.
"""

from typing import Union
from re import compile
from enum import auto

METRIC = auto()
IMPERIAL = auto()
class _Unit:
__slots__ = (
'temperature', 'velocity', 'pressure', 'precipitation', 'visibility',
'cm_divisor'
)

def __init__(
self,
temperature: str,
velocity: str,
pressure: str,
precipitation: str,
visibility: str,
cm_divisor: Union[int, float],
):
self.temperature = temperature
self.velocity = velocity
self.pressure = pressure
self.precipitation = precipitation
self.visibility = visibility
self.cm_divisor = cm_divisor

def __repr__(self) -> str:
return f'<Unit [{self.temperature}, {self.velocity}]>'

METRIC = _Unit('C', 'Kmph', '', 'MM', '', 1)
IMPERIAL = _Unit('F', 'Miles', 'Inches', 'Inches', 'Miles', 2.54)

LATLON_REGEX = compile(r'^Lat (\-?[\d\.]+) and Lon (\-?[\d\.]+)$')
VALID_UNITS = (METRIC, IMPERIAL)
23 changes: 12 additions & 11 deletions python_weather/forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
from datetime import datetime, date, time
from enum import auto

from .enums import Phase, Locale
from .constants import LATLON_REGEX, METRIC
from .base import BaseForecast, CustomizableBase
from .constants import LATLON_REGEX
from .enums import Phase, Locale

class Area:
"""Represents the location of the weather forecast."""
Expand Down Expand Up @@ -182,30 +182,30 @@ def dew_point(self) -> int:
""":class:`int`: The dew point in either Celcius or Fahrenheit."""

return int(
self._BaseForecast__inner[f'DewPoint{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self._BaseForecast__inner[f'DewPoint{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
def heat_index(self) -> int:
""":class:`int`: The heat index in either Celcius or Fahrenheit."""

return int(
self._BaseForecast__inner[f'HeatIndex{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self._BaseForecast__inner[f'HeatIndex{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
def wind_chill(self) -> int:
""":class:`int`: The wind chill value in either Celcius or Fahrenheit."""

return int(
self._BaseForecast__inner[f'WindChill{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self._BaseForecast__inner[f'WindChill{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
def wind_gust(self) -> int:
""":class:`int`: The wind gust value in either Kilometers per hour or Miles per hour."""

key = f'WindGust{"Kmph" if self._CustomizableBase__unit == METRIC else "Miles"}'
key = f'WindGust{self._CustomizableBase__unit.velocity}'
return int(self._BaseForecast__inner[key])

@property
Expand Down Expand Up @@ -310,23 +310,23 @@ def lowest_temperature(self) -> int:
""":class:`int`: The lowest temperature in either Celcius or Fahrenheit."""

return int(
self.__inner[f'mintemp{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self.__inner[f'mintemp{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
def highest_temperature(self) -> int:
""":class:`int`: The highest temperature in either Celcius or Fahrenheit."""

return int(
self.__inner[f'maxtemp{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self.__inner[f'maxtemp{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
def temperature(self) -> int:
""":class:`int`: The average temperature in either Celcius or Fahrenheit."""

return int(
self.__inner[f'avgtemp{"C" if self._CustomizableBase__unit == METRIC else "F"}']
self.__inner[f'avgtemp{self._CustomizableBase__unit.temperature}']
) # yapf: disable

@property
Expand All @@ -339,8 +339,9 @@ def sunlight(self) -> float:
def snowfall(self) -> float:
""":class:`float`: Total snowfall in either Centimeters or Inches."""

width = float(self.__inner['totalSnow_cm'])
return width if self._CustomizableBase__unit == METRIC else width / 2.54
return float(
self.__inner['totalSnow_cm']
) / self._CustomizableBase__unit.cm_divisor

@property
def hourly(self) -> Iterable[HourlyForecast]:
Expand Down

0 comments on commit 8a6f20d

Please sign in to comment.