Coverage for aixweather/imports/utils_import.py: 87%

61 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-12-31 11:58 +0000

1""" 

2includes a class that reads metadata from weather station 

3""" 

4import warnings 

5 

6from unidecode import unidecode 

7 

8 

9class MetaData: 

10 """ 

11 A class for storing metadata information about a weather station. 

12 

13 Attributes: 

14 station_name (str): The name of the weather station. 

15 station_id (str): The ID (DWD or DWD MOSMIX ID) of the weather station. 

16 altitude (float): The altitude of the weather station in meters. 

17 latitude (float): The latitude of the weather station in degree. 

18 longitude (float): The longitude of the weather station in degree. 

19 timezone (int): The timezone relative to UTC. E.g. -1 is UTC-1, 0 is UTC, etc. 

20 input_source (str): The source of input data for the station. 

21 """ 

22 def __init__(self, **kwargs: str): 

23 self._station_name: str = "UnknownStationName" 

24 self.station_id: str = "UnknownStationID" 

25 self._altitude: float = None 

26 self._latitude: float = None 

27 self._longitude: float = None 

28 self._timezone: int = 0 # Used for export 

29 self._imported_timezone: int = 0 

30 self.input_source: str = "UnknownInputSource" 

31 

32 self.__dict__.update(kwargs) 

33 

34 @property 

35 def station_name(self): 

36 return self._station_name 

37 

38 @station_name.setter 

39 def station_name(self, value): 

40 """avoid special chars""" 

41 self._station_name = unidecode(value) 

42 

43 @property 

44 def altitude(self) -> float: 

45 return self._altitude 

46 

47 @altitude.setter 

48 def altitude(self, value: float) -> None: 

49 self._altitude = round(_ensure_float(value), 5) 

50 

51 @property 

52 def latitude(self) -> float: 

53 return self._latitude 

54 

55 @latitude.setter 

56 def latitude(self, value: float) -> None: 

57 self._latitude = round(_ensure_float(value), 5) 

58 

59 @property 

60 def longitude(self) -> float: 

61 return self._longitude 

62 

63 @longitude.setter 

64 def longitude(self, value: float) -> None: 

65 self._longitude = round(_ensure_float(value), 5) 

66 

67 @property 

68 def timezone(self) -> float: 

69 return self._timezone 

70 

71 @timezone.setter 

72 def timezone(self, value: float) -> None: 

73 _check_timezone_bounds(value) 

74 if value != self._imported_timezone: 

75 warnings.warn( 

76 f"You are changing the imported timezone by {self._imported_timezone - value} hours. " 

77 "Ensure your other simulation input times also use this shift and check results." 

78 ) 

79 self._timezone = value 

80 

81 def set_imported_timezone(self, value: float) -> None: 

82 _check_timezone_bounds(value) 

83 self._timezone = value 

84 self._imported_timezone = value 

85 

86 

87def _check_timezone_bounds(value: float) -> None: 

88 if not isinstance(value, (float, int)): 

89 raise TypeError("Given timezone is not a valid int or float") 

90 if value < -12 or value > 14: 

91 raise ValueError("Given timezone is outside -12 and +14") 

92 

93 

94def _ensure_float(value): 

95 if value is not None: 

96 try: 

97 return float(value) 

98 except: 

99 raise ValueError(f"Value must be of type float, not {type(value)}")