Skip to content

Commit 77282f4

Browse files
spywogangatp
andauthored
Add getter methods of the python exception class (#230)
* Add getter methods of the python exception class The code and message should be able to return. It keeps consistent with the API of C++. The naming conversion is also followed with ACT implementation rather than python PEP 8. * Add additional methods * Add properties for the exception class It ensures Cross-Language Consistency. C++: Uses methods (getErrorCode()) C#: Uses properties (ErrorCode) Java: Uses methods (getErrorCode()) Python: Can support both patterns Meanwhile, rename the methods to comply with PEP 8 * Test the exception in python --------- Co-authored-by: gangatp <[email protected]>
1 parent 16e36db commit 77282f4

File tree

3 files changed

+176
-1
lines changed

3 files changed

+176
-1
lines changed

Examples/RTTI/RTTI_component/Bindings/Python/RTTI.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,80 @@ def __str__(self):
3232
if self._message:
3333
return 'RTTIException ' + str(self._code) + ': '+ str(self._message)
3434
return 'RTTIException ' + str(self._code)
35+
36+
def get_error_code(self):
37+
"""Returns the error code"""
38+
return self._code
39+
40+
def get_error_message(self):
41+
"""Returns the custom error message"""
42+
return self._message
43+
44+
def get_error_name(self):
45+
"""Returns the error name (constant name)"""
46+
if self._code == ErrorCodes.SUCCESS:
47+
return 'SUCCESS'
48+
elif self._code == ErrorCodes.NOTIMPLEMENTED:
49+
return 'NOTIMPLEMENTED'
50+
elif self._code == ErrorCodes.INVALIDPARAM:
51+
return 'INVALIDPARAM'
52+
elif self._code == ErrorCodes.INVALIDCAST:
53+
return 'INVALIDCAST'
54+
elif self._code == ErrorCodes.BUFFERTOOSMALL:
55+
return 'BUFFERTOOSMALL'
56+
elif self._code == ErrorCodes.GENERICEXCEPTION:
57+
return 'GENERICEXCEPTION'
58+
elif self._code == ErrorCodes.COULDNOTLOADLIBRARY:
59+
return 'COULDNOTLOADLIBRARY'
60+
elif self._code == ErrorCodes.COULDNOTFINDLIBRARYEXPORT:
61+
return 'COULDNOTFINDLIBRARYEXPORT'
62+
elif self._code == ErrorCodes.INCOMPATIBLEBINARYVERSION:
63+
return 'INCOMPATIBLEBINARYVERSION'
64+
else:
65+
return 'UNKNOWN'
66+
67+
def get_error_description(self):
68+
"""Returns the error description (human-readable)"""
69+
if self._code == ErrorCodes.SUCCESS:
70+
return 'success'
71+
elif self._code == ErrorCodes.NOTIMPLEMENTED:
72+
return 'functionality not implemented'
73+
elif self._code == ErrorCodes.INVALIDPARAM:
74+
return 'an invalid parameter was passed'
75+
elif self._code == ErrorCodes.INVALIDCAST:
76+
return 'a type cast failed'
77+
elif self._code == ErrorCodes.BUFFERTOOSMALL:
78+
return 'a provided buffer is too small'
79+
elif self._code == ErrorCodes.GENERICEXCEPTION:
80+
return 'a generic exception occurred'
81+
elif self._code == ErrorCodes.COULDNOTLOADLIBRARY:
82+
return 'the library could not be loaded'
83+
elif self._code == ErrorCodes.COULDNOTFINDLIBRARYEXPORT:
84+
return 'a required exported symbol could not be found in the library'
85+
elif self._code == ErrorCodes.INCOMPATIBLEBINARYVERSION:
86+
return 'the version of the binary interface does not match the bindings interface'
87+
else:
88+
return 'unknown error'
89+
90+
@property
91+
def error_code(self):
92+
"""Property to access error code"""
93+
return self._code
94+
95+
@property
96+
def error_message(self):
97+
"""Property to access custom error message"""
98+
return self._message
99+
100+
@property
101+
def error_name(self):
102+
"""Property to access error name"""
103+
return self.get_error_name()
104+
105+
@property
106+
def error_description(self):
107+
"""Property to access error description"""
108+
return self.get_error_description()
35109

36110
'''Definition of binding API version
37111
'''

Examples/RTTI/RTTI_component/Examples/Python/RTTI_Example.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,43 @@
2020
import RTTI
2121

2222

23+
def test_exception_methods():
24+
"""Test the new exception methods using assert statements"""
25+
print("Testing RTTI Exception Methods...")
26+
27+
# Test with a non-existent library to trigger an exception
28+
try:
29+
wrapper = RTTI.Wrapper(libraryName="nonexistent_library")
30+
assert False, "Should have thrown an exception!"
31+
except RTTI.ERTTIException as e:
32+
print("+ Successfully caught ERTTIException")
33+
34+
# Test the new methods with assertions
35+
error_code = e.get_error_code()
36+
error_message = e.get_error_message()
37+
error_name = e.get_error_name()
38+
error_description = e.get_error_description()
39+
40+
# Assertions for method functionality
41+
assert error_code == RTTI.ErrorCodes.COULDNOTLOADLIBRARY, f"Expected error code 6, got {error_code}"
42+
assert error_name == "COULDNOTLOADLIBRARY", f"Expected 'COULDNOTLOADLIBRARY', got '{error_name}'"
43+
assert error_description == "the library could not be loaded", f"Expected library load error description, got '{error_description}'"
44+
assert "nonexistent_library" in error_message, f"Expected library name in message, got '{error_message}'"
45+
46+
# Test properties (alternative access)
47+
assert e.error_code == error_code, "Property error_code should match method get_error_code()"
48+
assert e.error_message == error_message, "Property error_message should match method get_error_message()"
49+
assert e.error_name == error_name, "Property error_name should match method get_error_name()"
50+
assert e.error_description == error_description, "Property error_description should match method get_error_description()"
51+
52+
# Test string representation
53+
exception_str = str(e)
54+
assert "RTTIException" in exception_str, f"String representation should contain 'RTTIException', got '{exception_str}'"
55+
assert str(error_code) in exception_str, f"String representation should contain error code, got '{exception_str}'"
56+
57+
print("+ All exception method tests passed!")
58+
59+
2360
def main():
2461
libpath = '' # TODO add the location of the shared library binary here
2562
wrapper = RTTI.Wrapper(libraryName = os.path.join(libpath, "rtti"))
@@ -96,7 +133,21 @@ def main():
96133
animal = iter.GetNextAnimal(); assert not animal
97134

98135
if __name__ == "__main__":
136+
# Test exception methods first (before main, as it uses a non-existent library)
137+
print("Testing Exception Methods:")
138+
print("-" * 30)
139+
test_exception_methods()
140+
print()
141+
142+
# Then run the main example
143+
print("Running Main RTTI Example:")
144+
print("-" * 30)
99145
try:
100146
main()
101147
except RTTI.ERTTIException as e:
102-
print(e)
148+
print("RTTI Exception occurred:")
149+
print(f" Error Code: {e.get_error_code()}")
150+
print(f" Error Message: '{e.get_error_message()}'")
151+
print(f" Error Name: {e.get_error_name()}")
152+
print(f" Error Description: {e.get_error_description()}")
153+
print(f" Full Exception: {e}")

Source/buildbindingpython.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,56 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
132132
w.Writeln(" if self._message:")
133133
w.Writeln(" return '%sException ' + str(self._code) + ': '+ str(self._message)", NameSpace)
134134
w.Writeln(" return '%sException ' + str(self._code)", NameSpace)
135+
w.Writeln(" ")
136+
w.Writeln(" def get_error_code(self):")
137+
w.Writeln(" \"\"\"Returns the error code\"\"\"")
138+
w.Writeln(" return self._code")
139+
w.Writeln(" ")
140+
w.Writeln(" def get_error_message(self):")
141+
w.Writeln(" \"\"\"Returns the custom error message\"\"\"")
142+
w.Writeln(" return self._message")
143+
w.Writeln(" ")
144+
w.Writeln(" def get_error_name(self):")
145+
w.Writeln(" \"\"\"Returns the error name (constant name)\"\"\"")
146+
w.Writeln(" if self._code == ErrorCodes.SUCCESS:")
147+
w.Writeln(" return 'SUCCESS'")
148+
for _, errorDef := range componentdefinition.Errors.Errors {
149+
w.Writeln(" elif self._code == ErrorCodes.%s:", errorDef.Name)
150+
w.Writeln(" return '%s'", errorDef.Name)
151+
}
152+
w.Writeln(" else:")
153+
w.Writeln(" return 'UNKNOWN'")
154+
w.Writeln(" ")
155+
w.Writeln(" def get_error_description(self):")
156+
w.Writeln(" \"\"\"Returns the error description (human-readable)\"\"\"")
157+
w.Writeln(" if self._code == ErrorCodes.SUCCESS:")
158+
w.Writeln(" return 'success'")
159+
for _, errorDef := range componentdefinition.Errors.Errors {
160+
w.Writeln(" elif self._code == ErrorCodes.%s:", errorDef.Name)
161+
w.Writeln(" return '%s'", errorDef.Description)
162+
}
163+
w.Writeln(" else:")
164+
w.Writeln(" return 'unknown error'")
165+
w.Writeln(" ")
166+
w.Writeln(" @property")
167+
w.Writeln(" def error_code(self):")
168+
w.Writeln(" \"\"\"Property to access error code\"\"\"")
169+
w.Writeln(" return self._code")
170+
w.Writeln(" ")
171+
w.Writeln(" @property")
172+
w.Writeln(" def error_message(self):")
173+
w.Writeln(" \"\"\"Property to access custom error message\"\"\"")
174+
w.Writeln(" return self._message")
175+
w.Writeln(" ")
176+
w.Writeln(" @property")
177+
w.Writeln(" def error_name(self):")
178+
w.Writeln(" \"\"\"Property to access error name\"\"\"")
179+
w.Writeln(" return self.get_error_name()")
180+
w.Writeln(" ")
181+
w.Writeln(" @property")
182+
w.Writeln(" def error_description(self):")
183+
w.Writeln(" \"\"\"Property to access error description\"\"\"")
184+
w.Writeln(" return self.get_error_description()")
135185
w.Writeln("")
136186

137187

0 commit comments

Comments
 (0)