Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions Examples/RTTI/RTTI_component/Bindings/Python/RTTI.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,80 @@ def __str__(self):
if self._message:
return 'RTTIException ' + str(self._code) + ': '+ str(self._message)
return 'RTTIException ' + str(self._code)

def get_error_code(self):
"""Returns the error code"""
return self._code

def get_error_message(self):
"""Returns the custom error message"""
return self._message

def get_error_name(self):
"""Returns the error name (constant name)"""
if self._code == ErrorCodes.SUCCESS:
return 'SUCCESS'
elif self._code == ErrorCodes.NOTIMPLEMENTED:
return 'NOTIMPLEMENTED'
elif self._code == ErrorCodes.INVALIDPARAM:
return 'INVALIDPARAM'
elif self._code == ErrorCodes.INVALIDCAST:
return 'INVALIDCAST'
elif self._code == ErrorCodes.BUFFERTOOSMALL:
return 'BUFFERTOOSMALL'
elif self._code == ErrorCodes.GENERICEXCEPTION:
return 'GENERICEXCEPTION'
elif self._code == ErrorCodes.COULDNOTLOADLIBRARY:
return 'COULDNOTLOADLIBRARY'
elif self._code == ErrorCodes.COULDNOTFINDLIBRARYEXPORT:
return 'COULDNOTFINDLIBRARYEXPORT'
elif self._code == ErrorCodes.INCOMPATIBLEBINARYVERSION:
return 'INCOMPATIBLEBINARYVERSION'
else:
return 'UNKNOWN'

def get_error_description(self):
"""Returns the error description (human-readable)"""
if self._code == ErrorCodes.SUCCESS:
return 'success'
elif self._code == ErrorCodes.NOTIMPLEMENTED:
return 'functionality not implemented'
elif self._code == ErrorCodes.INVALIDPARAM:
return 'an invalid parameter was passed'
elif self._code == ErrorCodes.INVALIDCAST:
return 'a type cast failed'
elif self._code == ErrorCodes.BUFFERTOOSMALL:
return 'a provided buffer is too small'
elif self._code == ErrorCodes.GENERICEXCEPTION:
return 'a generic exception occurred'
elif self._code == ErrorCodes.COULDNOTLOADLIBRARY:
return 'the library could not be loaded'
elif self._code == ErrorCodes.COULDNOTFINDLIBRARYEXPORT:
return 'a required exported symbol could not be found in the library'
elif self._code == ErrorCodes.INCOMPATIBLEBINARYVERSION:
return 'the version of the binary interface does not match the bindings interface'
else:
return 'unknown error'

@property
def error_code(self):
"""Property to access error code"""
return self._code

@property
def error_message(self):
"""Property to access custom error message"""
return self._message

@property
def error_name(self):
"""Property to access error name"""
return self.get_error_name()

@property
def error_description(self):
"""Property to access error description"""
return self.get_error_description()

'''Definition of binding API version
'''
Expand Down
53 changes: 52 additions & 1 deletion Examples/RTTI/RTTI_component/Examples/Python/RTTI_Example.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,43 @@
import RTTI


def test_exception_methods():
"""Test the new exception methods using assert statements"""
print("Testing RTTI Exception Methods...")

# Test with a non-existent library to trigger an exception
try:
wrapper = RTTI.Wrapper(libraryName="nonexistent_library")
assert False, "Should have thrown an exception!"
except RTTI.ERTTIException as e:
print("+ Successfully caught ERTTIException")

# Test the new methods with assertions
error_code = e.get_error_code()
error_message = e.get_error_message()
error_name = e.get_error_name()
error_description = e.get_error_description()

# Assertions for method functionality
assert error_code == RTTI.ErrorCodes.COULDNOTLOADLIBRARY, f"Expected error code 6, got {error_code}"
assert error_name == "COULDNOTLOADLIBRARY", f"Expected 'COULDNOTLOADLIBRARY', got '{error_name}'"
assert error_description == "the library could not be loaded", f"Expected library load error description, got '{error_description}'"
assert "nonexistent_library" in error_message, f"Expected library name in message, got '{error_message}'"

# Test properties (alternative access)
assert e.error_code == error_code, "Property error_code should match method get_error_code()"
assert e.error_message == error_message, "Property error_message should match method get_error_message()"
assert e.error_name == error_name, "Property error_name should match method get_error_name()"
assert e.error_description == error_description, "Property error_description should match method get_error_description()"

