about summary refs log tree commit diff stats
path: root/crates/yt_dlp/src/python_error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/yt_dlp/src/python_error.rs')
-rw-r--r--crates/yt_dlp/src/python_error.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/crates/yt_dlp/src/python_error.rs b/crates/yt_dlp/src/python_error.rs
new file mode 100644
index 0000000..0c442b3
--- /dev/null
+++ b/crates/yt_dlp/src/python_error.rs
@@ -0,0 +1,55 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::fmt::{self, Display};
+
+use log::{Level, debug, log_enabled};
+use pyo3::{PyErr, Python, types::PyTracebackMethods};
+
+#[derive(thiserror::Error, Debug)]
+pub struct PythonError(pub String);
+
+pub(crate) trait IntoPythonError<T>: Sized {
+    fn wrap_exc(self, py: Python<'_>) -> Result<T, PythonError>;
+}
+
+impl<T> IntoPythonError<T> for Result<T, PyErr> {
+    fn wrap_exc(self, py: Python<'_>) -> Result<T, PythonError> {
+        self.map_err(|exc| PythonError::from_exception(py, &exc))
+    }
+}
+
+impl Display for PythonError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Python threw an exception: {}", self.0)
+    }
+}
+
+impl PythonError {
+    pub(super) fn from_exception(py: Python<'_>, exc: &PyErr) -> Self {
+        let buffer = process_exception(py, exc);
+        Self(buffer)
+    }
+}
+
+pub(super) fn process_exception(py: Python<'_>, err: &PyErr) -> String {
+    if log_enabled!(Level::Debug) {
+        let mut output = err.to_string();
+
+        if let Some(tb) = err.traceback(py) {
+            output.push('\n');
+            output.push_str(&tb.format().unwrap());
+        }
+
+        debug!("Python threw an exception: {output}");
+    }
+
+    err.to_string()
+}