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, Py, Python,
13};
14#[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
15use std::ffi::c_int;
16use std::ffi::CStr;
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 .cast_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 /// [`PyOnceLock::import`][crate::sync::PyOnceLock::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 .cast_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 /// # #[cfg(not(target_arch = "wasm32"))] // node fs doesn't see this file, maybe cwd wrong?
144 /// # {
145 /// // This path is resolved by however the platform resolves paths,
146 /// // which also makes this less portable. Consider using `include_str`
147 /// // if you just want to bundle a script with your module.
148 /// let code = std::fs::read_to_string("assets/script.py")?;
149 ///
150 /// Python::attach(|py| -> PyResult<()> {
151 /// PyModule::from_code(py, CString::new(code)?.as_c_str(), c_str!("example.py"), c_str!("example"))?;
152 /// Ok(())
153 /// })?;
154 /// # }
155 /// # Ok(())
156 /// # }
157 /// ```
158 pub fn from_code<'py>(
159 py: Python<'py>,
160 code: &CStr,
161 file_name: &CStr,
162 module_name: &CStr,
163 ) -> PyResult<Bound<'py, PyModule>> {
164 let file_name = if file_name.is_empty() {
165 c_str!("<string>")
166 } else {
167 file_name
168 };
169 unsafe {
170 let code = ffi::Py_CompileString(code.as_ptr(), file_name.as_ptr(), ffi::Py_file_input)
171 .assume_owned_or_err(py)?;
172
173 ffi::PyImport_ExecCodeModuleEx(module_name.as_ptr(), code.as_ptr(), file_name.as_ptr())
174 .assume_owned_or_err(py)
175 .cast_into()
176 }
177 }
178}
179
180/// Implementation of functionality for [`PyModule`].
181///
182/// These methods are defined for the `Bound<'py, PyModule>` smart pointer, so to use method call
183/// syntax these methods are separated into a trait, because stable Rust does not yet support
184/// `arbitrary_self_types`.
185#[doc(alias = "PyModule")]
186pub trait PyModuleMethods<'py>: crate::sealed::Sealed {
187 /// Returns the module's `__dict__` attribute, which contains the module's symbol table.
188 fn dict(&self) -> Bound<'py, PyDict>;
189
190 /// Returns the index (the `__all__` attribute) of the module,
191 /// creating one if needed.
192 ///
193 /// `__all__` declares the items that will be imported with `from my_module import *`.
194 fn index(&self) -> PyResult<Bound<'py, PyList>>;
195
196 /// Returns the name (the `__name__` attribute) of the module.
197 ///
198 /// May fail if the module does not have a `__name__` attribute.
199 fn name(&self) -> PyResult<Bound<'py, PyString>>;
200
201 /// Returns the filename (the `__file__` attribute) of the module.
202 ///
203 /// May fail if the module does not have a `__file__` attribute.
204 fn filename(&self) -> PyResult<Bound<'py, PyString>>;
205
206 /// Adds an attribute to the module.
207 ///
208 /// For adding classes, functions or modules, prefer to use [`PyModuleMethods::add_class`],
209 /// [`PyModuleMethods::add_function`] or [`PyModuleMethods::add_submodule`] instead,
210 /// respectively.
211 ///
212 /// # Examples
213 ///
214 /// ```rust,no_run
215 /// use pyo3::prelude::*;
216 ///
217 /// #[pymodule]
218 /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
219 /// module.add("c", 299_792_458)?;
220 /// Ok(())
221 /// }
222 /// ```
223 ///
224 /// Python code can then do the following:
225 ///
226 /// ```python
227 /// from my_module import c
228 ///
229 /// print("c is", c)
230 /// ```
231 ///
232 /// This will result in the following output:
233 ///
234 /// ```text
235 /// c is 299792458
236 /// ```
237 fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
238 where
239 N: IntoPyObject<'py, Target = PyString>,
240 V: IntoPyObject<'py>;
241
242 /// Adds a new class to the module.
243 ///
244 /// Notice that this method does not take an argument.
245 /// Instead, this method is *generic*, and requires us to use the
246 /// "turbofish" syntax to specify the class we want to add.
247 ///
248 /// # Examples
249 ///
250 /// ```rust,no_run
251 /// use pyo3::prelude::*;
252 ///
253 /// #[pyclass]
254 /// struct Foo { /* fields omitted */ }
255 ///
256 /// #[pymodule]
257 /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
258 /// module.add_class::<Foo>()?;
259 /// Ok(())
260 /// }
261 /// ```
262 ///
263 /// Python code can see this class as such:
264 /// ```python
265 /// from my_module import Foo
266 ///
267 /// print("Foo is", Foo)
268 /// ```
269 ///
270 /// This will result in the following output:
271 /// ```text
272 /// Foo is <class 'builtins.Foo'>
273 /// ```
274 ///
275 /// Note that as we haven't defined a [constructor][1], Python code can't actually
276 /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported
277 /// anything that can return instances of `Foo`).
278 ///
279 #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")]
280 fn add_class<T>(&self) -> PyResult<()>
281 where
282 T: PyClass;
283
284 /// Adds a function or a (sub)module to a module, using the functions name as name.
285 ///
286 /// Prefer to use [`PyModuleMethods::add_function`] and/or [`PyModuleMethods::add_submodule`]
287 /// instead.
288 fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
289 where
290 T: IntoPyCallbackOutput<'py, Py<PyAny>>;
291
292 /// Adds a submodule to a module.
293 ///
294 /// This is especially useful for creating module hierarchies.
295 ///
296 /// Note that this doesn't define a *package*, so this won't allow Python code
297 /// to directly import submodules by using
298 /// <span style="white-space: pre">`from my_module import submodule`</span>.
299 /// For more information, see [#759][1] and [#1517][2].
300 ///
301 /// # Examples
302 ///
303 /// ```rust,no_run
304 /// use pyo3::prelude::*;
305 ///
306 /// #[pymodule]
307 /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
308 /// let submodule = PyModule::new(py, "submodule")?;
309 /// submodule.add("super_useful_constant", "important")?;
310 ///
311 /// module.add_submodule(&submodule)?;
312 /// Ok(())
313 /// }
314 /// ```
315 ///
316 /// Python code can then do the following:
317 ///
318 /// ```python
319 /// import my_module
320 ///
321 /// print("super_useful_constant is", my_module.submodule.super_useful_constant)
322 /// ```
323 ///
324 /// This will result in the following output:
325 ///
326 /// ```text
327 /// super_useful_constant is important
328 /// ```
329 ///
330 /// [1]: https://github.com/PyO3/pyo3/issues/759
331 /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021
332 fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()>;
333
334 /// Add a function to a module.
335 ///
336 /// Note that this also requires the [`wrap_pyfunction!`][2] macro
337 /// to wrap a function annotated with [`#[pyfunction]`][1].
338 ///
339 /// ```rust,no_run
340 /// use pyo3::prelude::*;
341 ///
342 /// #[pyfunction]
343 /// fn say_hello() {
344 /// println!("Hello world!")
345 /// }
346 /// #[pymodule]
347 /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
348 /// module.add_function(wrap_pyfunction!(say_hello, module)?)
349 /// }
350 /// ```
351 ///
352 /// Python code can then do the following:
353 ///
354 /// ```python
355 /// from my_module import say_hello
356 ///
357 /// say_hello()
358 /// ```
359 ///
360 /// This will result in the following output:
361 ///
362 /// ```text
363 /// Hello world!
364 /// ```
365 ///
366 /// [1]: crate::prelude::pyfunction
367 /// [2]: crate::wrap_pyfunction
368 fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()>;
369
370 /// Declare whether or not this module supports running with the GIL disabled
371 ///
372 /// If the module does not rely on the GIL for thread safety, you can pass
373 /// `false` to this function to indicate the module does not rely on the GIL
374 /// for thread-safety.
375 ///
376 /// This function sets the [`Py_MOD_GIL`
377 /// slot](https://docs.python.org/3/c-api/module.html#c.Py_mod_gil) on the
378 /// module object. The default is `Py_MOD_GIL_USED`, so passing `true` to
379 /// this function is a no-op unless you have already set `Py_MOD_GIL` to
380 /// `Py_MOD_GIL_NOT_USED` elsewhere.
381 ///
382 /// # Examples
383 ///
384 /// ```rust,no_run
385 /// use pyo3::prelude::*;
386 ///
387 /// #[pymodule(gil_used = false)]
388 /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {
389 /// let submodule = PyModule::new(py, "submodule")?;
390 /// submodule.gil_used(false)?;
391 /// module.add_submodule(&submodule)?;
392 /// Ok(())
393 /// }
394 /// ```
395 ///
396 /// The resulting module will not print a `RuntimeWarning` and re-enable the
397 /// GIL when Python imports it on the free-threaded build, since all module
398 /// objects defined in the extension have `Py_MOD_GIL` set to
399 /// `Py_MOD_GIL_NOT_USED`.
400 ///
401 /// This is a no-op on the GIL-enabled build.
402 fn gil_used(&self, gil_used: bool) -> PyResult<()>;
403}
404
405impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> {
406 fn dict(&self) -> Bound<'py, PyDict> {
407 unsafe {
408 // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890).
409 ffi::PyModule_GetDict(self.as_ptr())
410 .assume_borrowed(self.py())
411 .to_owned()
412 .cast_into_unchecked()
413 }
414 }
415
416 fn index(&self) -> PyResult<Bound<'py, PyList>> {
417 let __all__ = __all__(self.py());
418 match self.getattr(__all__) {
419 Ok(idx) => idx.cast_into().map_err(PyErr::from),
420 Err(err) => {
421 if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) {
422 let l = PyList::empty(self.py());
423 self.setattr(__all__, &l)?;
424 Ok(l)
425 } else {
426 Err(err)
427 }
428 }
429 }
430 }
431
432 fn name(&self) -> PyResult<Bound<'py, PyString>> {
433 #[cfg(not(PyPy))]
434 {
435 unsafe {
436 ffi::PyModule_GetNameObject(self.as_ptr())
437 .assume_owned_or_err(self.py())
438 .cast_into_unchecked()
439 }
440 }
441
442 #[cfg(PyPy)]
443 {
444 self.dict()
445 .get_item("__name__")
446 .map_err(|_| exceptions::PyAttributeError::new_err("__name__"))?
447 .cast_into()
448 .map_err(PyErr::from)
449 }
450 }
451
452 fn filename(&self) -> PyResult<Bound<'py, PyString>> {
453 #[cfg(not(PyPy))]
454 unsafe {
455 ffi::PyModule_GetFilenameObject(self.as_ptr())
456 .assume_owned_or_err(self.py())
457 .cast_into_unchecked()
458 }
459
460 #[cfg(PyPy)]
461 {
462 self.dict()
463 .get_item("__file__")
464 .map_err(|_| exceptions::PyAttributeError::new_err("__file__"))?
465 .cast_into()
466 .map_err(PyErr::from)
467 }
468 }
469
470 fn add<N, V>(&self, name: N, value: V) -> PyResult<()>
471 where
472 N: IntoPyObject<'py, Target = PyString>,
473 V: IntoPyObject<'py>,
474 {
475 fn inner(
476 module: &Bound<'_, PyModule>,
477 name: Borrowed<'_, '_, PyString>,
478 value: Borrowed<'_, '_, PyAny>,
479 ) -> PyResult<()> {
480 module
481 .index()?
482 .append(name)
483 .expect("could not append __name__ to __all__");
484 module.setattr(name, value)
485 }
486
487 let py = self.py();
488 inner(
489 self,
490 name.into_pyobject_or_pyerr(py)?.as_borrowed(),
491 value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),
492 )
493 }
494
495 fn add_class<T>(&self) -> PyResult<()>
496 where
497 T: PyClass,
498 {
499 let py = self.py();
500 self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?)
501 }
502
503 fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>
504 where
505 T: IntoPyCallbackOutput<'py, Py<PyAny>>,
506 {
507 fn inner(module: &Bound<'_, PyModule>, object: Bound<'_, PyAny>) -> PyResult<()> {
508 let name = object.getattr(__name__(module.py()))?;
509 module.add(name.cast_into::<PyString>()?, object)
510 }
511
512 let py = self.py();
513 inner(self, wrapper(py).convert(py)?.into_bound(py))
514 }
515
516 fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> {
517 let name = module.name()?;
518 self.add(name, module)
519 }
520
521 fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()> {
522 let name = fun.getattr(__name__(self.py()))?;
523 self.add(name.cast_into::<PyString>()?, fun)
524 }
525
526 #[cfg_attr(any(Py_LIMITED_API, not(Py_GIL_DISABLED)), allow(unused_variables))]
527 fn gil_used(&self, gil_used: bool) -> PyResult<()> {
528 #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]
529 {
530 let gil_used = match gil_used {
531 true => ffi::Py_MOD_GIL_USED,
532 false => ffi::Py_MOD_GIL_NOT_USED,
533 };
534 match unsafe { ffi::PyUnstable_Module_SetGIL(self.as_ptr(), gil_used) } {
535 c_int::MIN..=-1 => Err(PyErr::fetch(self.py())),
536 0..=c_int::MAX => Ok(()),
537 }
538 }
539 #[cfg(any(Py_LIMITED_API, not(Py_GIL_DISABLED)))]
540 Ok(())
541 }
542}
543
544fn __all__(py: Python<'_>) -> &Bound<'_, PyString> {
545 intern!(py, "__all__")
546}
547
548fn __name__(py: Python<'_>) -> &Bound<'_, PyString> {
549 intern!(py, "__name__")
550}
551
552#[cfg(test)]
553mod tests {
554 use pyo3_ffi::c_str;
555
556 use crate::{
557 types::{module::PyModuleMethods, PyModule},
558 Python,
559 };
560
561 #[test]
562 fn module_import_and_name() {
563 Python::attach(|py| {
564 let builtins = PyModule::import(py, "builtins").unwrap();
565 assert_eq!(builtins.name().unwrap(), "builtins");
566 })
567 }
568
569 #[test]
570 fn module_filename() {
571 use crate::types::string::PyStringMethods;
572 Python::attach(|py| {
573 let site = PyModule::import(py, "site").unwrap();
574 assert!(site
575 .filename()
576 .unwrap()
577 .to_cow()
578 .unwrap()
579 .ends_with("site.py"));
580 })
581 }
582
583 #[test]
584 fn module_from_code_empty_file() {
585 Python::attach(|py| {
586 let builtins = PyModule::from_code(py, c_str!(""), c_str!(""), c_str!("")).unwrap();
587 assert_eq!(builtins.filename().unwrap(), "<string>");
588 })
589 }
590}