Repository: apache/opendal (language: rust)

Issue:
new feature: Return detailed error message in python binding
### Feature Description

Return a detailed error message in the Python binding. For instance, use `format!({err:?})` instead of simply `err.to_string()`.

### Problem and Solution

Our Python errors are overly simplistic and lack detailed underlying reasons, making it difficult to debug issues such as https://github.com/apache/opendal/issues/5483.

### Additional Context

_No response_

### Are you willing to contribute to the development of this feature?

- [ ] Yes, I am willing to contribute to the development of this feature.


Discussion / hints:
hi i'd like to work on this issue
Hi, @VigneshSK17, I think we need to fix it here:

https://github.com/apache/opendal/blob/6ca3eabc0cc5ad2b5e123acc215b62329bbdbf18/bindings/python/src/errors.rs#L60-L74
is `format!({err:?})` sufficient?

I can pr it.

> is `format!({err:?})` sufficient?
> 
> I can pr it.

I believe so, welcome to do this.

Fix patch:
diff --git a/bindings/python/src/errors.rs b/bindings/python/src/errors.rs
index 6a8be442a8e..575962cbf48 100644
--- a/bindings/python/src/errors.rs
+++ b/bindings/python/src/errors.rs
@@ -58,17 +58,18 @@ create_exception!(
 );
 
 pub fn format_pyerr(err: ocore::Error) -> PyErr {
+    let e = format!("{err:?}");
     match err.kind() {
-        ocore::ErrorKind::Unexpected => Unexpected::new_err(err.to_string()),
-        ocore::ErrorKind::Unsupported => Unsupported::new_err(err.to_string()),
-        ocore::ErrorKind::ConfigInvalid => ConfigInvalid::new_err(err.to_string()),
-        ocore::ErrorKind::NotFound => NotFound::new_err(err.to_string()),
-        ocore::ErrorKind::PermissionDenied => PermissionDenied::new_err(err.to_string()),
-        ocore::ErrorKind::IsADirectory => IsADirectory::new_err(err.to_string()),
-        ocore::ErrorKind::NotADirectory => NotADirectory::new_err(err.to_string()),
-        ocore::ErrorKind::AlreadyExists => AlreadyExists::new_err(err.to_string()),
-        ocore::ErrorKind::IsSameFile => IsSameFile::new_err(err.to_string()),
-        ocore::ErrorKind::ConditionNotMatch => ConditionNotMatch::new_err(err.to_string()),
-        _ => Unexpected::new_err(err.to_string()),
+        ocore::ErrorKind::Unexpected => Unexpected::new_err(e),
+        ocore::ErrorKind::Unsupported => Unsupported::new_err(e),
+        ocore::ErrorKind::ConfigInvalid => ConfigInvalid::new_err(e),
+        ocore::ErrorKind::NotFound => NotFound::new_err(e),
+        ocore::ErrorKind::PermissionDenied => PermissionDenied::new_err(e),
+        ocore::ErrorKind::IsADirectory => IsADirectory::new_err(e),
+        ocore::ErrorKind::NotADirectory => NotADirectory::new_err(e),
+        ocore::ErrorKind::AlreadyExists => AlreadyExists::new_err(e),
+        ocore::ErrorKind::IsSameFile => IsSameFile::new_err(e),
+        ocore::ErrorKind::ConditionNotMatch => ConditionNotMatch::new_err(e),
+        _ => Unexpected::new_err(e),
     }
 }


Test patch: