|
117 | 117 | //! [`Rc`]: std::rc::Rc |
118 | 118 | //! [`Py`]: crate::Py |
119 | 119 | use crate::conversion::IntoPyObject; |
120 | | -use crate::err::PyErr; |
121 | 120 | use crate::err::{self, PyResult}; |
122 | | -use crate::ffi_ptr_ext::FfiPtrExt; |
123 | 121 | use crate::gil::{GILGuard, SuspendGIL}; |
124 | 122 | use crate::impl_::not_send::NotSend; |
125 | | -use crate::py_result_ext::PyResultExt; |
126 | 123 | use crate::types::any::PyAnyMethods; |
127 | 124 | use crate::types::{ |
128 | | - PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType, |
| 125 | + PyAny, PyCode, PyCodeMethods, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, |
| 126 | + PyType, |
129 | 127 | }; |
130 | 128 | use crate::version::PythonVersionInfo; |
131 | 129 | use crate::{ffi, Bound, PyObject, PyTypeInfo}; |
132 | 130 | use std::ffi::CStr; |
133 | 131 | use std::marker::PhantomData; |
134 | | -use std::os::raw::c_int; |
135 | 132 |
|
136 | 133 | /// Types that are safe to access while the GIL is not held. |
137 | 134 | /// |
@@ -567,7 +564,13 @@ impl<'py> Python<'py> { |
567 | 564 | globals: Option<&Bound<'py, PyDict>>, |
568 | 565 | locals: Option<&Bound<'py, PyDict>>, |
569 | 566 | ) -> PyResult<Bound<'py, PyAny>> { |
570 | | - self.run_code(code, ffi::Py_eval_input, globals, locals) |
| 567 | + let code = PyCode::compile( |
| 568 | + self, |
| 569 | + code, |
| 570 | + ffi::c_str!("<string>"), |
| 571 | + crate::types::PyCodeInput::Eval, |
| 572 | + )?; |
| 573 | + code.run(globals, locals) |
571 | 574 | } |
572 | 575 |
|
573 | 576 | /// Executes one or more Python statements in the given context. |
@@ -611,79 +614,17 @@ impl<'py> Python<'py> { |
611 | 614 | globals: Option<&Bound<'py, PyDict>>, |
612 | 615 | locals: Option<&Bound<'py, PyDict>>, |
613 | 616 | ) -> PyResult<()> { |
614 | | - let res = self.run_code(code, ffi::Py_file_input, globals, locals); |
615 | | - res.map(|obj| { |
| 617 | + let code = PyCode::compile( |
| 618 | + self, |
| 619 | + code, |
| 620 | + ffi::c_str!("<string>"), |
| 621 | + crate::types::PyCodeInput::File, |
| 622 | + )?; |
| 623 | + code.run(globals, locals).map(|obj| { |
616 | 624 | debug_assert!(obj.is_none()); |
617 | 625 | }) |
618 | 626 | } |
619 | 627 |
|
620 | | - /// Runs code in the given context. |
621 | | - /// |
622 | | - /// `start` indicates the type of input expected: one of `Py_single_input`, |
623 | | - /// `Py_file_input`, or `Py_eval_input`. |
624 | | - /// |
625 | | - /// If `globals` is `None`, it defaults to Python module `__main__`. |
626 | | - /// If `locals` is `None`, it defaults to the value of `globals`. |
627 | | - fn run_code( |
628 | | - self, |
629 | | - code: &CStr, |
630 | | - start: c_int, |
631 | | - globals: Option<&Bound<'py, PyDict>>, |
632 | | - locals: Option<&Bound<'py, PyDict>>, |
633 | | - ) -> PyResult<Bound<'py, PyAny>> { |
634 | | - let mptr = unsafe { |
635 | | - ffi::compat::PyImport_AddModuleRef(ffi::c_str!("__main__").as_ptr()) |
636 | | - .assume_owned_or_err(self)? |
637 | | - }; |
638 | | - let attr = mptr.getattr(crate::intern!(self, "__dict__"))?; |
639 | | - let globals = match globals { |
640 | | - Some(globals) => globals, |
641 | | - None => attr.downcast::<PyDict>()?, |
642 | | - }; |
643 | | - let locals = locals.unwrap_or(globals); |
644 | | - |
645 | | - // If `globals` don't provide `__builtins__`, most of the code will fail if Python |
646 | | - // version is <3.10. That's probably not what user intended, so insert `__builtins__` |
647 | | - // for them. |
648 | | - // |
649 | | - // See also: |
650 | | - // - https://github.com/python/cpython/pull/24564 (the same fix in CPython 3.10) |
651 | | - // - https://github.com/PyO3/pyo3/issues/3370 |
652 | | - let builtins_s = crate::intern!(self, "__builtins__"); |
653 | | - let has_builtins = globals.contains(builtins_s)?; |
654 | | - if !has_builtins { |
655 | | - crate::sync::with_critical_section(globals, || { |
656 | | - // check if another thread set __builtins__ while this thread was blocked on the critical section |
657 | | - let has_builtins = globals.contains(builtins_s)?; |
658 | | - if !has_builtins { |
659 | | - // Inherit current builtins. |
660 | | - let builtins = unsafe { ffi::PyEval_GetBuiltins() }; |
661 | | - |
662 | | - // `PyDict_SetItem` doesn't take ownership of `builtins`, but `PyEval_GetBuiltins` |
663 | | - // seems to return a borrowed reference, so no leak here. |
664 | | - if unsafe { |
665 | | - ffi::PyDict_SetItem(globals.as_ptr(), builtins_s.as_ptr(), builtins) |
666 | | - } == -1 |
667 | | - { |
668 | | - return Err(PyErr::fetch(self)); |
669 | | - } |
670 | | - } |
671 | | - Ok(()) |
672 | | - })?; |
673 | | - } |
674 | | - |
675 | | - let code_obj = unsafe { |
676 | | - ffi::Py_CompileString(code.as_ptr(), ffi::c_str!("<string>").as_ptr(), start) |
677 | | - .assume_owned_or_err(self)? |
678 | | - }; |
679 | | - |
680 | | - unsafe { |
681 | | - ffi::PyEval_EvalCode(code_obj.as_ptr(), globals.as_ptr(), locals.as_ptr()) |
682 | | - .assume_owned_or_err(self) |
683 | | - .downcast_into_unchecked() |
684 | | - } |
685 | | - } |
686 | | - |
687 | 628 | /// Gets the Python type object for type `T`. |
688 | 629 | #[inline] |
689 | 630 | pub fn get_type<T>(self) -> Bound<'py, PyType> |
@@ -766,7 +707,7 @@ impl<'py> Python<'py> { |
766 | 707 | /// Lets the Python interpreter check and handle any pending signals. This will invoke the |
767 | 708 | /// corresponding signal handlers registered in Python (if any). |
768 | 709 | /// |
769 | | - /// Returns `Err(`[`PyErr`]`)` if any signal handler raises an exception. |
| 710 | + /// Returns `Err(`[`PyErr`](crate::PyErr)`)` if any signal handler raises an exception. |
770 | 711 | /// |
771 | 712 | /// These signals include `SIGINT` (normally raised by CTRL + C), which by default raises |
772 | 713 | /// `KeyboardInterrupt`. For this reason it is good practice to call this function regularly |
@@ -939,6 +880,8 @@ mod tests { |
939 | 880 | #[test] |
940 | 881 | #[cfg(not(Py_LIMITED_API))] |
941 | 882 | fn test_acquire_gil() { |
| 883 | + use std::ffi::c_int; |
| 884 | + |
942 | 885 | const GIL_NOT_HELD: c_int = 0; |
943 | 886 | const GIL_HELD: c_int = 1; |
944 | 887 |
|
|
0 commit comments