pyo3/types/
module.rs

1use crate::callback::IntoPyCallbackOutput;
2use crate::err::{PyErr, PyResult};
3use crate::ffi_ptr_ext::FfiPtrExt;
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::{exceptions, ffi, Bound, IntoPy, Py, PyObject, Python};
10use std::ffi::CString;
11use std::str;
12
13#[cfg(feature = "gil-refs")]
14use {super::PyStringMethods, crate::PyNativeType};
15
16/// Represents a Python [`module`][1] object.
17///
18/// Values of this type are accessed via PyO3's smart pointers, e.g. as
19/// [`Py<PyModule>`][crate::Py] or [`Bound<'py, PyModule>`][Bound].
20///
21/// For APIs available on `module` objects, see the [`PyModuleMethods`] trait which is implemented for
22/// [`Bound<'py, PyModule>`][Bound].
23///
24/// As with all other Python objects, modules are first class citizens.
25/// This means they can be passed to or returned from functions,
26/// created dynamically, assigned to variables and so forth.
27///
28/// [1]: https://docs.python.org/3/tutorial/modules.html
29#[repr(transparent)]
30pub struct PyModule(PyAny);
31
32pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check);
33
34impl PyModule {
35    /// Creates a new module object with the `__name__` attribute set to `name`.
36    ///
37    /// # Examples
38    ///
39    /// ``` rust
40    /// use pyo3::prelude::*;
41    ///
42    /// # fn main() -> PyResult<()> {
43    /// Python::with_gil(|py| -> PyResult<()> {
44    ///     let module = PyModule::new_bound(py, "my_module")?;
45    ///
46    ///     assert_eq!(module.name()?, "my_module");
47    ///     Ok(())
48    /// })?;
49    /// # Ok(())}
50    ///  ```
51    pub fn new_bound<'py>(py: Python<'py>, name: &str) -> PyResult<Bound<'py, PyModule>> {
52        // Could use PyModule_NewObject, but it doesn't exist on PyPy.
53        let name = CString::new(name)?;
54        unsafe {
55            ffi::PyModule_New(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_bound(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    pub fn import_bound<N>(py: Python<'_>, name: N) -> PyResult<Bound<'_, PyModule>>
80    where
81        N: IntoPy<Py<PyString>>,
82    {
83        let name: Py<PyString> = name.into_py(py);
84        unsafe {
85            ffi::PyImport_Import(name.as_ptr())
86                .assume_owned_or_err(py)
87                .downcast_into_unchecked()
88        }
89    }
90
91    /// Creates and loads a module named `module_name`,
92    /// containing the Python code passed to `code`
93    /// and pretending to live at `file_name`.
94    ///
95    /// <div class="information">
96    ///     <div class="tooltip compile_fail" style="">&#x26a0; &#xfe0f;</div>
97    /// </div><div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
98    //
99    ///  <strong>Warning</strong>: This will compile and execute code. <strong>Never</strong> pass untrusted code to this function!
100    ///
101    /// </pre></div>
102    ///
103    /// # Errors
104    ///
105    /// Returns `PyErr` if:
106    /// - `code` is not syntactically correct Python.
107    /// - Any Python exceptions are raised while initializing the module.
108    /// - Any of the arguments cannot be converted to [`CString`]s.
109    ///
110    /// # Example: bundle in a file at compile time with [`include_str!`][std::include_str]:
111    ///
112    /// ```rust
113    /// use pyo3::prelude::*;
114    ///
115    /// # fn main() -> PyResult<()> {
116    /// // This path is resolved relative to this file.
117    /// let code = include_str!("../../assets/script.py");
118    ///
119    /// Python::with_gil(|py| -> PyResult<()> {
120    ///     PyModule::from_code_bound(py, code, "example.py", "example")?;
121    ///     Ok(())
122    /// })?;
123    /// # Ok(())
124    /// # }
125    /// ```
126    ///
127    /// # Example: Load a file at runtime with [`std::fs::read_to_string`].
128    ///
129    /// ```rust
130    /// use pyo3::prelude::*;
131    ///
132    /// # fn main() -> PyResult<()> {
133    /// // This path is resolved by however the platform resolves paths,
134    /// // which also makes this less portable. Consider using `include_str`
135    /// // if you just want to bundle a script with your module.
136    /// let code = std::fs::read_to_string("assets/script.py")?;
137    ///
138    /// Python::with_gil(|py| -> PyResult<()> {
139    ///     PyModule::from_code_bound(py, &code, "example.py", "example")?;
140    ///     Ok(())
141    /// })?;
142    /// Ok(())
143    /// # }
144    /// ```
145    pub fn from_code_bound<'py>(
146        py: Python<'py>,
147        code: &str,
148        file_name: &str,
149        module_name: &str,
150    ) -> PyResult<Bound<'py, PyModule>> {
151        let data = CString::new(code)?;
152        let filename = CString::new(file_name)?;
153        let module = CString::new(module_name)?;
154
155        unsafe {
156            let code = ffi::Py_CompileString(data.as_ptr(), filename.as_ptr(), ffi::Py_file_input)
157                .assume_owned_or_err(py)?;
158
159            ffi::PyImport_ExecCodeModuleEx(module.as_ptr(), code.as_ptr(), filename.as_ptr())
160                .assume_owned_or_err(py)
161                .downcast_into()
162        }
163    }
164}
165
166#[cfg(feature = "gil-refs")]
167impl PyModule {
168    /// Deprecated form of [`PyModule::new_bound`].
169    #[inline]
170    #[deprecated(
171        since = "0.21.0",
172        note = "`PyModule::new` will be replaced by `PyModule::new_bound` in a future PyO3 version"
173    )]
174    pub fn new<'py>(py: Python<'py>, name: &str) -> PyResult<&'py PyModule> {
175        Self::new_bound(py, name).map(Bound::into_gil_ref)
176    }
177
178    /// Deprecated form of [`PyModule::import_bound`].
179    #[inline]
180    #[deprecated(
181        since = "0.21.0",
182        note = "`PyModule::import` will be replaced by `PyModule::import_bound` in a future PyO3 version"
183    )]
184    pub fn import<N>(py: Python<'_>, name: N) -> PyResult<&PyModule>
185    where
186        N: IntoPy<Py<PyString>>,
187    {
188        Self::import_bound(py, name).map(Bound::into_gil_ref)
189    }
190
191    /// Deprecated form of [`PyModule::from_code_bound`].
192    #[inline]
193    #[deprecated(
194        since = "0.21.0",
195        note = "`PyModule::from_code` will be replaced by `PyModule::from_code_bound` in a future PyO3 version"
196    )]
197    pub fn from_code<'py>(
198        py: Python<'py>,
199        code: &str,
200        file_name: &str,
201        module_name: &str,
202    ) -> PyResult<&'py PyModule> {
203        Self::from_code_bound(py, code, file_name, module_name).map(Bound::into_gil_ref)
204    }
205
206    /// Returns the module's `__dict__` attribute, which contains the module's symbol table.
207    pub fn dict(&self) -> &PyDict {
208        self.as_borrowed().dict().into_gil_ref()
209    }
210
211    /// Returns the index (the `__all__` attribute) of the module,
212    /// creating one if needed.
213    ///
214    /// `__all__` declares the items that will be imported with `from my_module import *`.
215    pub fn index(&self) -> PyResult<&PyList> {
216        self.as_borrowed().index().map(Bound::into_gil_ref)
217    }
218
219    /// Returns the name (the `__name__` attribute) of the module.
220    ///
221    /// May fail if the module does not have a `__name__` attribute.
222    pub fn name(&self) -> PyResult<&str> {
223        self.as_borrowed().name()?.into_gil_ref().to_str()
224    }
225
226    /// Returns the filename (the `__file__` attribute) of the module.
227    ///
228    /// May fail if the module does not have a `__file__` attribute.
229    pub fn filename(&self) -> PyResult<&str> {
230        self.as_borrowed().filename()?.into_gil_ref().to_str()
231    }
232
233    /// Adds an attribute to the module.
234    ///
235    /// For adding classes, functions or modules, prefer to use [`PyModule::add_class`],
236    /// [`PyModule::add_function`] or [`PyModule::add_submodule`] instead, respectively.
237    ///
238    /// # Examples
239    ///
240    /// ```rust
241    /// use pyo3::prelude::*;
242    ///
243    /// #[pymodule]
244    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
245    ///     module.add("c", 299_792_458)?;
246    ///     Ok(())
247    /// }
248    /// ```
249    ///
250    /// Python code can then do the following:
251    ///
252    /// ```python
253    /// from my_module import c
254    ///
255    /// print("c is", c)
256    /// ```
257    ///
258    /// This will result in the following output:
259    ///
260    /// ```text
261    /// c is 299792458
262    /// ```
263    pub fn add<V>(&self, name: &str, value: V) -> PyResult<()>
264    where
265        V: IntoPy<PyObject>,
266    {
267        self.as_borrowed().add(name, value)
268    }
269
270    /// Adds a new class to the module.
271    ///
272    /// Notice that this method does not take an argument.
273    /// Instead, this method is *generic*, and requires us to use the
274    /// "turbofish" syntax to specify the class we want to add.
275    ///
276    /// # Examples
277    ///
278    /// ```rust
279    /// use pyo3::prelude::*;
280    ///
281    /// #[pyclass]
282    /// struct Foo { /* fields omitted */ }
283    ///
284    /// #[pymodule]
285    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
286    ///     module.add_class::<Foo>()?;
287    ///     Ok(())
288    /// }
289    ///  ```
290    ///
291    /// Python code can see this class as such:
292    /// ```python
293    /// from my_module import Foo
294    ///
295    /// print("Foo is", Foo)
296    /// ```
297    ///
298    /// This will result in the following output:
299    /// ```text
300    /// Foo is <class 'builtins.Foo'>
301    /// ```
302    ///
303    /// Note that as we haven't defined a [constructor][1], Python code can't actually
304    /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported
305    /// anything that can return instances of `Foo`).
306    ///
307    #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")]
308    pub fn add_class<T>(&self) -> PyResult<()>
309    where
310        T: PyClass,
311    {
312        self.as_borrowed().add_class::<T>()
313    }
314
315    /// Adds a function or a (sub)module to a module, using the functions name as name.
316    ///
317    /// Prefer to use [`PyModule::add_function`] and/or [`PyModule::add_submodule`] instead.
318    pub fn add_wrapped<'a, T>(&'a self, wrapper: &impl Fn(Python<'a>) -> T) -> PyResult<()>
319    where
320        T: IntoPyCallbackOutput<PyObject>,
321    {
322        self.as_borrowed().add_wrapped(wrapper)
323    }
324
325    /// Adds a submodule to a module.
326    ///
327    /// This is especially useful for creating module hierarchies.
328    ///
329    /// Note that this doesn't define a *package*, so this won't allow Python code
330    /// to directly import submodules by using
331    /// <span style="white-space: pre">`from my_module import submodule`</span>.
332    /// For more information, see [#759][1] and [#1517][2].
333    ///
334    /// # Examples
335    ///
336    /// ```rust
337    /// use pyo3::prelude::*;
338    ///
339    /// #[pymodule]
340    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
341    ///     let submodule = PyModule::new_bound(py, "submodule")?;
342    ///     submodule.add("super_useful_constant", "important")?;
343    ///
344    ///     module.add_submodule(&submodule)?;
345    ///     Ok(())
346    /// }
347    /// ```
348    ///
349    /// Python code can then do the following:
350    ///
351    /// ```python
352    /// import my_module
353    ///
354    /// print("super_useful_constant is", my_module.submodule.super_useful_constant)
355    /// ```
356    ///
357    /// This will result in the following output:
358    ///
359    /// ```text
360    /// super_useful_constant is important
361    /// ```
362    ///
363    /// [1]: https://github.com/PyO3/pyo3/issues/759
364    /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021
365    pub fn add_submodule(&self, module: &PyModule) -> PyResult<()> {
366        self.as_borrowed().add_submodule(&module.as_borrowed())
367    }
368
369    /// Add a function to a module.
370    ///
371    /// Note that this also requires the [`wrap_pyfunction!`][2] macro
372    /// to wrap a function annotated with [`#[pyfunction]`][1].
373    ///
374    /// ```rust
375    /// use pyo3::prelude::*;
376    ///
377    /// #[pyfunction]
378    /// fn say_hello() {
379    ///     println!("Hello world!")
380    /// }
381    /// #[pymodule]
382    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
383    ///     module.add_function(wrap_pyfunction!(say_hello, module)?)
384    /// }
385    /// ```
386    ///
387    /// Python code can then do the following:
388    ///
389    /// ```python
390    /// from my_module import say_hello
391    ///
392    /// say_hello()
393    /// ```
394    ///
395    /// This will result in the following output:
396    ///
397    /// ```text
398    /// Hello world!
399    /// ```
400    ///
401    /// [1]: crate::prelude::pyfunction
402    /// [2]: crate::wrap_pyfunction
403    pub fn add_function<'a>(&'a self, fun: &'a PyCFunction) -> PyResult<()> {
404        let name = fun
405            .as_borrowed()
406            .getattr(__name__(self.py()))?
407            .downcast_into::<PyString>()?;
408        let name = name.to_cow()?;
409        self.add(&name, fun)
410    }
411}
412
413/// Implementation of functionality for [`PyModule`].
414///
415/// These methods are defined for the `Bound<'py, PyModule>` smart pointer, so to use method call
416/// syntax these methods are separated into a trait, because stable Rust does not yet support
417/// `arbitrary_self_types`.
418#[doc(alias = "PyModule")]
419pub trait PyModuleMethods<'py>: crate::sealed::Sealed {
420    /// Returns the module's `__dict__` attribute, which contains the module's symbol table.
421    fn dict(&self) -> Bound<'py, PyDict>;
422
423    /// Returns the index (the `__all__` attribute) of the module,
424    /// creating one if needed.
425    ///
426    /// `__all__` declares the items that will be imported with `from my_module import *`.
427    fn index(&self) -> PyResult<Bound<'py, PyList>>;
428
429    /// Returns the name (the `__name__` attribute) of the module.
430    ///
431    /// May fail if the module does not have a `__name__` attribute.
432    fn name(&self) -> PyResult<Bound<'py, PyString>>;
433
434    /// Returns the filename (the `__file__` attribute) of the module.
435    ///
436    /// May fail if the module does not have a `__file__` attribute.
437    fn filename(&self) -> PyResult<Bound<'py, PyString>>;
438
439    /// Adds an attribute to the module.
440    ///
441    /// For adding classes, functions or modules, prefer to use [`PyModuleMethods::add_class`],
442    /// [`PyModuleMethods::add_function`] or [`PyModuleMethods::add_submodule`] instead,
443    /// respectively.
444    ///
445    /// # Examples
446    ///
447    /// ```rust
448    /// use pyo3::prelude::*;
449    ///
450    /// #[pymodule]
451    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
452    ///     module.add("c", 299_792_458)?;
453    ///     Ok(())
454    /// }
455    /// ```
456    ///
457    /// Python code can then do the following:
458    ///
459    /// ```python
460    /// from my_module import c
461    ///
462    /// print("c is", c)
463    /// ```
464    ///
465    /// This will result in the following output:
466    ///
467    /// ```text
468    /// c is 299792458
469    /// ```
470    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
471    where
472        N: IntoPy<Py<PyString>>,
473        V: IntoPy<PyObject>;
474
475    /// Adds a new class to the module.
476    ///
477    /// Notice that this method does not take an argument.
478    /// Instead, this method is *generic*, and requires us to use the
479    /// "turbofish" syntax to specify the class we want to add.
480    ///
481    /// # Examples
482    ///
483    /// ```rust
484    /// use pyo3::prelude::*;
485    ///
486    /// #[pyclass]
487    /// struct Foo { /* fields omitted */ }
488    ///
489    /// #[pymodule]
490    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
491    ///     module.add_class::<Foo>()?;
492    ///     Ok(())
493    /// }
494    ///  ```
495    ///
496    /// Python code can see this class as such:
497    /// ```python
498    /// from my_module import Foo
499    ///
500    /// print("Foo is", Foo)
501    /// ```
502    ///
503    /// This will result in the following output:
504    /// ```text
505    /// Foo is <class 'builtins.Foo'>
506    /// ```
507    ///
508    /// Note that as we haven't defined a [constructor][1], Python code can't actually
509    /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported
510    /// anything that can return instances of `Foo`).
511    ///
512    #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")]
513    fn add_class<T>(&self) -> PyResult<()>
514    where
515        T: PyClass;
516
517    /// Adds a function or a (sub)module to a module, using the functions name as name.
518    ///
519    /// Prefer to use [`PyModuleMethods::add_function`] and/or [`PyModuleMethods::add_submodule`]
520    /// instead.
521    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
522    where
523        T: IntoPyCallbackOutput<PyObject>;
524
525    /// Adds a submodule to a module.
526    ///
527    /// This is especially useful for creating module hierarchies.
528    ///
529    /// Note that this doesn't define a *package*, so this won't allow Python code
530    /// to directly import submodules by using
531    /// <span style="white-space: pre">`from my_module import submodule`</span>.
532    /// For more information, see [#759][1] and [#1517][2].
533    ///
534    /// # Examples
535    ///
536    /// ```rust
537    /// use pyo3::prelude::*;
538    ///
539    /// #[pymodule]
540    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
541    ///     let submodule = PyModule::new_bound(py, "submodule")?;
542    ///     submodule.add("super_useful_constant", "important")?;
543    ///
544    ///     module.add_submodule(&submodule)?;
545    ///     Ok(())
546    /// }
547    /// ```
548    ///
549    /// Python code can then do the following:
550    ///
551    /// ```python
552    /// import my_module
553    ///
554    /// print("super_useful_constant is", my_module.submodule.super_useful_constant)
555    /// ```
556    ///
557    /// This will result in the following output:
558    ///
559    /// ```text
560    /// super_useful_constant is important
561    /// ```
562    ///
563    /// [1]: https://github.com/PyO3/pyo3/issues/759
564    /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021
565    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()>;
566
567    /// Add a function to a module.
568    ///
569    /// Note that this also requires the [`wrap_pyfunction!`][2] macro
570    /// to wrap a function annotated with [`#[pyfunction]`][1].
571    ///
572    /// ```rust
573    /// use pyo3::prelude::*;
574    ///
575    /// #[pyfunction]
576    /// fn say_hello() {
577    ///     println!("Hello world!")
578    /// }
579    /// #[pymodule]
580    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
581    ///     module.add_function(wrap_pyfunction!(say_hello, module)?)
582    /// }
583    /// ```
584    ///
585    /// Python code can then do the following:
586    ///
587    /// ```python
588    /// from my_module import say_hello
589    ///
590    /// say_hello()
591    /// ```
592    ///
593    /// This will result in the following output:
594    ///
595    /// ```text
596    /// Hello world!
597    /// ```
598    ///
599    /// [1]: crate::prelude::pyfunction
600    /// [2]: crate::wrap_pyfunction
601    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()>;
602}
603
604impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> {
605    fn dict(&self) -> Bound<'py, PyDict> {
606        unsafe {
607            // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890).
608            ffi::PyModule_GetDict(self.as_ptr())
609                .assume_borrowed(self.py())
610                .to_owned()
611                .downcast_into_unchecked()
612        }
613    }
614
615    fn index(&self) -> PyResult<Bound<'py, PyList>> {
616        let __all__ = __all__(self.py());
617        match self.getattr(__all__) {
618            Ok(idx) => idx.downcast_into().map_err(PyErr::from),
619            Err(err) => {
620                if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) {
621                    let l = PyList::empty_bound(self.py());
622                    self.setattr(__all__, &l).map_err(PyErr::from)?;
623                    Ok(l)
624                } else {
625                    Err(err)
626                }
627            }
628        }
629    }
630
631    fn name(&self) -> PyResult<Bound<'py, PyString>> {
632        #[cfg(not(PyPy))]
633        {
634            unsafe {
635                ffi::PyModule_GetNameObject(self.as_ptr())
636                    .assume_owned_or_err(self.py())
637                    .downcast_into_unchecked()
638            }
639        }
640
641        #[cfg(PyPy)]
642        {
643            self.dict()
644                .get_item("__name__")
645                .map_err(|_| exceptions::PyAttributeError::new_err("__name__"))?
646                .downcast_into()
647                .map_err(PyErr::from)
648        }
649    }
650
651    fn filename(&self) -> PyResult<Bound<'py, PyString>> {
652        #[cfg(not(PyPy))]
653        unsafe {
654            ffi::PyModule_GetFilenameObject(self.as_ptr())
655                .assume_owned_or_err(self.py())
656                .downcast_into_unchecked()
657        }
658
659        #[cfg(PyPy)]
660        {
661            self.dict()
662                .get_item("__file__")
663                .map_err(|_| exceptions::PyAttributeError::new_err("__file__"))?
664                .downcast_into()
665                .map_err(PyErr::from)
666        }
667    }
668
669    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
670    where
671        N: IntoPy<Py<PyString>>,
672        V: IntoPy<PyObject>,
673    {
674        fn inner(
675            module: &Bound<'_, PyModule>,
676            name: Bound<'_, PyString>,
677            value: Bound<'_, PyAny>,
678        ) -> PyResult<()> {
679            module
680                .index()?
681                .append(&name)
682                .expect("could not append __name__ to __all__");
683            module.setattr(name, value.into_py(module.py()))
684        }
685
686        let py = self.py();
687        inner(
688            self,
689            name.into_py(py).into_bound(py),
690            value.into_py(py).into_bound(py),
691        )
692    }
693
694    fn add_class<T>(&self) -> PyResult<()>
695    where
696        T: PyClass,
697    {
698        let py = self.py();
699        self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?)
700    }
701
702    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
703    where
704        T: IntoPyCallbackOutput<PyObject>,
705    {
706        fn inner(module: &Bound<'_, PyModule>, object: Bound<'_, PyAny>) -> PyResult<()> {
707            let name = object.getattr(__name__(module.py()))?;
708            module.add(name.downcast_into::<PyString>()?, object)
709        }
710
711        let py = self.py();
712        inner(self, wrapper(py).convert(py)?.into_bound(py))
713    }
714
715    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> {
716        let name = module.name()?;
717        self.add(name, module)
718    }
719
720    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()> {
721        let name = fun.getattr(__name__(self.py()))?;
722        self.add(name.downcast_into::<PyString>()?, fun)
723    }
724}
725
726fn __all__(py: Python<'_>) -> &Bound<'_, PyString> {
727    intern!(py, "__all__")
728}
729
730fn __name__(py: Python<'_>) -> &Bound<'_, PyString> {
731    intern!(py, "__name__")
732}
733
734#[cfg(test)]
735mod tests {
736    use crate::{
737        types::{module::PyModuleMethods, PyModule},
738        Python,
739    };
740
741    #[test]
742    fn module_import_and_name() {
743        Python::with_gil(|py| {
744            let builtins = PyModule::import_bound(py, "builtins").unwrap();
745            assert_eq!(builtins.name().unwrap(), "builtins");
746        })
747    }
748
749    #[test]
750    fn module_filename() {
751        use crate::types::string::PyStringMethods;
752        Python::with_gil(|py| {
753            let site = PyModule::import_bound(py, "site").unwrap();
754            assert!(site
755                .filename()
756                .unwrap()
757                .to_cow()
758                .unwrap()
759                .ends_with("site.py"));
760        })
761    }
762}