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="">⚠ ️</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}