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.rs105
1 files changed, 22 insertions, 83 deletions
diff --git a/crates/yt_dlp/src/python_error.rs b/crates/yt_dlp/src/python_error.rs
index 9513956..0c442b3 100644
--- a/crates/yt_dlp/src/python_error.rs
+++ b/crates/yt_dlp/src/python_error.rs
@@ -8,109 +8,48 @@
 // 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::Display;
+use std::fmt::{self, Display};
 
 use log::{Level, debug, log_enabled};
-use rustpython::vm::{
-    AsObject, PyPayload, PyRef, VirtualMachine,
-    builtins::{PyBaseException, PyBaseExceptionRef, PyStr},
-    py_io::Write,
-    suggestion::offer_suggestions,
-};
+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 std::fmt::Formatter<'_>) -> std::fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "Python threw an exception: {}", self.0)
     }
 }
 
 impl PythonError {
-    pub(super) fn from_exception(vm: &VirtualMachine, exc: &PyRef<PyBaseException>) -> Self {
-        let buffer = process_exception(vm, exc);
+    pub(super) fn from_exception(py: Python<'_>, exc: &PyErr) -> Self {
+        let buffer = process_exception(py, exc);
         Self(buffer)
     }
 }
 
-pub(super) fn process_exception(vm: &VirtualMachine, err: &PyBaseExceptionRef) -> String {
-    let mut buffer = String::new();
-    write_exception(vm, &mut buffer, err)
-        .expect("We are writing into an *in-memory* string, it will always work");
-
+pub(super) fn process_exception(py: Python<'_>, err: &PyErr) -> String {
     if log_enabled!(Level::Debug) {
-        let mut output = String::new();
-        vm.write_exception(&mut output, err)
-            .expect("We are writing into an *in-memory* string, it will always work");
-        debug!("Python threw an exception: {output}");
-    }
+        let mut output = err.to_string();
 
-    buffer
-}
-
-// Inlined and changed from `vm.write_exception_inner`
-fn write_exception<W: Write>(
-    vm: &VirtualMachine,
-    output: &mut W,
-    exc: &PyBaseExceptionRef,
-) -> Result<(), W::Error> {
-    let varargs = exc.args();
-    let args_repr = {
-        match varargs.len() {
-            0 => vec![],
-            1 => {
-                let args0_repr = if true {
-                    varargs[0]
-                        .str(vm)
-                        .unwrap_or_else(|_| PyStr::from("<element str() failed>").into_ref(&vm.ctx))
-                } else {
-                    varargs[0].repr(vm).unwrap_or_else(|_| {
-                        PyStr::from("<element repr() failed>").into_ref(&vm.ctx)
-                    })
-                };
-                vec![args0_repr]
-            }
-            _ => varargs
-                .iter()
-                .map(|vararg| {
-                    vararg.repr(vm).unwrap_or_else(|_| {
-                        PyStr::from("<element repr() failed>").into_ref(&vm.ctx)
-                    })
-                })
-                .collect(),
+        if let Some(tb) = err.traceback(py) {
+            output.push('\n');
+            output.push_str(&tb.format().unwrap());
         }
-    };
 
-    let exc_class = exc.class();
-
-    if exc_class.fast_issubclass(vm.ctx.exceptions.syntax_error) {
-        unreachable!(
-            "A syntax error should never be raised, \
-            as yt_dlp should not have them and neither our embedded code"
-        );
+        debug!("Python threw an exception: {output}");
     }
 
-    let exc_name = exc_class.name();
-    match args_repr.len() {
-        0 => write!(output, "{exc_name}"),
-        1 => write!(output, "{}: {}", exc_name, args_repr[0]),
-        _ => write!(
-            output,
-            "{}: ({})",
-            exc_name,
-            args_repr
-                .iter()
-                .map(|val| val.as_str())
-                .collect::<Vec<_>>()
-                .join(", "),
-        ),
-    }?;
-
-    match offer_suggestions(exc, vm) {
-        Some(suggestions) => {
-            write!(output, ". Did you mean: '{suggestions}'?")
-        }
-        None => Ok(()),
-    }
+    err.to_string()
 }