Coverage for pybeepop/exceptions.py: 100%

19 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-30 13:34 +0000

1""" 

2Custom exceptions for PyBeePop with enhanced error reporting. 

3 

4This module provides custom exception classes that automatically include BeePop+ 

5internal error logs in exception messages, providing better diagnostic information 

6without requiring manual log retrieval. 

7""" 

8 

9 

10class BeepopException(Exception): 

11 """ 

12 Base exception for PyBeePop errors with enhanced error reporting. 

13 

14 Automatically includes BeePop+ error log and info log for better diagnostics. 

15 This exception captures engine-specific error information and formats it 

16 into a comprehensive error message. 

17 

18 Attributes: 

19 message (str): The primary error message 

20 error_log (str): BeePop+ error log content 

21 info_log (str): BeePop+ info log content 

22 engine_type (str): Engine that raised the error ('cpp' or 'python') 

23 

24 Example: 

25 >>> raise BeepopException( 

26 ... "Simulation failed", 

27 ... error_log="Invalid parameter: SimStart", 

28 ... engine_type="python" 

29 ... ) 

30 BeepopException: Simulation failed 

31 

32 BeePop+ Error Log (python engine): 

33 Invalid parameter: SimStart 

34 """ 

35 

36 def __init__( 

37 self, 

38 message: str, 

39 error_log: str = "", 

40 info_log: str = "", 

41 engine_type: str = "", 

42 ): 

43 """ 

44 Initialize BeepopException with message and optional logs. 

45 

46 Args: 

47 message: Primary error message 

48 error_log: BeePop+ error log content (optional) 

49 info_log: BeePop+ info log content (optional) 

50 engine_type: Engine that raised the error (optional) 

51 """ 

52 self.message = message 

53 self.error_log = error_log 

54 self.info_log = info_log 

55 self.engine_type = engine_type 

56 

57 # Build comprehensive error message 

58 full_message = message 

59 

60 # Add error log if available and non-empty 

61 if error_log and error_log.strip(): 

62 engine_label = f" ({engine_type} engine)" if engine_type else "" 

63 full_message += f"\n\nBeePop+ Error Log{engine_label}:\n{error_log.strip()}" 

64 

65 # Add info log if available and non-empty (usually less critical) 

66 if info_log and info_log.strip(): 

67 full_message += f"\n\nBeePop+ Info Log:\n{info_log.strip()}" 

68 

69 super().__init__(full_message) 

70 

71 

72class BeepopParameterError(BeepopException, ValueError): 

73 """ 

74 Invalid parameter name or value. 

75 

76 Raised when a parameter name is not recognized or a parameter value 

77 is invalid. Inherits from both BeepopException (for enhanced logging) 

78 and ValueError (for standard exception compatibility). 

79 

80 This dual inheritance ensures: 

81 - isinstance(e, ValueError) returns True (backward compatible) 

82 - isinstance(e, BeepopException) returns True (can catch all BeePop errors) 

83 - Error logs are automatically included in the message 

84 

85 Example: 

86 >>> model = PyBeePop(engine='python') 

87 >>> model.set_parameters({"InvalidParam": "123"}) 

88 BeepopParameterError: InvalidParam is not a valid parameter. 

89 

90 BeePop+ Error Log (python engine): 

91 Parameter 'InvalidParam' not found in valid parameter list. 

92 Expected one of: ICWorkerAdults, SimStart, SimEnd, ... 

93 """ 

94 

95 pass 

96 

97 

98class BeepopRuntimeError(BeepopException, RuntimeError): 

99 """ 

100 Error during BeePop+ operation. 

101 

102 Raised when a BeePop+ operation fails at runtime (e.g., simulation fails, 

103 file loading fails, parameter setting fails). Inherits from both 

104 BeepopException (for enhanced logging) and RuntimeError (for standard 

105 exception compatibility). 

106 

107 This dual inheritance ensures: 

108 - isinstance(e, RuntimeError) returns True (backward compatible) 

109 - isinstance(e, BeepopException) returns True (can catch all BeePop errors) 

110 - Error logs are automatically included in the message 

111 

112 Example: 

113 >>> model = PyBeePop(engine='python') 

114 >>> model.run_model() # No weather loaded 

115 BeepopRuntimeError: Weather must be set before running simulation 

116 

117 BeePop+ Error Log (python engine): 

118 Attempted to run simulation without weather data. 

119 Call load_weather() or pass weather_file to constructor. 

120 """ 

121 

122 pass 

123 

124 

125class BeepopFileError(BeepopException, OSError): 

126 """ 

127 Error reading or parsing input file. 

128 

129 Raised when a file cannot be opened, read, or parsed correctly. 

130 Inherits from both BeepopException (for enhanced logging) and OSError 

131 (for standard exception compatibility). 

132 

133 This dual inheritance ensures: 

134 - isinstance(e, OSError) returns True (backward compatible) 

135 - isinstance(e, BeepopException) returns True (can catch all BeePop errors) 

136 - Error logs are automatically included in the message 

137 

138 Example: 

139 >>> model = PyBeePop(engine='python') 

140 >>> model.load_weather("corrupted_weather.txt") 

141 BeepopFileError: Weather file is invalid. 

142 

143 BeePop+ Error Log (python engine): 

144 Failed to parse weather file at line 15. 

145 Expected format: Date,MaxTemp,MinTemp,AvgTemp,Windspeed,Rain,Daylight 

146 Got: 06/15/2020,invalid_data 

147 """ 

148 

149 pass