pyo3/types/
module.rs

1use crate::err::{PyErr, PyResult};
2use crate::ffi_ptr_ext::FfiPtrExt;
3use crate::impl_::callback::IntoPyCallbackOutput;
4use crate::py_result_ext::PyResultExt;
5use crate::pyclass::PyClass;
6use crate::types::{
7    any::PyAnyMethods, list::PyListMethods, PyAny, PyCFunction, PyDict, PyList, PyString,
8};
9use crate::{
10    exceptions, ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, PyObject, Python,
11};
12use std::ffi::CStr;
13#[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
14use std::os::raw::c_int;
15use std::str;
16
17/// Represents a Python [`module`][1] object.
18///
19/// Values of this type are accessed via PyO3's smart pointers, e.g. as
20/// [`Py<PyModule>`][crate::Py] or [`Bound<'py, PyModule>`][Bound].
21///
22/// For APIs available on `module` objects, see the [`PyModuleMethods`] trait which is implemented for
23/// [`Bound<'py, PyModule>`][Bound].
24///
25/// As with all other Python objects, modules are first class citizens.
26/// This means they can be passed to or returned from functions,
27/// created dynamically, assigned to variables and so forth.
28///
29/// [1]: https://docs.python.org/3/tutorial/modules.html
30#[repr(transparent)]
31pub struct PyModule(PyAny);
32
33pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check);
34
35impl PyModule {
36    /// Creates a new module object with the `__name__` attribute set to `name`.
37    ///
38    /// # Examples
39    ///
40    /// ``` rust
41    /// use pyo3::prelude::*;
42    ///
43    /// # fn main() -> PyResult<()> {
44    /// Python::with_gil(|py| -> PyResult<()> {
45    ///     let module = PyModule::new(py, "my_module")?;
46    ///
47    ///     assert_eq!(module.name()?, "my_module");
48    ///     Ok(())
49    /// })?;
50    /// # Ok(())}
51    ///  ```
52    pub fn new<'py>(py: Python<'py>, name: &str) -> PyResult<Bound<'py, PyModule>> {
53        let name = PyString::new(py, name);
54        unsafe {
55            ffi::PyModule_NewObject(name.as_ptr())
56                .assume_owned_or_err(py)
57                .downcast_into_unchecked()
58        }
59    }
60
61    /// Imports the Python module with the specified name.
62    ///
63    /// # Examples
64    ///
65    /// ```no_run
66    /// # fn main() {
67    /// use pyo3::prelude::*;
68    ///
69    /// Python::with_gil(|py| {
70    ///     let module = PyModule::import(py, "antigravity").expect("No flying for you.");
71    /// });
72    /// # }
73    ///  ```
74    ///
75    /// This is equivalent to the following Python expression:
76    /// ```python
77    /// import antigravity
78    /// ```
79    ///
80    /// If you want to import a class, you can store a reference to it with
81    /// [`GILOnceCell::import`][crate::sync::GILOnceCell#method.import].
82    pub fn import<'py, N>(py: Python<'py>, name: N) -> PyResult<Bound<'py, PyModule>>
83    where
84        N: IntoPyObject<'py, Target = PyString>,
85    {
86        let name = name.into_pyobject_or_pyerr(py)?;
87        unsafe {
88            ffi::PyImport_Import(name.as_ptr())
89                .assume_owned_or_err(py)
90                .downcast_into_unchecked()
91        }
92    }
93
94    /// Creates and loads a module named `module_name`,
95    /// containing the Python code passed to `code`
96    /// and pretending to live at `file_name`.
97    ///
98    /// <div class="information">
99    ///     <div class="tooltip compile_fail" style="">&#x26a0; &#xfe0f;</div>
100    /// </div><div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
101    //
102    ///  <strong>Warning</strong>: This will compile and execute code. <strong>Never</strong> pass untrusted code to this function!
103    ///
104    /// </pre></div>
105    ///
106    /// # Errors
107    ///
108    /// Returns `PyErr` if:
109    /// - `code` is not syntactically correct Python.
110    /// - Any Python exceptions are raised while initializing the module.
111    /// - Any of the arguments cannot be converted to [`CString`][std::ffi::CString]s.
112    ///
113    /// # Example: bundle in a file at compile time with [`include_str!`][std::include_str]:
114    ///
115    /// ```rust
116    /// use pyo3::prelude::*;
117    /// use pyo3::ffi::c_str;
118    ///
119    /// # fn main() -> PyResult<()> {
120    /// // This path is resolved relative to this file.
121    /// let code = c_str!(include_str!("../../assets/script.py"));
122    ///
123    /// Python::with_gil(|py| -> PyResult<()> {
124    ///     PyModule::from_code(py, code, c_str!("example.py"), c_str!("example"))?;
125    ///     Ok(())
126    /// })?;
127    /// # Ok(())
128    /// # }
129    /// ```
130    ///
131    /// # Example: Load a file at runtime with [`std::fs::read_to_string`].
132    ///
133    /// ```rust
134    /// use pyo3::prelude::*;
135    /// use pyo3::ffi::c_str;
136    /// use std::ffi::CString;
137    ///
138    /// # fn main() -> PyResult<()> {
139    /// // This path is resolved by however the platform resolves paths,
140    /// // which also makes this less portable. Consider using `include_str`
141    /// // if you just want to bundle a script with your module.
142    /// let code = std::fs::read_to_string("assets/script.py")?;
143    ///
144    /// Python::with_gil(|py| -> PyResult<()> {
145    ///     PyModule::from_code(py, CString::new(code)?.as_c_str(), c_str!("example.py"), c_str!("example"))?;
146    ///     Ok(())
147    /// })?;
148    /// Ok(())
149    /// # }
150    /// ```
151    pub fn from_code<'py>(
152        py: Python<'py>,
153        code: &CStr,
154        file_name: &CStr,
155        module_name: &CStr,
156    ) -> PyResult<Bound<'py, PyModule>> {
157        unsafe {
158            let code = ffi::Py_CompileString(code.as_ptr(), file_name.as_ptr(), ffi::Py_file_input)
159                .assume_owned_or_err(py)?;
160
161            ffi::PyImport_ExecCodeModuleEx(module_name.as_ptr(), code.as_ptr(), file_name.as_ptr())
162                .assume_owned_or_err(py)
163                .downcast_into()
164        }
165    }
166}
167
168/// Implementation of functionality for [`PyModule`].
169///
170/// These methods are defined for the `Bound<'py, PyModule>` smart pointer, so to use method call
171/// syntax these methods are separated into a trait, because stable Rust does not yet support
172/// `arbitrary_self_types`.
173#[doc(alias = "PyModule")]
174pub trait PyModuleMethods<'py>: crate::sealed::Sealed {
175    /// Returns the module's `__dict__` attribute, which contains the module's symbol table.
176    fn dict(&self) -> Bound<'py, PyDict>;
177
178    /// Returns the index (the `__all__` attribute) of the module,
179    /// creating one if needed.
180    ///
181    /// `__all__` declares the items that will be imported with `from my_module import *`.
182    fn index(&self) -> PyResult<Bound<'py, PyList>>;
183
184    /// Returns the name (the `__name__` attribute) of the module.
185    ///
186    /// May fail if the module does not have a `__name__` attribute.
187    fn name(&self) -> PyResult<Bound<'py, PyString>>;
188
189    /// Returns the filename (the `__file__` attribute) of the module.
190    ///
191    /// May fail if the module does not have a `__file__` attribute.
192    fn filename(&self) -> PyResult<Bound<'py, PyString>>;
193
194    /// Adds an attribute to the module.
195    ///
196    /// For adding classes, functions or modules, prefer to use [`PyModuleMethods::add_class`],
197    /// [`PyModuleMethods::add_function`] or [`PyModuleMethods::add_submodule`] instead,
198    /// respectively.
199    ///
200    /// # Examples
201    ///
202    /// ```rust,no_run
203    /// use pyo3::prelude::*;
204    ///
205    /// #[pymodule]
206    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
207    ///     module.add("c", 299_792_458)?;
208    ///     Ok(())
209    /// }
210    /// ```
211    ///
212    /// Python code can then do the following:
213    ///
214    /// ```python
215    /// from my_module import c
216    ///
217    /// print("c is", c)
218    /// ```
219    ///
220    /// This will result in the following output:
221    ///
222    /// ```text
223    /// c is 299792458
224    /// ```
225    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
226    where
227        N: IntoPyObject<'py, Target = PyString>,
228        V: IntoPyObject<'py>;
229
230    /// Adds a new class to the module.
231    ///
232    /// Notice that this method does not take an argument.
233    /// Instead, this method is *generic*, and requires us to use the
234    /// "turbofish" syntax to specify the class we want to add.
235    ///
236    /// # Examples
237    ///
238    /// ```rust,no_run
239    /// use pyo3::prelude::*;
240    ///
241    /// #[pyclass]
242    /// struct Foo { /* fields omitted */ }
243    ///
244    /// #[pymodule]
245    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
246    ///     module.add_class::<Foo>()?;
247    ///     Ok(())
248    /// }
249    ///  ```
250    ///
251    /// Python code can see this class as such:
252    /// ```python
253    /// from my_module import Foo
254    ///
255    /// print("Foo is", Foo)
256    /// ```
257    ///
258    /// This will result in the following output:
259    /// ```text
260    /// Foo is <class 'builtins.Foo'>
261    /// ```
262    ///
263    /// Note that as we haven't defined a [constructor][1], Python code can't actually
264    /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported
265    /// anything that can return instances of `Foo`).
266    ///
267    #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")]
268    fn add_class<T>(&self) -> PyResult<()>
269    where
270        T: PyClass;
271
272    /// Adds a function or a (sub)module to a module, using the functions name as name.
273    ///
274    /// Prefer to use [`PyModuleMethods::add_function`] and/or [`PyModuleMethods::add_submodule`]
275    /// instead.
276    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
277    where
278        T: IntoPyCallbackOutput<'py, PyObject>;
279
280    /// Adds a submodule to a module.
281    ///
282    /// This is especially useful for creating module hierarchies.
283    ///
284    /// Note that this doesn't define a *package*, so this won't allow Python code
285    /// to directly import submodules by using
286    /// <span style="white-space: pre">`from my_module import submodule`</span>.
287    /// For more information, see [#759][1] and [#1517][2].
288    ///
289    /// # Examples
290    ///
291    /// ```rust,no_run
292    /// use pyo3::prelude::*;
293    ///
294    /// #[pymodule]
295    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
296    ///     let submodule = PyModule::new(py, "submodule")?;
297    ///     submodule.add("super_useful_constant", "important")?;
298    ///
299    ///     module.add_submodule(&submodule)?;
300    ///     Ok(())
301    /// }
302    /// ```
303    ///
304    /// Python code can then do the following:
305    ///
306    /// ```python
307    /// import my_module
308    ///
309    /// print("super_useful_constant is", my_module.submodule.super_useful_constant)
310    /// ```
311    ///
312    /// This will result in the following output:
313    ///
314    /// ```text
315    /// super_useful_constant is important
316    /// ```
317    ///
318    /// [1]: https://github.com/PyO3/pyo3/issues/759
319    /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021
320    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()>;
321
322    /// Add a function to a module.
323    ///
324    /// Note that this also requires the [`wrap_pyfunction!`][2] macro
325    /// to wrap a function annotated with [`#[pyfunction]`][1].
326    ///
327    /// ```rust,no_run
328    /// use pyo3::prelude::*;
329    ///
330    /// #[pyfunction]
331    /// fn say_hello() {
332    ///     println!("Hello world!")
333    /// }
334    /// #[pymodule]
335    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
336    ///     module.add_function(wrap_pyfunction!(say_hello, module)?)
337    /// }
338    /// ```
339    ///
340    /// Python code can then do the following:
341    ///
342    /// ```python
343    /// from my_module import say_hello
344    ///
345    /// say_hello()
346    /// ```
347    ///
348    /// This will result in the following output:
349    ///
350    /// ```text
351    /// Hello world!
352    /// ```
353    ///
354    /// [1]: crate::prelude::pyfunction
355    /// [2]: crate::wrap_pyfunction
356    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()>;
357
358    /// Declare whether or not this module supports running with the GIL disabled
359    ///
360    /// If the module does not rely on the GIL for thread safety, you can pass
361    /// `false` to this function to indicate the module does not rely on the GIL
362    /// for thread-safety.
363    ///
364    /// This function sets the [`Py_MOD_GIL`
365    /// slot](https://docs.python.org/3/c-api/module.html#c.Py_mod_gil) on the
366    /// module object. The default is `Py_MOD_GIL_USED`, so passing `true` to
367    /// this function is a no-op unless you have already set `Py_MOD_GIL` to
368    /// `Py_MOD_GIL_NOT_USED` elsewhere.
369    ///
370    /// # Examples
371    ///
372    /// ```rust,no_run
373    /// use pyo3::prelude::*;
374    ///
375    /// #[pymodule(gil_used = false)]
376    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
377    ///     let submodule = PyModule::new(py, "submodule")?;
378    ///     submodule.gil_used(false)?;
379    ///     module.add_submodule(&submodule)?;
380    ///     Ok(())
381    /// }
382    /// ```
383    ///
384    /// The resulting module will not print a `RuntimeWarning` and re-enable the
385    /// GIL when Python imports it on the free-threaded build, since all module
386    /// objects defined in the extension have `Py_MOD_GIL` set to
387    /// `Py_MOD_GIL_NOT_USED`.
388    ///
389    /// This is a no-op on the GIL-enabled build.
390    fn gil_used(&self, gil_used: bool) -> PyResult<()>;
391}
392
393impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> {
394    fn dict(&self) -> Bound<'py, PyDict> {
395        unsafe {
396            // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890).
397            ffi::PyModule_GetDict(self.as_ptr())
398                .assume_borrowed(self.py())
399                .to_owned()
400                .downcast_into_unchecked()
401        }
402    }
403
404    fn index(&self) -> PyResult<Bound<'py, PyList>> {
405        let __all__ = __all__(self.py());
406        match self.getattr(__all__) {
407            Ok(idx) => idx.downcast_into().map_err(PyErr::from),
408            Err(err) => {
409                if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) {
410                    let l = PyList::empty(self.py());
411                    self.setattr(__all__, &l)?;
412                    Ok(l)
413                } else {
414                    Err(err)
415                }
416            }
417        }
418    }
419
420    fn name(&self) -> PyResult<Bound<'py, PyString>> {
421        #[cfg(not(PyPy))]
422        {
423            unsafe {
424                ffi::PyModule_GetNameObject(self.as_ptr())
425                    .assume_owned_or_err(self.py())
426                    .downcast_into_unchecked()
427            }
428        }
429
430        #[cfg(PyPy)]
431        {
432            self.dict()
433                .get_item("__name__")
434                .map_err(|_| exceptions::PyAttributeError::new_err("__name__"))?
435                .downcast_into()
436                .map_err(PyErr::from)
437        }
438    }
439
440    fn filename(&self) -> PyResult<Bound<'py, PyString>> {
441        #[cfg(not(PyPy))]
442        unsafe {
443            ffi::PyModule_GetFilenameObject(self.as_ptr())
444                .assume_owned_or_err(self.py())
445                .downcast_into_unchecked()
446        }
447
448        #[cfg(PyPy)]
449        {
450            self.dict()
451                .get_item("__file__")
452                .map_err(|_| exceptions::PyAttributeError::new_err("__file__"))?
453                .downcast_into()
454                .map_err(PyErr::from)
455        }
456    }
457
458    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
459    where
460        N: IntoPyObject<'py, Target = PyString>,
461        V: IntoPyObject<'py>,
462    {
463        fn inner(
464            module: &Bound<'_, PyModule>,
465            name: Borrowed<'_, '_, PyString>,
466            value: Borrowed<'_, '_, PyAny>,
467        ) -> PyResult<()> {
468            module
469                .index()?
470                .append(name)
471                .expect("could not append __name__ to __all__");
472            module.setattr(name, value)
473        }
474
475        let py = self.py();
476        inner(
477            self,
478            name.into_pyobject_or_pyerr(py)?.as_borrowed(),
479            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),
480        )
481    }
482
483    fn add_class<T>(&self) -> PyResult<()>
484    where
485        T: PyClass,
486    {
487        let py = self.py();
488        self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?)
489    }
490
491    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
492    where
493        T: IntoPyCallbackOutput<'py, PyObject>,
494    {
495        fn inner(module: &Bound<'_, PyModule>, object: Bound<'_, PyAny>) -> PyResult<()> {
496            let name = object.getattr(__name__(module.py()))?;
497            module.add(name.downcast_into::<PyString>()?, object)
498        }
499
500        let py = self.py();
501        inner(self, wrapper(py).convert(py)?.into_bound(py))
502    }
503
504    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> {
505        let name = module.name()?;
506        self.add(name, module)
507    }
508
509    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()> {
510        let name = fun.getattr(__name__(self.py()))?;
511        self.add(name.downcast_into::<PyString>()?, fun)
512    }
513
514    #[cfg_attr(any(Py_LIMITED_API, not(Py_GIL_DISABLED)), allow(unused_variables))]
515    fn gil_used(&self, gil_used: bool) -> PyResult<()> {
516        #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
517        {
518            let gil_used = match gil_used {
519                true => ffi::Py_MOD_GIL_USED,
520                false => ffi::Py_MOD_GIL_NOT_USED,
521            };
522            match unsafe { ffi::PyUnstable_Module_SetGIL(self.as_ptr(), gil_used) } {
523                c_int::MIN..=-1 => Err(PyErr::fetch(self.py())),
524                0..=c_int::MAX => Ok(()),
525            }
526        }
527        #[cfg(any(Py_LIMITED_API, not(Py_GIL_DISABLED)))]
528        Ok(())
529    }
530}
531
532fn __all__(py: Python<'_>) -> &Bound<'_, PyString> {
533    intern!(py, "__all__")
534}
535
536fn __name__(py: Python<'_>) -> &Bound<'_, PyString> {
537    intern!(py, "__name__")
538}
539
540#[cfg(test)]
541mod tests {
542    use crate::{
543        types::{module::PyModuleMethods, PyModule},
544        Python,
545    };
546
547    #[test]
548    fn module_import_and_name() {
549        Python::with_gil(|py| {
550            let builtins = PyModule::import(py, "builtins").unwrap();
551            assert_eq!(builtins.name().unwrap(), "builtins");
552        })
553    }
554
555    #[test]
556    fn module_filename() {
557        use crate::types::string::PyStringMethods;
558        Python::with_gil(|py| {
559            let site = PyModule::import(py, "site").unwrap();
560            assert!(site
561                .filename()
562                .unwrap()
563                .to_cow()
564                .unwrap()
565                .ends_with("site.py"));
566        })
567    }
568}
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here