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