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 Nov 1, 2023
1 parent 2c3d848 commit 55b277b
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 25 deletions.
16 changes: 8 additions & 8 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 @@ -108,7 +108,7 @@ def feels_like(self) -> int:

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

@property
Expand All @@ -123,7 +123,7 @@ def temperature(self) -> int:

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

@property
Expand All @@ -132,7 +132,7 @@ def precipitation(self) -> float:

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

@property
Expand All @@ -141,7 +141,7 @@ def pressure(self) -> float:

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

@property
Expand All @@ -150,7 +150,7 @@ def visibility(self) -> int:

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

Expand All @@ -160,7 +160,7 @@ def wind_speed(self) -> int:

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

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
30 changes: 26 additions & 4 deletions python_weather/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,33 @@
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}]>'

LATLON_REGEX = compile(r'^Lat (\-?[\d\.]+) and Lon (\-?[\d\.]+)$')
VALID_UNITS = (METRIC, IMPERIAL)
METRIC = _Unit('C', 'Kmph', '', 'MM', '', 1)
IMPERIAL = _Unit('F', 'Miles', 'Inches', 'Inches', 'Miles', 2.54)

LATLON_REGEX = compile(r'^Lat (\-?[\d\.]+) and Lon (\-?[\d\.]+)$')
21 changes: 10 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,7 @@ 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 55b277b

Please sign in to comment.