# Test string representation
exception_str = str(e)
assert "RTTIException" in exception_str, f"String representation should contain 'RTTIException', got '{exception_str}'"
assert str(error_code) in exception_str, f"String representation should contain error code, got '{exception_str}'"

print("+ All exception method tests passed!")


def main():
libpath = '' # TODO add the location of the shared library binary here
wrapper = RTTI.Wrapper(libraryName = os.path.join(libpath, "rtti"))
Expand Down Expand Up @@ -96,7 +133,21 @@ def main():
animal = iter.GetNextAnimal(); assert not animal

if __name__ == "__main__":
# Test exception methods first (before main, as it uses a non-existent library)
print("Testing Exception Methods:")
print("-" * 30)
test_exception_methods()
print()

# Then run the main example
print("Running Main RTTI Example:")
print("-" * 30)
try:
main()
except RTTI.ERTTIException as e:
print(e)
print("RTTI Exception occurred:")
print(f" Error Code: {e.get_error_code()}")
print(f" Error Message: '{e.get_error_message()}'")
print(f" Error Name: {e.get_error_name()}")
print(f" Error Description: {e.get_error_description()}")
print(f" Full Exception: {e}")
50 changes: 50 additions & 0 deletions Source/buildbindingpython.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,56 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w
w.Writeln(" if self._message:")
w.Writeln(" return '%sException ' + str(self._code) + ': '+ str(self._message)", NameSpace)
w.Writeln(" return '%sException ' + str(self._code)", NameSpace)
w.Writeln(" ")
w.Writeln(" def get_error_code(self):")
w.Writeln(" \"\"\"Returns the error code\"\"\"")
w.Writeln(" return self._code")
w.Writeln(" ")
w.Writeln(" def get_error_message(self):")
w.Writeln(" \"\"\"Returns the custom error message\"\"\"")
w.Writeln(" return self._message")
w.Writeln(" ")
w.Writeln(" def get_error_name(self):")
w.Writeln(" \"\"\"Returns the error name (constant name)\"\"\"")
w.Writeln(" if self._code == ErrorCodes.SUCCESS:")
w.Writeln(" return 'SUCCESS'")
for _, errorDef := range componentdefinition.Errors.Errors {
w.Writeln(" elif self._code == ErrorCodes.%s:", errorDef.Name)
w.Writeln(" return '%s'", errorDef.Name)
}
w.Writeln(" else:")
w.Writeln(" return 'UNKNOWN'")
w.Writeln(" ")
w.Writeln(" def get_error_description(self):")
w.Writeln(" \"\"\"Returns the error description (human-readable)\"\"\"")
w.Writeln(" if self._code == ErrorCodes.SUCCESS:")
w.Writeln(" return 'success'")
for _, errorDef := range componentdefinition.Errors.Errors {
w.Writeln(" elif self._code == ErrorCodes.%s:", errorDef.Name)
w.Writeln(" return '%s'", errorDef.Description)
}
w.Writeln(" else:")
w.Writeln(" return 'unknown error'")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_code(self):")
w.Writeln(" \"\"\"Property to access error code\"\"\"")
w.Writeln(" return self._code")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_message(self):")
w.Writeln(" \"\"\"Property to access custom error message\"\"\"")
w.Writeln(" return self._message")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_name(self):")
w.Writeln(" \"\"\"Property to access error name\"\"\"")
w.Writeln(" return self.get_error_name()")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_description(self):")
w.Writeln(" \"\"\"Property to access error description\"\"\"")
w.Writeln(" return self.get_error_description()")
Comment on lines +179 to +184
Copy link

Copilot AI Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The properties error_name and error_description add unnecessary indirection by calling getter methods that contain the actual logic. Consider implementing the logic directly in the properties to eliminate the redundant method calls and simplify the code structure.

Suggested change
w.Writeln(" return self.get_error_name()")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_description(self):")
w.Writeln(" \"\"\"Property to access error description\"\"\"")
w.Writeln(" return self.get_error_description()")
w.Writeln(" # Inlined logic from get_error_name")
w.Writeln(" return type(self).__name__")
w.Writeln(" ")
w.Writeln(" @property")
w.Writeln(" def error_description(self):")
w.Writeln(" \"\"\"Property to access error description\"\"\"")
w.Writeln(" # Inlined logic from get_error_description")
w.Writeln(" return str(self)")

Copilot uses AI. Check for mistakes.

w.Writeln("")


Expand Down
Loading