pyo3/types/
module.rs

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