Coverage for rulekit/exceptions.py: 41%

37 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-07 11:26 +0000

1"""Module containing classes for handling exceptions.""" 

2from typing import Any 

3from typing import Callable 

4 

5from jpype import JException 

6 

7 

8class RuleKitJavaException(Exception): 

9 """Wrapper method for handling Java exceptions produced by RuleKit. 

10 Useful for debugging internal Java code error. It allows to access java 

11 stack traces easily. 

12 

13 Example: 

14 >>> from rulekit import RuleKit 

15 >>> from rulekit.classification import RuleClassifier 

16 >>> 

17 >>> clf = RuleClassifier() 

18 >>> try: 

19 >>> clf.fit(X, y) 

20 >>> except JException as e: # catch java exceptions 

21 >>> e = RuleKitJavaException(e) # wrap them for easier handling 

22 >>> e.print_java_stack_trace() # access java stack trace 

23 """ 

24 

25 def __init__(self, java_exception: JException) -> None: 

26 """ 

27 Args: 

28 java_exception (JException): original java exception 

29 """ 

30 self._original_exception: JException = java_exception 

31 self.message: str = java_exception.message() 

32 super().__init__(self.message) 

33 

34 @property 

35 def original_exception(self) -> JException: 

36 """ 

37 Original java exception 

38 Returns: 

39 JException: original java exception 

40 """ 

41 return self._original_exception 

42 

43 def print_java_stack_trace(self) -> None: 

44 """Prints java exception stack trace.""" 

45 print(self.original_exception.stacktrace()) 

46 

47 

48class RuleKitMisconfigurationException(Exception): 

49 """Exception indicating that some RuleKit parameters are misconfigured - 

50 their values were not correctly passed to java code. 

51 """ 

52 

53 def __init__( 

54 self, 

55 java_parameters: dict[str, Any], 

56 python_parameters: dict[str, Any] 

57 ) -> None: 

58 

59 super().__init__( 

60 self._prepare_message(java_parameters, python_parameters) 

61 ) 

62 self._java_parameters: dict[str, Any] = java_parameters 

63 self._python_parameters: dict[str, Any] = python_parameters 

64 

65 def _prepare_message( 

66 self, 

67 java_parameters: dict[str, Any], 

68 python_parameters: dict[str, Any] 

69 ) -> str: 

70 combined_keys: set[str] = set( 

71 java_parameters.keys()) | set(python_parameters.keys()) 

72 params_lines: list[str] = [] 

73 for key in combined_keys: 

74 java_value = java_parameters.get(key) 

75 python_value = python_parameters.get(key) 

76 line: str = f' {key}: ({java_value}, {python_value}),' 

77 # skip check for user defined measures 

78 skip_check: bool = isinstance(python_value, Callable) 

79 if java_value != python_value and not skip_check: 

80 line = f'{line} <-- **DIFFERENT**' 

81 params_lines.append(line) 

82 message: str = ( 

83 'RuleKit parameters configuration error' + 

84 'RuleGenerator parameters configured in Java do not' + 

85 'match with given parameters\n\n' + 

86 'Parameters (first value is in Java, second is in Python):\n{\n' + 

87 '\n'.join(params_lines) + 

88 '\n}' 

89 ) 

90 return message 

91 

92 @property 

93 def java_parameters(self) -> dict[str, Any]: 

94 """ 

95 Configured operator parameters values extracted from java 

96 Returns: 

97 dict[str, Any]: parameters 

98 """ 

99 return self._java_parameters 

100 

101 @property 

102 def python_parameters(self) -> dict[str, Any]: 

103 """ 

104 Operator parameters passed to the python operator class 

105 Returns: 

106 dict[str, Any]: parameters 

107 """ 

108 return self._python_parameters