Skip to content

py_run! creates unexpected scope issues #2891

@davidhewitt

Description

@davidhewitt

Bug Description

Try the following code (originally discussed in #2889).

#[pyfunction]
fn report_unraisable(py: Python) {
    use pyo3::exceptions::PyRuntimeError;
    let err = PyRuntimeError::new_err("foo");
    err.write_unraisable(py, None);

    let err = PyRuntimeError::new_err("bar");
    err.write_unraisable(py, Some(py.NotImplemented().as_ref(py)));
}

#[test]
fn test_write_unraisable() {
    Python::with_gil(|py| {
        let report_unraisable = wrap_pyfunction!(report_unraisable, py).unwrap();
        let locals = PyDict::new(py);
        locals
            .set_item("report_unraisable", report_unraisable)
            .unwrap();

        py_run!(
            py,
            report_unraisable,
            r#"
                import sys

                captured = []
                def report(data):
                    captured.append(list(data))

                original_hook = sys.unraisablehook
                try:
                    sys.unraisablehook = report
                    report_unraisable()

                    assert len(captured) == 2

                    assert captured[0][0] is RuntimeError
                    assert str(captured[0][1]) == 'foo'
                    assert captured[0][4] is None

                    assert captured[1][0] is RuntimeError
                    assert str(captured[1][1]) == 'bar'
                    assert captured[1][4] is NotImplemented
                finally:
                    sys.unraisablehook = original_hook
            "#
        );
    });
}

The report function defined within the py_run! source will print errors like the following, and the test will fail:

Exception ignored in sys.unraisablehook: <function report at 0x102e94040>
Traceback (most recent call last):
  File "<string>", line 5, in report
NameError: name 'captured' is not defined
Exception ignored in sys.unraisablehook: <function report at 0x102e94040>
Traceback (most recent call last):
  File "<string>", line 5, in report
NameError: name 'captured' is not defined
Traceback (most recent call last):
  File "<string>", line 12, in <module>
AssertionError

Steps to Reproduce

As above

Backtrace

No response

Your operating system and version

macOS Ventura 13.1

Your Python version (python --version)

Python 3.10.9

Your Rust version (rustc --version)

rustc 1.67.0-beta.2

Your PyO3 version

0.18.0

How did you install python? Did you use a virtualenv?

brew + vent

Additional Info

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions