pyo3/marker.rs
1//! Fundamental properties of objects tied to the Python interpreter.
2//!
3//! The Python interpreter is not threadsafe. To protect the Python interpreter in multithreaded
4//! scenarios there is a global lock, the *global interpreter lock* (hereafter referred to as *GIL*)
5//! that must be held to safely interact with Python objects. This is why in PyO3 when you acquire
6//! the GIL you get a [`Python`] marker token that carries the *lifetime* of holding the GIL and all
7//! borrowed references to Python objects carry this lifetime as well. This will statically ensure
8//! that you can never use Python objects after dropping the lock - if you mess this up it will be
9//! caught at compile time and your program will fail to compile.
10//!
11//! It also supports this pattern that many extension modules employ:
12//! - Drop the GIL, so that other Python threads can acquire it and make progress themselves
13//! - Do something independently of the Python interpreter, like IO, a long running calculation or
14//! awaiting a future
15//! - Once that is done, reacquire the GIL
16//!
17//! That API is provided by [`Python::allow_threads`] and enforced via the [`Ungil`] bound on the
18//! closure and the return type. This is done by relying on the [`Send`] auto trait. `Ungil` is
19//! defined as the following:
20//!
21//! ```rust
22//! # #![allow(dead_code)]
23//! pub unsafe trait Ungil {}
24//!
25//! unsafe impl<T: Send> Ungil for T {}
26//! ```
27//!
28//! We piggy-back off the `Send` auto trait because it is not possible to implement custom auto
29//! traits on stable Rust. This is the solution which enables it for as many types as possible while
30//! making the API usable.
31//!
32//! In practice this API works quite well, but it comes with some drawbacks:
33//!
34//! ## Drawbacks
35//!
36//! There is no reason to prevent `!Send` types like [`Rc`] from crossing the closure. After all,
37//! [`Python::allow_threads`] just lets other Python threads run - it does not itself launch a new
38//! thread.
39//!
40//! ```rust, compile_fail
41//! # #[cfg(feature = "nightly")]
42//! # compile_error!("this actually works on nightly")
43//! use pyo3::prelude::*;
44//! use std::rc::Rc;
45//!
46//! fn main() {
47//! Python::with_gil(|py| {
48//! let rc = Rc::new(5);
49//!
50//! py.allow_threads(|| {
51//! // This would actually be fine...
52//! println!("{:?}", *rc);
53//! });
54//! });
55//! }
56//! ```
57//!
58//! Because we are using `Send` for something it's not quite meant for, other code that
59//! (correctly) upholds the invariants of [`Send`] can cause problems.
60//!
61//! [`SendWrapper`] is one of those. Per its documentation:
62//!
63//! > A wrapper which allows you to move around non-Send-types between threads, as long as you
64//! > access the contained value only from within the original thread and make sure that it is
65//! > dropped from within the original thread.
66//!
67//! This will "work" to smuggle Python references across the closure, because we're not actually
68//! doing anything with threads:
69//!
70//! ```rust, no_run
71//! use pyo3::prelude::*;
72//! use pyo3::types::PyString;
73//! use send_wrapper::SendWrapper;
74//!
75//! Python::with_gil(|py| {
76//! let string = PyString::new_bound(py, "foo");
77//!
78//! let wrapped = SendWrapper::new(string);
79//!
80//! py.allow_threads(|| {
81//! # #[cfg(not(feature = "nightly"))]
82//! # {
83//! // 💥 Unsound! 💥
84//! let smuggled: &Bound<'_, PyString> = &*wrapped;
85//! println!("{:?}", smuggled);
86//! # }
87//! });
88//! });
89//! ```
90//!
91//! For now the answer to that is "don't do that".
92//!
93//! # A proper implementation using an auto trait
94//!
95//! However on nightly Rust and when PyO3's `nightly` feature is
96//! enabled, `Ungil` is defined as the following:
97//!
98//! ```rust
99//! # #[cfg(any())]
100//! # {
101//! #![feature(auto_traits, negative_impls)]
102//!
103//! pub unsafe auto trait Ungil {}
104//!
105//! // It is unimplemented for the `Python` struct and Python objects.
106//! impl !Ungil for Python<'_> {}
107//! impl !Ungil for ffi::PyObject {}
108//!
109//! // `Py` wraps it in a safe api, so this is OK
110//! unsafe impl<T> Ungil for Py<T> {}
111//! # }
112//! ```
113//!
114//! With this feature enabled, the above two examples will start working and not working, respectively.
115//!
116//! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html
117//! [`Rc`]: std::rc::Rc
118//! [`Py`]: crate::Py
119use crate::err::{self, PyErr, PyResult};
120use crate::ffi_ptr_ext::FfiPtrExt;
121use crate::gil::{GILGuard, SuspendGIL};
122use crate::impl_::not_send::NotSend;
123use crate::py_result_ext::PyResultExt;
124use crate::types::any::PyAnyMethods;
125use crate::types::{
126 PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType,
127};
128use crate::version::PythonVersionInfo;
129use crate::{ffi, Bound, IntoPy, Py, PyObject, PyTypeInfo};
130#[allow(deprecated)]
131#[cfg(feature = "gil-refs")]
132use crate::{gil::GILPool, FromPyPointer, PyNativeType};
133use std::ffi::{CStr, CString};
134use std::marker::PhantomData;
135use std::os::raw::c_int;
136
137/// Types that are safe to access while the GIL is not held.
138///
139/// # Safety
140///
141/// The type must not carry borrowed Python references or, if it does, not allow access to them if
142/// the GIL is not held.
143///
144/// See the [module-level documentation](self) for more information.
145///
146/// # Examples
147///
148/// This tracking is currently imprecise as it relies on the [`Send`] auto trait on stable Rust.
149/// For example, an `Rc` smart pointer should be usable without the GIL, but we currently prevent that:
150///
151/// ```compile_fail
152/// # use pyo3::prelude::*;
153/// use std::rc::Rc;
154///
155/// Python::with_gil(|py| {
156/// let rc = Rc::new(42);
157///
158/// py.allow_threads(|| {
159/// println!("{:?}", rc);
160/// });
161/// });
162/// ```
163///
164/// This also implies that the interplay between `with_gil` and `allow_threads` is unsound, for example
165/// one can circumvent this protection using the [`send_wrapper`](https://docs.rs/send_wrapper/) crate:
166///
167/// ```no_run
168/// # use pyo3::prelude::*;
169/// # use pyo3::types::PyString;
170/// use send_wrapper::SendWrapper;
171///
172/// Python::with_gil(|py| {
173/// let string = PyString::new_bound(py, "foo");
174///
175/// let wrapped = SendWrapper::new(string);
176///
177/// py.allow_threads(|| {
178/// let sneaky: &Bound<'_, PyString> = &*wrapped;
179///
180/// println!("{:?}", sneaky);
181/// });
182/// });
183/// ```
184///
185/// Fixing this loophole on stable Rust has significant ergonomic issues, but it is fixed when using
186/// nightly Rust and the `nightly` feature, c.f. [#2141](https://github.com/PyO3/pyo3/issues/2141).
187#[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag
188#[cfg(not(feature = "nightly"))]
189pub unsafe trait Ungil {}
190
191#[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag
192#[cfg(not(feature = "nightly"))]
193unsafe impl<T: Send> Ungil for T {}
194
195#[cfg(feature = "nightly")]
196mod nightly {
197 macro_rules! define {
198 ($($tt:tt)*) => { $($tt)* }
199 }
200
201 define! {
202 /// Types that are safe to access while the GIL is not held.
203 ///
204 /// # Safety
205 ///
206 /// The type must not carry borrowed Python references or, if it does, not allow access to them if
207 /// the GIL is not held.
208 ///
209 /// See the [module-level documentation](self) for more information.
210 ///
211 /// # Examples
212 ///
213 /// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g.
214 ///
215 /// ```compile_fail
216 /// # use pyo3::prelude::*;
217 /// # use pyo3::types::PyString;
218 /// Python::with_gil(|py| {
219 /// let string = PyString::new_bound(py, "foo");
220 ///
221 /// py.allow_threads(|| {
222 /// println!("{:?}", string);
223 /// });
224 /// });
225 /// ```
226 ///
227 /// This applies to the GIL token `Python` itself as well, e.g.
228 ///
229 /// ```compile_fail
230 /// # use pyo3::prelude::*;
231 /// Python::with_gil(|py| {
232 /// py.allow_threads(|| {
233 /// drop(py);
234 /// });
235 /// });
236 /// ```
237 ///
238 /// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able
239 /// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate:
240 ///
241 /// ```compile_fail
242 /// # use pyo3::prelude::*;
243 /// # use pyo3::types::PyString;
244 /// use send_wrapper::SendWrapper;
245 ///
246 /// Python::with_gil(|py| {
247 /// let string = PyString::new_bound(py, "foo");
248 ///
249 /// let wrapped = SendWrapper::new(string);
250 ///
251 /// py.allow_threads(|| {
252 /// let sneaky: &PyString = *wrapped;
253 ///
254 /// println!("{:?}", sneaky);
255 /// });
256 /// });
257 /// ```
258 ///
259 /// This also enables using non-[`Send`] types in `allow_threads`,
260 /// at least if they are not also bound to the GIL:
261 ///
262 /// ```rust
263 /// # use pyo3::prelude::*;
264 /// use std::rc::Rc;
265 ///
266 /// Python::with_gil(|py| {
267 /// let rc = Rc::new(42);
268 ///
269 /// py.allow_threads(|| {
270 /// println!("{:?}", rc);
271 /// });
272 /// });
273 /// ```
274 pub unsafe auto trait Ungil {}
275 }
276
277 impl !Ungil for crate::Python<'_> {}
278
279 // This means that PyString, PyList, etc all inherit !Ungil from this.
280 impl !Ungil for crate::PyAny {}
281
282 // All the borrowing wrappers
283 #[allow(deprecated)]
284 #[cfg(feature = "gil-refs")]
285 impl<T> !Ungil for crate::PyCell<T> {}
286 impl<T> !Ungil for crate::PyRef<'_, T> {}
287 impl<T> !Ungil for crate::PyRefMut<'_, T> {}
288
289 // FFI pointees
290 impl !Ungil for crate::ffi::PyObject {}
291 impl !Ungil for crate::ffi::PyLongObject {}
292
293 impl !Ungil for crate::ffi::PyThreadState {}
294 impl !Ungil for crate::ffi::PyInterpreterState {}
295 impl !Ungil for crate::ffi::PyWeakReference {}
296 impl !Ungil for crate::ffi::PyFrameObject {}
297 impl !Ungil for crate::ffi::PyCodeObject {}
298 #[cfg(not(Py_LIMITED_API))]
299 impl !Ungil for crate::ffi::PyDictKeysObject {}
300 #[cfg(not(any(Py_LIMITED_API, Py_3_10)))]
301 impl !Ungil for crate::ffi::PyArena {}
302}
303
304#[cfg(feature = "nightly")]
305pub use nightly::Ungil;
306
307/// A marker token that represents holding the GIL.
308///
309/// It serves three main purposes:
310/// - It provides a global API for the Python interpreter, such as [`Python::eval_bound`].
311/// - It can be passed to functions that require a proof of holding the GIL, such as
312/// [`Py::clone_ref`].
313/// - Its lifetime represents the scope of holding the GIL which can be used to create Rust
314/// references that are bound to it, such as [`Bound<'py, PyAny>`].
315///
316/// Note that there are some caveats to using it that you might need to be aware of. See the
317/// [Deadlocks](#deadlocks) and [Releasing and freeing memory](#releasing-and-freeing-memory)
318/// paragraphs for more information about that.
319///
320/// # Obtaining a Python token
321///
322/// The following are the recommended ways to obtain a [`Python<'py>`] token, in order of preference:
323/// - If you already have something with a lifetime bound to the GIL, such as [`Bound<'py, PyAny>`], you can
324/// use its `.py()` method to get a token.
325/// - In a function or method annotated with [`#[pyfunction]`](crate::pyfunction) or [`#[pymethods]`](crate::pymethods) you can declare it
326/// as a parameter, and PyO3 will pass in the token when Python code calls it.
327/// - When you need to acquire the GIL yourself, such as when calling Python code from Rust, you
328/// should call [`Python::with_gil`] to do that and pass your code as a closure to it.
329///
330/// The first two options are zero-cost; [`Python::with_gil`] requires runtime checking and may need to block
331/// to acquire the GIL.
332///
333/// # Deadlocks
334///
335/// Note that the GIL can be temporarily released by the Python interpreter during a function call
336/// (e.g. importing a module). In general, you don't need to worry about this because the GIL is
337/// reacquired before returning to the Rust code:
338///
339/// ```text
340/// `Python` exists |=====================================|
341/// GIL actually held |==========| |================|
342/// Rust code running |=======| |==| |======|
343/// ```
344///
345/// This behaviour can cause deadlocks when trying to lock a Rust mutex while holding the GIL:
346///
347/// * Thread 1 acquires the GIL
348/// * Thread 1 locks a mutex
349/// * Thread 1 makes a call into the Python interpreter which releases the GIL
350/// * Thread 2 acquires the GIL
351/// * Thread 2 tries to locks the mutex, blocks
352/// * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2
353///
354/// To avoid deadlocking, you should release the GIL before trying to lock a mutex or `await`ing in
355/// asynchronous code, e.g. with [`Python::allow_threads`].
356///
357/// # Releasing and freeing memory
358///
359/// The [`Python<'py>`] type can be used to create references to variables owned by the Python
360/// interpreter, using functions such as [`Python::eval_bound`] and [`PyModule::import_bound`].
361#[derive(Copy, Clone)]
362pub struct Python<'py>(PhantomData<(&'py GILGuard, NotSend)>);
363
364impl Python<'_> {
365 /// Acquires the global interpreter lock, allowing access to the Python interpreter. The
366 /// provided closure `F` will be executed with the acquired `Python` marker token.
367 ///
368 /// If implementing [`#[pymethods]`](crate::pymethods) or [`#[pyfunction]`](crate::pyfunction),
369 /// declare `py: Python` as an argument. PyO3 will pass in the token to grant access to the GIL
370 /// context in which the function is running, avoiding the need to call `with_gil`.
371 ///
372 /// If the [`auto-initialize`] feature is enabled and the Python runtime is not already
373 /// initialized, this function will initialize it. See
374 #[cfg_attr(
375 not(any(PyPy, GraalPy)),
376 doc = "[`prepare_freethreaded_python`](crate::prepare_freethreaded_python)"
377 )]
378 #[cfg_attr(PyPy, doc = "`prepare_freethreaded_python`")]
379 /// for details.
380 ///
381 /// If the current thread does not yet have a Python "thread state" associated with it,
382 /// a new one will be automatically created before `F` is executed and destroyed after `F`
383 /// completes.
384 ///
385 /// # Panics
386 ///
387 /// - If the [`auto-initialize`] feature is not enabled and the Python interpreter is not
388 /// initialized.
389 ///
390 /// # Examples
391 ///
392 /// ```
393 /// use pyo3::prelude::*;
394 ///
395 /// # fn main() -> PyResult<()> {
396 /// Python::with_gil(|py| -> PyResult<()> {
397 /// let x: i32 = py.eval_bound("5", None, None)?.extract()?;
398 /// assert_eq!(x, 5);
399 /// Ok(())
400 /// })
401 /// # }
402 /// ```
403 ///
404 /// [`auto-initialize`]: https://pyo3.rs/main/features.html#auto-initialize
405 #[inline]
406 pub fn with_gil<F, R>(f: F) -> R
407 where
408 F: for<'py> FnOnce(Python<'py>) -> R,
409 {
410 let guard = GILGuard::acquire();
411
412 // SAFETY: Either the GIL was already acquired or we just created a new `GILGuard`.
413 f(guard.python())
414 }
415
416 /// Like [`Python::with_gil`] except Python interpreter state checking is skipped.
417 ///
418 /// Normally when the GIL is acquired, we check that the Python interpreter is an
419 /// appropriate state (e.g. it is fully initialized). This function skips those
420 /// checks.
421 ///
422 /// # Safety
423 ///
424 /// If [`Python::with_gil`] would succeed, it is safe to call this function.
425 ///
426 /// In most cases, you should use [`Python::with_gil`].
427 ///
428 /// A justified scenario for calling this function is during multi-phase interpreter
429 /// initialization when [`Python::with_gil`] would fail before
430 // this link is only valid on 3.8+not pypy and up.
431 #[cfg_attr(
432 all(Py_3_8, not(PyPy)),
433 doc = "[`_Py_InitializeMain`](crate::ffi::_Py_InitializeMain)"
434 )]
435 #[cfg_attr(any(not(Py_3_8), PyPy), doc = "`_Py_InitializeMain`")]
436 /// is called because the interpreter is only partially initialized.
437 ///
438 /// Behavior in other scenarios is not documented.
439 #[inline]
440 pub unsafe fn with_gil_unchecked<F, R>(f: F) -> R
441 where
442 F: for<'py> FnOnce(Python<'py>) -> R,
443 {
444 let guard = GILGuard::acquire_unchecked();
445
446 f(guard.python())
447 }
448}
449
450impl<'py> Python<'py> {
451 /// Temporarily releases the GIL, thus allowing other Python threads to run. The GIL will be
452 /// reacquired when `F`'s scope ends.
453 ///
454 /// If you don't need to touch the Python
455 /// interpreter for some time and have other Python threads around, this will let you run
456 /// Rust-only code while letting those other Python threads make progress.
457 ///
458 /// Only types that implement [`Ungil`] can cross the closure. See the
459 /// [module level documentation](self) for more information.
460 ///
461 /// If you need to pass Python objects into the closure you can use [`Py`]`<T>`to create a
462 /// reference independent of the GIL lifetime. However, you cannot do much with those without a
463 /// [`Python`] token, for which you'd need to reacquire the GIL.
464 ///
465 /// # Example: Releasing the GIL while running a computation in Rust-only code
466 ///
467 /// ```
468 /// use pyo3::prelude::*;
469 ///
470 /// #[pyfunction]
471 /// fn sum_numbers(py: Python<'_>, numbers: Vec<u32>) -> PyResult<u32> {
472 /// // We release the GIL here so any other Python threads get a chance to run.
473 /// py.allow_threads(move || {
474 /// // An example of an "expensive" Rust calculation
475 /// let sum = numbers.iter().sum();
476 ///
477 /// Ok(sum)
478 /// })
479 /// }
480 /// #
481 /// # fn main() -> PyResult<()> {
482 /// # Python::with_gil(|py| -> PyResult<()> {
483 /// # let fun = pyo3::wrap_pyfunction_bound!(sum_numbers, py)?;
484 /// # let res = fun.call1((vec![1_u32, 2, 3],))?;
485 /// # assert_eq!(res.extract::<u32>()?, 6_u32);
486 /// # Ok(())
487 /// # })
488 /// # }
489 /// ```
490 ///
491 /// Please see the [Parallelism] chapter of the guide for a thorough discussion of using
492 /// [`Python::allow_threads`] in this manner.
493 ///
494 /// # Example: Passing borrowed Python references into the closure is not allowed
495 ///
496 /// ```compile_fail
497 /// use pyo3::prelude::*;
498 /// use pyo3::types::PyString;
499 ///
500 /// fn parallel_print(py: Python<'_>) {
501 /// let s = PyString::new_bound(py, "This object cannot be accessed without holding the GIL >_<");
502 /// py.allow_threads(move || {
503 /// println!("{:?}", s); // This causes a compile error.
504 /// });
505 /// }
506 /// ```
507 ///
508 /// [`Py`]: crate::Py
509 /// [`PyString`]: crate::types::PyString
510 /// [auto-traits]: https://doc.rust-lang.org/nightly/unstable-book/language-features/auto-traits.html
511 /// [Parallelism]: https://pyo3.rs/main/parallelism.html
512 pub fn allow_threads<T, F>(self, f: F) -> T
513 where
514 F: Ungil + FnOnce() -> T,
515 T: Ungil,
516 {
517 // Use a guard pattern to handle reacquiring the GIL,
518 // so that the GIL will be reacquired even if `f` panics.
519 // The `Send` bound on the closure prevents the user from
520 // transferring the `Python` token into the closure.
521 let _guard = unsafe { SuspendGIL::new() };
522 f()
523 }
524
525 /// Deprecated version of [`Python::eval_bound`]
526 #[cfg(feature = "gil-refs")]
527 #[deprecated(
528 since = "0.21.0",
529 note = "`Python::eval` will be replaced by `Python::eval_bound` in a future PyO3 version"
530 )]
531 pub fn eval(
532 self,
533 code: &str,
534 globals: Option<&'py PyDict>,
535 locals: Option<&'py PyDict>,
536 ) -> PyResult<&'py PyAny> {
537 self.eval_bound(
538 code,
539 globals.map(PyNativeType::as_borrowed).as_deref(),
540 locals.map(PyNativeType::as_borrowed).as_deref(),
541 )
542 .map(Bound::into_gil_ref)
543 }
544
545 /// Evaluates a Python expression in the given context and returns the result.
546 ///
547 /// If `globals` is `None`, it defaults to Python module `__main__`.
548 /// If `locals` is `None`, it defaults to the value of `globals`.
549 ///
550 /// If `globals` doesn't contain `__builtins__`, default `__builtins__`
551 /// will be added automatically.
552 ///
553 /// # Examples
554 ///
555 /// ```
556 /// # use pyo3::prelude::*;
557 /// # Python::with_gil(|py| {
558 /// let result = py.eval_bound("[i * 10 for i in range(5)]", None, None).unwrap();
559 /// let res: Vec<i64> = result.extract().unwrap();
560 /// assert_eq!(res, vec![0, 10, 20, 30, 40])
561 /// # });
562 /// ```
563 pub fn eval_bound(
564 self,
565 code: &str,
566 globals: Option<&Bound<'py, PyDict>>,
567 locals: Option<&Bound<'py, PyDict>>,
568 ) -> PyResult<Bound<'py, PyAny>> {
569 self.run_code(code, ffi::Py_eval_input, globals, locals)
570 }
571
572 /// Deprecated version of [`Python::run_bound`]
573 #[cfg(feature = "gil-refs")]
574 #[deprecated(
575 since = "0.21.0",
576 note = "`Python::run` will be replaced by `Python::run_bound` in a future PyO3 version"
577 )]
578 pub fn run(
579 self,
580 code: &str,
581 globals: Option<&PyDict>,
582 locals: Option<&PyDict>,
583 ) -> PyResult<()> {
584 self.run_bound(
585 code,
586 globals.map(PyNativeType::as_borrowed).as_deref(),
587 locals.map(PyNativeType::as_borrowed).as_deref(),
588 )
589 }
590
591 /// Executes one or more Python statements in the given context.
592 ///
593 /// If `globals` is `None`, it defaults to Python module `__main__`.
594 /// If `locals` is `None`, it defaults to the value of `globals`.
595 ///
596 /// If `globals` doesn't contain `__builtins__`, default `__builtins__`
597 /// will be added automatically.
598 ///
599 /// # Examples
600 /// ```
601 /// use pyo3::{
602 /// prelude::*,
603 /// types::{PyBytes, PyDict},
604 /// };
605 /// Python::with_gil(|py| {
606 /// let locals = PyDict::new_bound(py);
607 /// py.run_bound(
608 /// r#"
609 /// import base64
610 /// s = 'Hello Rust!'
611 /// ret = base64.b64encode(s.encode('utf-8'))
612 /// "#,
613 /// None,
614 /// Some(&locals),
615 /// )
616 /// .unwrap();
617 /// let ret = locals.get_item("ret").unwrap().unwrap();
618 /// let b64 = ret.downcast::<PyBytes>().unwrap();
619 /// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE=");
620 /// });
621 /// ```
622 ///
623 /// You can use [`py_run!`](macro.py_run.html) for a handy alternative of `run`
624 /// if you don't need `globals` and unwrapping is OK.
625 pub fn run_bound(
626 self,
627 code: &str,
628 globals: Option<&Bound<'py, PyDict>>,
629 locals: Option<&Bound<'py, PyDict>>,
630 ) -> PyResult<()> {
631 let res = self.run_code(code, ffi::Py_file_input, globals, locals);
632 res.map(|obj| {
633 debug_assert!(obj.is_none());
634 })
635 }
636
637 /// Runs code in the given context.
638 ///
639 /// `start` indicates the type of input expected: one of `Py_single_input`,
640 /// `Py_file_input`, or `Py_eval_input`.
641 ///
642 /// If `globals` is `None`, it defaults to Python module `__main__`.
643 /// If `locals` is `None`, it defaults to the value of `globals`.
644 fn run_code(
645 self,
646 code: &str,
647 start: c_int,
648 globals: Option<&Bound<'py, PyDict>>,
649 locals: Option<&Bound<'py, PyDict>>,
650 ) -> PyResult<Bound<'py, PyAny>> {
651 let code = CString::new(code)?;
652 unsafe {
653 let mptr = ffi::PyImport_AddModule(ffi::c_str!("__main__").as_ptr());
654 if mptr.is_null() {
655 return Err(PyErr::fetch(self));
656 }
657
658 let globals = globals
659 .map(|dict| dict.as_ptr())
660 .unwrap_or_else(|| ffi::PyModule_GetDict(mptr));
661 let locals = locals.map(|dict| dict.as_ptr()).unwrap_or(globals);
662
663 // If `globals` don't provide `__builtins__`, most of the code will fail if Python
664 // version is <3.10. That's probably not what user intended, so insert `__builtins__`
665 // for them.
666 //
667 // See also:
668 // - https://github.com/python/cpython/pull/24564 (the same fix in CPython 3.10)
669 // - https://github.com/PyO3/pyo3/issues/3370
670 let builtins_s = crate::intern!(self, "__builtins__").as_ptr();
671 let has_builtins = ffi::PyDict_Contains(globals, builtins_s);
672 if has_builtins == -1 {
673 return Err(PyErr::fetch(self));
674 }
675 if has_builtins == 0 {
676 // Inherit current builtins.
677 let builtins = ffi::PyEval_GetBuiltins();
678
679 // `PyDict_SetItem` doesn't take ownership of `builtins`, but `PyEval_GetBuiltins`
680 // seems to return a borrowed reference, so no leak here.
681 if ffi::PyDict_SetItem(globals, builtins_s, builtins) == -1 {
682 return Err(PyErr::fetch(self));
683 }
684 }
685
686 let code_obj =
687 ffi::Py_CompileString(code.as_ptr(), ffi::c_str!("<string>").as_ptr(), start);
688 if code_obj.is_null() {
689 return Err(PyErr::fetch(self));
690 }
691 let res_ptr = ffi::PyEval_EvalCode(code_obj, globals, locals);
692 ffi::Py_DECREF(code_obj);
693
694 res_ptr.assume_owned_or_err(self).downcast_into_unchecked()
695 }
696 }
697
698 /// Gets the Python type object for type `T`.
699 #[cfg(feature = "gil-refs")]
700 #[deprecated(
701 since = "0.21.0",
702 note = "`Python::get_type` will be replaced by `Python::get_type_bound` in a future PyO3 version"
703 )]
704 #[inline]
705 pub fn get_type<T>(self) -> &'py PyType
706 where
707 T: PyTypeInfo,
708 {
709 self.get_type_bound::<T>().into_gil_ref()
710 }
711
712 /// Gets the Python type object for type `T`.
713 #[inline]
714 pub fn get_type_bound<T>(self) -> Bound<'py, PyType>
715 where
716 T: PyTypeInfo,
717 {
718 T::type_object_bound(self)
719 }
720
721 /// Deprecated form of [`Python::import_bound`]
722 #[cfg(feature = "gil-refs")]
723 #[deprecated(
724 since = "0.21.0",
725 note = "`Python::import` will be replaced by `Python::import_bound` in a future PyO3 version"
726 )]
727 pub fn import<N>(self, name: N) -> PyResult<&'py PyModule>
728 where
729 N: IntoPy<Py<PyString>>,
730 {
731 Self::import_bound(self, name).map(Bound::into_gil_ref)
732 }
733
734 /// Imports the Python module with the specified name.
735 pub fn import_bound<N>(self, name: N) -> PyResult<Bound<'py, PyModule>>
736 where
737 N: IntoPy<Py<PyString>>,
738 {
739 PyModule::import_bound(self, name)
740 }
741
742 /// Gets the Python builtin value `None`.
743 #[allow(non_snake_case)] // the Python keyword starts with uppercase
744 #[inline]
745 pub fn None(self) -> PyObject {
746 PyNone::get_bound(self).into_py(self)
747 }
748
749 /// Gets the Python builtin value `Ellipsis`, or `...`.
750 #[allow(non_snake_case)] // the Python keyword starts with uppercase
751 #[inline]
752 pub fn Ellipsis(self) -> PyObject {
753 PyEllipsis::get_bound(self).into_py(self)
754 }
755
756 /// Gets the Python builtin value `NotImplemented`.
757 #[allow(non_snake_case)] // the Python keyword starts with uppercase
758 #[inline]
759 pub fn NotImplemented(self) -> PyObject {
760 PyNotImplemented::get_bound(self).into_py(self)
761 }
762
763 /// Gets the running Python interpreter version as a string.
764 ///
765 /// # Examples
766 /// ```rust
767 /// # use pyo3::Python;
768 /// Python::with_gil(|py| {
769 /// // The full string could be, for example:
770 /// // "3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]"
771 /// assert!(py.version().starts_with("3."));
772 /// });
773 /// ```
774 pub fn version(self) -> &'py str {
775 unsafe {
776 CStr::from_ptr(ffi::Py_GetVersion())
777 .to_str()
778 .expect("Python version string not UTF-8")
779 }
780 }
781
782 /// Gets the running Python interpreter version as a struct similar to
783 /// `sys.version_info`.
784 ///
785 /// # Examples
786 /// ```rust
787 /// # use pyo3::Python;
788 /// Python::with_gil(|py| {
789 /// // PyO3 supports Python 3.7 and up.
790 /// assert!(py.version_info() >= (3, 7));
791 /// assert!(py.version_info() >= (3, 7, 0));
792 /// });
793 /// ```
794 pub fn version_info(self) -> PythonVersionInfo<'py> {
795 let version_str = self.version();
796
797 // Portion of the version string returned by Py_GetVersion up to the first space is the
798 // version number.
799 let version_number_str = version_str.split(' ').next().unwrap_or(version_str);
800
801 PythonVersionInfo::from_str(version_number_str).unwrap()
802 }
803
804 /// Registers the object in the release pool, and tries to downcast to specific type.
805 #[cfg(feature = "gil-refs")]
806 #[deprecated(
807 since = "0.21.0",
808 note = "use `obj.downcast_bound::<T>(py)` instead of `py.checked_cast_as::<T>(obj)`"
809 )]
810 pub fn checked_cast_as<T>(
811 self,
812 obj: PyObject,
813 ) -> Result<&'py T, crate::err::PyDowncastError<'py>>
814 where
815 T: crate::PyTypeCheck<AsRefTarget = T>,
816 {
817 #[allow(deprecated)]
818 obj.into_ref(self).downcast()
819 }
820
821 /// Registers the object in the release pool, and does an unchecked downcast
822 /// to the specific type.
823 ///
824 /// # Safety
825 ///
826 /// Callers must ensure that ensure that the cast is valid.
827 #[cfg(feature = "gil-refs")]
828 #[deprecated(
829 since = "0.21.0",
830 note = "use `obj.downcast_bound_unchecked::<T>(py)` instead of `py.cast_as::<T>(obj)`"
831 )]
832 pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
833 where
834 T: crate::type_object::HasPyGilRef<AsRefTarget = T>,
835 {
836 #[allow(deprecated)]
837 obj.into_ref(self).downcast_unchecked()
838 }
839
840 /// Registers the object pointer in the release pool,
841 /// and does an unchecked downcast to the specific type.
842 ///
843 /// # Safety
844 ///
845 /// Callers must ensure that ensure that the cast is valid.
846 #[allow(clippy::wrong_self_convention, deprecated)]
847 #[cfg(feature = "gil-refs")]
848 #[deprecated(
849 since = "0.21.0",
850 note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead"
851 )]
852 pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'py T
853 where
854 T: FromPyPointer<'py>,
855 {
856 FromPyPointer::from_owned_ptr(self, ptr)
857 }
858
859 /// Registers the owned object pointer in the release pool.
860 ///
861 /// Returns `Err(PyErr)` if the pointer is NULL.
862 /// Does an unchecked downcast to the specific type.
863 ///
864 /// # Safety
865 ///
866 /// Callers must ensure that ensure that the cast is valid.
867 #[allow(clippy::wrong_self_convention, deprecated)]
868 #[cfg(feature = "gil-refs")]
869 #[deprecated(
870 since = "0.21.0",
871 note = "use `Py::from_owned_ptr_or_err(py, ptr)` or `Bound::from_owned_ptr_or_err(py, ptr)` instead"
872 )]
873 pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'py T>
874 where
875 T: FromPyPointer<'py>,
876 {
877 FromPyPointer::from_owned_ptr_or_err(self, ptr)
878 }
879
880 /// Registers the owned object pointer in release pool.
881 ///
882 /// Returns `None` if the pointer is NULL.
883 /// Does an unchecked downcast to the specific type.
884 ///
885 /// # Safety
886 ///
887 /// Callers must ensure that ensure that the cast is valid.
888 #[allow(clippy::wrong_self_convention, deprecated)]
889 #[cfg(feature = "gil-refs")]
890 #[deprecated(
891 since = "0.21.0",
892 note = "use `Py::from_owned_ptr_or_opt(py, ptr)` or `Bound::from_owned_ptr_or_opt(py, ptr)` instead"
893 )]
894 pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'py T>
895 where
896 T: FromPyPointer<'py>,
897 {
898 FromPyPointer::from_owned_ptr_or_opt(self, ptr)
899 }
900
901 /// Does an unchecked downcast to the specific type.
902 ///
903 /// Panics if the pointer is NULL.
904 ///
905 /// # Safety
906 ///
907 /// Callers must ensure that ensure that the cast is valid.
908 #[allow(clippy::wrong_self_convention, deprecated)]
909 #[cfg(feature = "gil-refs")]
910 #[deprecated(
911 since = "0.21.0",
912 note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead"
913 )]
914 pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'py T
915 where
916 T: FromPyPointer<'py>,
917 {
918 FromPyPointer::from_borrowed_ptr(self, ptr)
919 }
920
921 /// Does an unchecked downcast to the specific type.
922 ///
923 /// Returns `Err(PyErr)` if the pointer is NULL.
924 ///
925 /// # Safety
926 ///
927 /// Callers must ensure that ensure that the cast is valid.
928 #[allow(clippy::wrong_self_convention, deprecated)]
929 #[cfg(feature = "gil-refs")]
930 #[deprecated(
931 since = "0.21.0",
932 note = "use `Py::from_borrowed_ptr_or_err(py, ptr)` or `Bound::from_borrowed_ptr_or_err(py, ptr)` instead"
933 )]
934 pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'py T>
935 where
936 T: FromPyPointer<'py>,
937 {
938 FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
939 }
940
941 /// Does an unchecked downcast to the specific type.
942 ///
943 /// Returns `None` if the pointer is NULL.
944 ///
945 /// # Safety
946 ///
947 /// Callers must ensure that ensure that the cast is valid.
948 #[allow(clippy::wrong_self_convention, deprecated)]
949 #[cfg(feature = "gil-refs")]
950 #[deprecated(
951 since = "0.21.0",
952 note = "use `Py::from_borrowed_ptr_or_opt(py, ptr)` or `Bound::from_borrowed_ptr_or_opt(py, ptr)` instead"
953 )]
954 pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'py T>
955 where
956 T: FromPyPointer<'py>,
957 {
958 FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
959 }
960
961 /// Lets the Python interpreter check and handle any pending signals. This will invoke the
962 /// corresponding signal handlers registered in Python (if any).
963 ///
964 /// Returns `Err(`[`PyErr`]`)` if any signal handler raises an exception.
965 ///
966 /// These signals include `SIGINT` (normally raised by CTRL + C), which by default raises
967 /// `KeyboardInterrupt`. For this reason it is good practice to call this function regularly
968 /// as part of long-running Rust functions so that users can cancel it.
969 ///
970 /// # Example
971 ///
972 /// ```rust
973 /// # #![allow(dead_code)] // this example is quite impractical to test
974 /// use pyo3::prelude::*;
975 ///
976 /// # fn main() {
977 /// #[pyfunction]
978 /// fn loop_forever(py: Python<'_>) -> PyResult<()> {
979 /// loop {
980 /// // As this loop is infinite it should check for signals every once in a while.
981 /// // Using `?` causes any `PyErr` (potentially containing `KeyboardInterrupt`)
982 /// // to break out of the loop.
983 /// py.check_signals()?;
984 ///
985 /// // do work here
986 /// # break Ok(()) // don't actually loop forever
987 /// }
988 /// }
989 /// # }
990 /// ```
991 ///
992 /// # Note
993 ///
994 /// This function calls [`PyErr_CheckSignals()`][1] which in turn may call signal handlers.
995 /// As Python's [`signal`][2] API allows users to define custom signal handlers, calling this
996 /// function allows arbitrary Python code inside signal handlers to run.
997 ///
998 /// If the function is called from a non-main thread, or under a non-main Python interpreter,
999 /// it does nothing yet still returns `Ok(())`.
1000 ///
1001 /// [1]: https://docs.python.org/3/c-api/exceptions.html?highlight=pyerr_checksignals#c.PyErr_CheckSignals
1002 /// [2]: https://docs.python.org/3/library/signal.html
1003 pub fn check_signals(self) -> PyResult<()> {
1004 err::error_on_minusone(self, unsafe { ffi::PyErr_CheckSignals() })
1005 }
1006
1007 /// Create a new pool for managing PyO3's GIL Refs. This has no functional
1008 /// use for code which does not use the deprecated GIL Refs API.
1009 ///
1010 /// When this `GILPool` is dropped, all GIL Refs created after this `GILPool` will
1011 /// all have their Python reference counts decremented, potentially allowing Python to drop
1012 /// the corresponding Python objects.
1013 ///
1014 /// Typical usage of PyO3 will not need this API, as [`Python::with_gil`] automatically creates
1015 /// a `GILPool` where appropriate.
1016 ///
1017 /// Advanced uses of PyO3 which perform long-running tasks which never free the GIL may need
1018 /// to use this API to clear memory, as PyO3 usually does not clear memory until the GIL is
1019 /// released.
1020 ///
1021 /// # Examples
1022 ///
1023 /// ```rust
1024 /// # use pyo3::prelude::*;
1025 /// Python::with_gil(|py| {
1026 /// // Some long-running process like a webserver, which never releases the GIL.
1027 /// loop {
1028 /// // Create a new pool, so that PyO3 can clear memory at the end of the loop.
1029 /// #[allow(deprecated)] // `new_pool` is not needed in code not using the GIL Refs API
1030 /// let pool = unsafe { py.new_pool() };
1031 ///
1032 /// // It is recommended to *always* immediately set py to the pool's Python, to help
1033 /// // avoid creating references with invalid lifetimes.
1034 /// let py = pool.python();
1035 ///
1036 /// // do stuff...
1037 /// # break; // Exit the loop so that doctest terminates!
1038 /// }
1039 /// });
1040 /// ```
1041 ///
1042 /// # Safety
1043 ///
1044 /// Extreme care must be taken when using this API, as misuse can lead to accessing invalid
1045 /// memory. In addition, the caller is responsible for guaranteeing that the GIL remains held
1046 /// for the entire lifetime of the returned `GILPool`.
1047 ///
1048 /// Two best practices are required when using this API:
1049 /// - From the moment `new_pool()` is called, only the `Python` token from the returned
1050 /// `GILPool` (accessible using [`.python()`]) should be used in PyO3 APIs. All other older
1051 /// `Python` tokens with longer lifetimes are unsafe to use until the `GILPool` is dropped,
1052 /// because they can be used to create PyO3 owned references which have lifetimes which
1053 /// outlive the `GILPool`.
1054 /// - Similarly, methods on existing owned references will implicitly refer back to the
1055 /// `Python` token which that reference was originally created with. If the returned values
1056 /// from these methods are owned references they will inherit the same lifetime. As a result,
1057 /// Rust's lifetime rules may allow them to outlive the `GILPool`, even though this is not
1058 /// safe for reasons discussed above. Care must be taken to never access these return values
1059 /// after the `GILPool` is dropped, unless they are converted to `Py<T>` *before* the pool
1060 /// is dropped.
1061 ///
1062 /// [`.python()`]: crate::GILPool::python
1063 #[inline]
1064 #[cfg(feature = "gil-refs")]
1065 #[deprecated(
1066 since = "0.21.0",
1067 note = "code not using the GIL Refs API can safely remove use of `Python::new_pool`"
1068 )]
1069 #[allow(deprecated)]
1070 pub unsafe fn new_pool(self) -> GILPool {
1071 GILPool::new()
1072 }
1073}
1074
1075impl Python<'_> {
1076 /// Creates a scope using a new pool for managing PyO3's GIL Refs. This has no functional
1077 /// use for code which does not use the deprecated GIL Refs API.
1078 ///
1079 /// This is a safe alterantive to [`new_pool`][Self::new_pool] as
1080 /// it limits the closure to using the new GIL token at the cost of
1081 /// being unable to capture existing GIL-bound references.
1082 ///
1083 /// Note that on stable Rust, this API suffers from the same the `SendWrapper` loophole
1084 /// as [`allow_threads`][Self::allow_threads], c.f. the documentation of the [`Ungil`] trait,
1085 ///
1086 /// # Examples
1087 ///
1088 /// ```rust
1089 /// # use pyo3::prelude::*;
1090 /// Python::with_gil(|py| {
1091 /// // Some long-running process like a webserver, which never releases the GIL.
1092 /// loop {
1093 /// // Create a new scope, so that PyO3 can clear memory at the end of the loop.
1094 /// #[allow(deprecated)] // `with_pool` is not needed in code not using the GIL Refs API
1095 /// py.with_pool(|py| {
1096 /// // do stuff...
1097 /// });
1098 /// # break; // Exit the loop so that doctest terminates!
1099 /// }
1100 /// });
1101 /// ```
1102 ///
1103 /// The `Ungil` bound on the closure does prevent hanging on to existing GIL-bound references
1104 ///
1105 /// ```compile_fail
1106 /// # #![allow(deprecated)]
1107 /// # use pyo3::prelude::*;
1108 /// # use pyo3::types::PyString;
1109 ///
1110 /// Python::with_gil(|py| {
1111 /// let old_str = PyString::new(py, "a message from the past");
1112 ///
1113 /// py.with_pool(|_py| {
1114 /// print!("{:?}", old_str);
1115 /// });
1116 /// });
1117 /// ```
1118 ///
1119 /// or continuing to use the old GIL token
1120 ///
1121 /// ```compile_fail
1122 /// # use pyo3::prelude::*;
1123 ///
1124 /// Python::with_gil(|old_py| {
1125 /// old_py.with_pool(|_new_py| {
1126 /// let _none = old_py.None();
1127 /// });
1128 /// });
1129 /// ```
1130 #[inline]
1131 #[cfg(feature = "gil-refs")]
1132 #[deprecated(
1133 since = "0.21.0",
1134 note = "code not using the GIL Refs API can safely remove use of `Python::with_pool`"
1135 )]
1136 #[allow(deprecated)]
1137 pub fn with_pool<F, R>(&self, f: F) -> R
1138 where
1139 F: for<'py> FnOnce(Python<'py>) -> R + Ungil,
1140 {
1141 // SAFETY: The closure is `Ungil`,
1142 // i.e. it does not capture any GIL-bound references
1143 // and accesses only the newly created GIL token.
1144 let pool = unsafe { GILPool::new() };
1145
1146 f(pool.python())
1147 }
1148}
1149
1150impl<'unbound> Python<'unbound> {
1151 /// Unsafely creates a Python token with an unbounded lifetime.
1152 ///
1153 /// Many of PyO3 APIs use `Python<'_>` as proof that the GIL is held, but this function can be
1154 /// used to call them unsafely.
1155 ///
1156 /// # Safety
1157 ///
1158 /// - This token and any borrowed Python references derived from it can only be safely used
1159 /// whilst the currently executing thread is actually holding the GIL.
1160 /// - This function creates a token with an *unbounded* lifetime. Safe code can assume that
1161 /// holding a `Python<'py>` token means the GIL is and stays acquired for the lifetime `'py`.
1162 /// If you let it or borrowed Python references escape to safe code you are
1163 /// responsible for bounding the lifetime `'unbound` appropriately. For more on unbounded
1164 /// lifetimes, see the [nomicon].
1165 ///
1166 /// [nomicon]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html
1167 #[inline]
1168 pub unsafe fn assume_gil_acquired() -> Python<'unbound> {
1169 Python(PhantomData)
1170 }
1171}
1172
1173#[cfg(test)]
1174mod tests {
1175 use super::*;
1176 use crate::types::{IntoPyDict, PyList};
1177
1178 #[test]
1179 fn test_eval() {
1180 Python::with_gil(|py| {
1181 // Make sure builtin names are accessible
1182 let v: i32 = py
1183 .eval_bound("min(1, 2)", None, None)
1184 .map_err(|e| e.display(py))
1185 .unwrap()
1186 .extract()
1187 .unwrap();
1188 assert_eq!(v, 1);
1189
1190 let d = [("foo", 13)].into_py_dict_bound(py);
1191
1192 // Inject our own global namespace
1193 let v: i32 = py
1194 .eval_bound("foo + 29", Some(&d), None)
1195 .unwrap()
1196 .extract()
1197 .unwrap();
1198 assert_eq!(v, 42);
1199
1200 // Inject our own local namespace
1201 let v: i32 = py
1202 .eval_bound("foo + 29", None, Some(&d))
1203 .unwrap()
1204 .extract()
1205 .unwrap();
1206 assert_eq!(v, 42);
1207
1208 // Make sure builtin names are still accessible when using a local namespace
1209 let v: i32 = py
1210 .eval_bound("min(foo, 2)", None, Some(&d))
1211 .unwrap()
1212 .extract()
1213 .unwrap();
1214 assert_eq!(v, 2);
1215 });
1216 }
1217
1218 #[test]
1219 #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled
1220 fn test_allow_threads_releases_and_acquires_gil() {
1221 Python::with_gil(|py| {
1222 let b = std::sync::Arc::new(std::sync::Barrier::new(2));
1223
1224 let b2 = b.clone();
1225 std::thread::spawn(move || Python::with_gil(|_| b2.wait()));
1226
1227 py.allow_threads(|| {
1228 // If allow_threads does not release the GIL, this will deadlock because
1229 // the thread spawned above will never be able to acquire the GIL.
1230 b.wait();
1231 });
1232
1233 unsafe {
1234 // If the GIL is not reacquired at the end of allow_threads, this call
1235 // will crash the Python interpreter.
1236 let tstate = ffi::PyEval_SaveThread();
1237 ffi::PyEval_RestoreThread(tstate);
1238 }
1239 });
1240 }
1241
1242 #[test]
1243 fn test_allow_threads_panics_safely() {
1244 Python::with_gil(|py| {
1245 let result = std::panic::catch_unwind(|| unsafe {
1246 let py = Python::assume_gil_acquired();
1247 py.allow_threads(|| {
1248 panic!("There was a panic!");
1249 });
1250 });
1251
1252 // Check panic was caught
1253 assert!(result.is_err());
1254
1255 // If allow_threads is implemented correctly, this thread still owns the GIL here
1256 // so the following Python calls should not cause crashes.
1257 let list = PyList::new_bound(py, [1, 2, 3, 4]);
1258 assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![1, 2, 3, 4]);
1259 });
1260 }
1261
1262 #[cfg(not(pyo3_disable_reference_pool))]
1263 #[test]
1264 fn test_allow_threads_pass_stuff_in() {
1265 let list = Python::with_gil(|py| PyList::new_bound(py, vec!["foo", "bar"]).unbind());
1266 let mut v = vec![1, 2, 3];
1267 let a = std::sync::Arc::new(String::from("foo"));
1268
1269 Python::with_gil(|py| {
1270 py.allow_threads(|| {
1271 drop((list, &mut v, a));
1272 });
1273 });
1274 }
1275
1276 #[test]
1277 #[cfg(not(Py_LIMITED_API))]
1278 fn test_acquire_gil() {
1279 const GIL_NOT_HELD: c_int = 0;
1280 const GIL_HELD: c_int = 1;
1281
1282 // Before starting the interpreter the state of calling `PyGILState_Check`
1283 // seems to be undefined, so let's ensure that Python is up.
1284 #[cfg(not(any(PyPy, GraalPy)))]
1285 crate::prepare_freethreaded_python();
1286
1287 let state = unsafe { crate::ffi::PyGILState_Check() };
1288 assert_eq!(state, GIL_NOT_HELD);
1289
1290 Python::with_gil(|_| {
1291 let state = unsafe { crate::ffi::PyGILState_Check() };
1292 assert_eq!(state, GIL_HELD);
1293 });
1294
1295 let state = unsafe { crate::ffi::PyGILState_Check() };
1296 assert_eq!(state, GIL_NOT_HELD);
1297 }
1298
1299 #[test]
1300 fn test_ellipsis() {
1301 Python::with_gil(|py| {
1302 assert_eq!(py.Ellipsis().to_string(), "Ellipsis");
1303
1304 let v = py
1305 .eval_bound("...", None, None)
1306 .map_err(|e| e.display(py))
1307 .unwrap();
1308
1309 assert!(v.eq(py.Ellipsis()).unwrap());
1310 });
1311 }
1312
1313 #[test]
1314 fn test_py_run_inserts_globals() {
1315 use crate::types::dict::PyDictMethods;
1316
1317 Python::with_gil(|py| {
1318 let namespace = PyDict::new_bound(py);
1319 py.run_bound("class Foo: pass", Some(&namespace), Some(&namespace))
1320 .unwrap();
1321 assert!(matches!(namespace.get_item("Foo"), Ok(Some(..))));
1322 assert!(matches!(namespace.get_item("__builtins__"), Ok(Some(..))));
1323 })
1324 }
1325}