Coverage for lobster/tools/trlc/errors.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-09-22 04:43 +0000

1# LOBSTER - Lightweight Open BMW Software Traceability Evidence Report 

2# Copyright (C) 2025 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) 

3# 

4# This program is free software: you can redistribute it and/or modify 

5# it under the terms of the GNU Affero General Public License as 

6# published by the Free Software Foundation, either version 3 of the 

7# License, or (at your option) any later version. 

8# 

9# This program is distributed in the hope that it will be useful, but 

10# WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

12# Affero General Public License for more details. 

13# 

14# You should have received a copy of the GNU Affero General Public 

15# License along with this program. If not, see 

16# <https://www.gnu.org/licenses/>. 

17 

18from typing import Iterable 

19from trlc import ast 

20 

21 

22class TrlcFailure(Exception): 

23 """Exception if a TRLC API function indicated an error through its return value. 

24 In that case the TRLC message handler should have printed details to stdout, but 

25 these details are not provided through the API return value. 

26 """ 

27 

28 

29class InvalidConversionRuleError(Exception): 

30 """Exception raised when a conversion rule is invalid, e.g., if it does not match 

31 any record type in the TRLC symbol table. 

32 """ 

33 

34 

35# The errors below are usually raised when TRLC data could not be converted to a 

36# LOBSTER item 

37 

38 

39class RecordObjectComponentError(Exception): 

40 """Exception raised when a required component is missing in a RecordObject.""" 

41 

42 def __init__(self, component_name: str, record_object: ast.Record_Object): 

43 super().__init__( 

44 f"Component '{component_name}' not found in TRLC Record_Object " 

45 f"'{record_object.fully_qualified_name()}'!" 

46 ) 

47 self.component_name = component_name 

48 self.record_object = record_object 

49 

50 

51class TupleError(Exception): 

52 """Exception raised for errors related to tuple aggregates.""" 

53 

54 def __init__(self, tuple_aggregate: ast.Tuple_Aggregate, message: str): 

55 super().__init__(message) 

56 self.tuple_aggregate = tuple_aggregate 

57 

58 @staticmethod 

59 def tuple_details(tuple_aggregate: ast.Tuple_Aggregate) -> str: 

60 return f"tuple '{tuple_aggregate.typ.name}' " \ 

61 f"with value '{tuple_aggregate.to_python_object()}', " \ 

62 f"used at {tuple_aggregate.location.to_string()}, " \ 

63 f"defined at {tuple_aggregate.typ.location.to_string()}" 

64 

65 

66class TupleComponentError(TupleError): 

67 """Exception raised when a to-string instruction cannot be applied to a tuple 

68 aggregate because a required component is missing. 

69 

70 This can either be the case if the corresponding Tuple_Type does not have 

71 the required component at all, or if the component is not present (because) 

72 it is optional). 

73 """ 

74 

75 def __init__(self, component_name: str, tuple_aggregate: ast.Tuple_Aggregate): 

76 super().__init__( 

77 tuple_aggregate, 

78 f"Required tuple component " 

79 f"'{component_name}' is missing for " 

80 f"{self.tuple_details(tuple_aggregate)}!", 

81 ) 

82 self.component_name = component_name 

83 

84 

85class TupleToStringMissingError(TupleError): 

86 """Exception raised when a to-string function is missing for a tuple aggregate.""" 

87 

88 def __init__(self, tuple_aggregate: ast.Tuple_Aggregate): 

89 super().__init__( 

90 tuple_aggregate, 

91 f"No 'to-string' function defined for " 

92 f"{self.tuple_details(tuple_aggregate)}!" 

93 ) 

94 

95 

96class TupleToStringFailedError(TupleError): 

97 """Exception raised when all to-string conversion instructions failed to be 

98 applied to a tuple.""" 

99 

100 def __init__( 

101 self, 

102 tuple_aggregate: ast.Tuple_Aggregate, 

103 earlier_errors: Iterable[Exception], 

104 ): 

105 earlier_errors_text = '\n'.join(str(e) for e in earlier_errors) 

106 super().__init__( 

107 tuple_aggregate, 

108 f"All 'to_string' conversion functions failed for " 

109 f"{self.tuple_details(tuple_aggregate)}!\n" 

110 f"The following errors occurred when applying the given functions:\n" 

111 f"{earlier_errors_text}" 

112 ) 

113 self.earlier_errors = earlier_errors