1 | use crate::callback::IntoPyCallbackOutput; |
2 | use crate::err::{PyErr, PyResult}; |
3 | use crate::exceptions; |
4 | use crate::ffi; |
5 | use crate::pyclass::PyClass; |
6 | use crate::types::{PyAny, PyCFunction, PyDict, PyList, PyString}; |
7 | use crate::{IntoPy, Py, PyObject, Python}; |
8 | use std::ffi::{CStr, CString}; |
9 | use std::str; |
10 | |
11 | /// Represents a Python [`module`][1] object. |
12 | /// |
13 | /// As with all other Python objects, modules are first class citizens. |
14 | /// This means they can be passed to or returned from functions, |
15 | /// created dynamically, assigned to variables and so forth. |
16 | /// |
17 | /// [1]: https://docs.python.org/3/tutorial/modules.html |
18 | #[repr (transparent)] |
19 | pub struct PyModule(PyAny); |
20 | |
21 | pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check); |
22 | |
23 | impl PyModule { |
24 | /// Creates a new module object with the `__name__` attribute set to `name`. |
25 | /// |
26 | /// # Examples |
27 | /// |
28 | /// ``` rust |
29 | /// use pyo3::prelude::*; |
30 | /// |
31 | /// # fn main() -> PyResult<()> { |
32 | /// Python::with_gil(|py| -> PyResult<()> { |
33 | /// let module = PyModule::new(py, "my_module" )?; |
34 | /// |
35 | /// assert_eq!(module.name()?, "my_module" ); |
36 | /// Ok(()) |
37 | /// })?; |
38 | /// # Ok(())} |
39 | /// ``` |
40 | pub fn new<'p>(py: Python<'p>, name: &str) -> PyResult<&'p PyModule> { |
41 | // Could use PyModule_NewObject, but it doesn't exist on PyPy. |
42 | let name = CString::new(name)?; |
43 | unsafe { py.from_owned_ptr_or_err(ffi::PyModule_New(name.as_ptr())) } |
44 | } |
45 | |
46 | /// Imports the Python module with the specified name. |
47 | /// |
48 | /// # Examples |
49 | /// |
50 | /// ```no_run |
51 | /// # fn main() { |
52 | /// use pyo3::prelude::*; |
53 | /// |
54 | /// Python::with_gil(|py| { |
55 | /// let module = PyModule::import(py, "antigravity" ).expect("No flying for you." ); |
56 | /// }); |
57 | /// # } |
58 | /// ``` |
59 | /// |
60 | /// This is equivalent to the following Python expression: |
61 | /// ```python |
62 | /// import antigravity |
63 | /// ``` |
64 | pub fn import<N>(py: Python<'_>, name: N) -> PyResult<&PyModule> |
65 | where |
66 | N: IntoPy<Py<PyString>>, |
67 | { |
68 | let name: Py<PyString> = name.into_py(py); |
69 | unsafe { py.from_owned_ptr_or_err(ffi::PyImport_Import(name.as_ptr())) } |
70 | } |
71 | |
72 | /// Creates and loads a module named `module_name`, |
73 | /// containing the Python code passed to `code` |
74 | /// and pretending to live at `file_name`. |
75 | /// |
76 | /// <div class="information"> |
77 | /// <div class="tooltip compile_fail" style="">⚠ ️</div> |
78 | /// </div><div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;"> |
79 | // |
80 | /// <strong>Warning</strong>: This will compile and execute code. <strong>Never</strong> pass untrusted code to this function! |
81 | /// |
82 | /// </pre></div> |
83 | /// |
84 | /// # Errors |
85 | /// |
86 | /// Returns `PyErr` if: |
87 | /// - `code` is not syntactically correct Python. |
88 | /// - Any Python exceptions are raised while initializing the module. |
89 | /// - Any of the arguments cannot be converted to [`CString`]s. |
90 | /// |
91 | /// # Example: bundle in a file at compile time with [`include_str!`][std::include_str]: |
92 | /// |
93 | /// ```rust |
94 | /// use pyo3::prelude::*; |
95 | /// |
96 | /// # fn main() -> PyResult<()> { |
97 | /// // This path is resolved relative to this file. |
98 | /// let code = include_str!("../../assets/script.py" ); |
99 | /// |
100 | /// Python::with_gil(|py| -> PyResult<()> { |
101 | /// PyModule::from_code(py, code, "example.py" , "example" )?; |
102 | /// Ok(()) |
103 | /// })?; |
104 | /// # Ok(()) |
105 | /// # } |
106 | /// ``` |
107 | /// |
108 | /// # Example: Load a file at runtime with [`std::fs::read_to_string`]. |
109 | /// |
110 | /// ```rust |
111 | /// use pyo3::prelude::*; |
112 | /// |
113 | /// # fn main() -> PyResult<()> { |
114 | /// // This path is resolved by however the platform resolves paths, |
115 | /// // which also makes this less portable. Consider using `include_str` |
116 | /// // if you just want to bundle a script with your module. |
117 | /// let code = std::fs::read_to_string("assets/script.py" )?; |
118 | /// |
119 | /// Python::with_gil(|py| -> PyResult<()> { |
120 | /// PyModule::from_code(py, &code, "example.py" , "example" )?; |
121 | /// Ok(()) |
122 | /// })?; |
123 | /// Ok(()) |
124 | /// # } |
125 | /// ``` |
126 | pub fn from_code<'p>( |
127 | py: Python<'p>, |
128 | code: &str, |
129 | file_name: &str, |
130 | module_name: &str, |
131 | ) -> PyResult<&'p PyModule> { |
132 | let data = CString::new(code)?; |
133 | let filename = CString::new(file_name)?; |
134 | let module = CString::new(module_name)?; |
135 | |
136 | unsafe { |
137 | let cptr = ffi::Py_CompileString(data.as_ptr(), filename.as_ptr(), ffi::Py_file_input); |
138 | if cptr.is_null() { |
139 | return Err(PyErr::fetch(py)); |
140 | } |
141 | |
142 | let mptr = ffi::PyImport_ExecCodeModuleEx(module.as_ptr(), cptr, filename.as_ptr()); |
143 | ffi::Py_DECREF(cptr); |
144 | if mptr.is_null() { |
145 | return Err(PyErr::fetch(py)); |
146 | } |
147 | |
148 | <&PyModule as crate::FromPyObject>::extract(py.from_owned_ptr_or_err(mptr)?) |
149 | } |
150 | } |
151 | |
152 | /// Returns the module's `__dict__` attribute, which contains the module's symbol table. |
153 | pub fn dict(&self) -> &PyDict { |
154 | unsafe { |
155 | // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890). |
156 | let ptr = ffi::PyModule_GetDict(self.as_ptr()); |
157 | self.py().from_owned_ptr(ffi::_Py_NewRef(ptr)) |
158 | } |
159 | } |
160 | |
161 | /// Returns the index (the `__all__` attribute) of the module, |
162 | /// creating one if needed. |
163 | /// |
164 | /// `__all__` declares the items that will be imported with `from my_module import *`. |
165 | pub fn index(&self) -> PyResult<&PyList> { |
166 | let __all__ = __all__(self.py()); |
167 | match self.getattr(__all__) { |
168 | Ok(idx) => idx.downcast().map_err(PyErr::from), |
169 | Err(err) => { |
170 | if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) { |
171 | let l = PyList::empty(self.py()); |
172 | self.setattr(__all__, l).map_err(PyErr::from)?; |
173 | Ok(l) |
174 | } else { |
175 | Err(err) |
176 | } |
177 | } |
178 | } |
179 | } |
180 | |
181 | /// Returns the name (the `__name__` attribute) of the module. |
182 | /// |
183 | /// May fail if the module does not have a `__name__` attribute. |
184 | pub fn name(&self) -> PyResult<&str> { |
185 | let ptr = unsafe { ffi::PyModule_GetName(self.as_ptr()) }; |
186 | if ptr.is_null() { |
187 | Err(PyErr::fetch(self.py())) |
188 | } else { |
189 | let name = unsafe { CStr::from_ptr(ptr) } |
190 | .to_str() |
191 | .expect("PyModule_GetName expected to return utf8" ); |
192 | Ok(name) |
193 | } |
194 | } |
195 | |
196 | /// Returns the filename (the `__file__` attribute) of the module. |
197 | /// |
198 | /// May fail if the module does not have a `__file__` attribute. |
199 | #[cfg (not(PyPy))] |
200 | pub fn filename(&self) -> PyResult<&str> { |
201 | unsafe { |
202 | self.py() |
203 | .from_owned_ptr_or_err::<PyString>(ffi::PyModule_GetFilenameObject(self.as_ptr()))? |
204 | .to_str() |
205 | } |
206 | } |
207 | |
208 | /// Adds an attribute to the module. |
209 | /// |
210 | /// For adding classes, functions or modules, prefer to use [`PyModule::add_class`], |
211 | /// [`PyModule::add_function`] or [`PyModule::add_submodule`] instead, respectively. |
212 | /// |
213 | /// # Examples |
214 | /// |
215 | /// ```rust |
216 | /// use pyo3::prelude::*; |
217 | /// |
218 | /// #[pymodule] |
219 | /// fn my_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> { |
220 | /// module.add("c" , 299_792_458)?; |
221 | /// Ok(()) |
222 | /// } |
223 | /// ``` |
224 | /// |
225 | /// Python code can then do the following: |
226 | /// |
227 | /// ```python |
228 | /// from my_module import c |
229 | /// |
230 | /// print("c is", c) |
231 | /// ``` |
232 | /// |
233 | /// This will result in the following output: |
234 | /// |
235 | /// ```text |
236 | /// c is 299792458 |
237 | /// ``` |
238 | pub fn add<V>(&self, name: &str, value: V) -> PyResult<()> |
239 | where |
240 | V: IntoPy<PyObject>, |
241 | { |
242 | self.index()? |
243 | .append(name) |
244 | .expect("could not append __name__ to __all__" ); |
245 | self.setattr(name, value.into_py(self.py())) |
246 | } |
247 | |
248 | /// Adds a new class to the module. |
249 | /// |
250 | /// Notice that this method does not take an argument. |
251 | /// Instead, this method is *generic*, and requires us to use the |
252 | /// "turbofish" syntax to specify the class we want to add. |
253 | /// |
254 | /// # Examples |
255 | /// |
256 | /// ```rust |
257 | /// use pyo3::prelude::*; |
258 | /// |
259 | /// #[pyclass] |
260 | /// struct Foo { /* fields omitted */ } |
261 | /// |
262 | /// #[pymodule] |
263 | /// fn my_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> { |
264 | /// module.add_class::<Foo>()?; |
265 | /// Ok(()) |
266 | /// } |
267 | /// ``` |
268 | /// |
269 | /// Python code can see this class as such: |
270 | /// ```python |
271 | /// from my_module import Foo |
272 | /// |
273 | /// print("Foo is", Foo) |
274 | /// ``` |
275 | /// |
276 | /// This will result in the following output: |
277 | /// ```text |
278 | /// Foo is <class 'builtins.Foo'> |
279 | /// ``` |
280 | /// |
281 | /// Note that as we haven't defined a [constructor][1], Python code can't actually |
282 | /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported |
283 | /// anything that can return instances of `Foo`). |
284 | /// |
285 | /// [1]: https://pyo3.rs/latest/class.html#constructor |
286 | pub fn add_class<T>(&self) -> PyResult<()> |
287 | where |
288 | T: PyClass, |
289 | { |
290 | let py = self.py(); |
291 | self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?) |
292 | } |
293 | |
294 | /// Adds a function or a (sub)module to a module, using the functions name as name. |
295 | /// |
296 | /// Prefer to use [`PyModule::add_function`] and/or [`PyModule::add_submodule`] instead. |
297 | pub fn add_wrapped<'a, T>(&'a self, wrapper: &impl Fn(Python<'a>) -> T) -> PyResult<()> |
298 | where |
299 | T: IntoPyCallbackOutput<PyObject>, |
300 | { |
301 | self._add_wrapped(wrapper(self.py()).convert(self.py())?) |
302 | } |
303 | |
304 | fn _add_wrapped(&self, object: PyObject) -> PyResult<()> { |
305 | let py = self.py(); |
306 | let name = object.getattr(py, __name__(py))?; |
307 | let name = name.extract(py)?; |
308 | self.add(name, object) |
309 | } |
310 | |
311 | /// Adds a submodule to a module. |
312 | /// |
313 | /// This is especially useful for creating module hierarchies. |
314 | /// |
315 | /// Note that this doesn't define a *package*, so this won't allow Python code |
316 | /// to directly import submodules by using |
317 | /// <span style="white-space: pre">`from my_module import submodule`</span>. |
318 | /// For more information, see [#759][1] and [#1517][2]. |
319 | /// |
320 | /// # Examples |
321 | /// |
322 | /// ```rust |
323 | /// use pyo3::prelude::*; |
324 | /// |
325 | /// #[pymodule] |
326 | /// fn my_module(py: Python<'_>, module: &PyModule) -> PyResult<()> { |
327 | /// let submodule = PyModule::new(py, "submodule" )?; |
328 | /// submodule.add("super_useful_constant" , "important" )?; |
329 | /// |
330 | /// module.add_submodule(submodule)?; |
331 | /// Ok(()) |
332 | /// } |
333 | /// ``` |
334 | /// |
335 | /// Python code can then do the following: |
336 | /// |
337 | /// ```python |
338 | /// import my_module |
339 | /// |
340 | /// print("super_useful_constant is", my_module.submodule.super_useful_constant) |
341 | /// ``` |
342 | /// |
343 | /// This will result in the following output: |
344 | /// |
345 | /// ```text |
346 | /// super_useful_constant is important |
347 | /// ``` |
348 | /// |
349 | /// [1]: https://github.com/PyO3/pyo3/issues/759 |
350 | /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021 |
351 | pub fn add_submodule(&self, module: &PyModule) -> PyResult<()> { |
352 | let name = module.name()?; |
353 | self.add(name, module) |
354 | } |
355 | |
356 | /// Add a function to a module. |
357 | /// |
358 | /// Note that this also requires the [`wrap_pyfunction!`][2] macro |
359 | /// to wrap a function annotated with [`#[pyfunction]`][1]. |
360 | /// |
361 | /// ```rust |
362 | /// use pyo3::prelude::*; |
363 | /// |
364 | /// #[pyfunction] |
365 | /// fn say_hello() { |
366 | /// println!("Hello world!" ) |
367 | /// } |
368 | /// #[pymodule] |
369 | /// fn my_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> { |
370 | /// module.add_function(wrap_pyfunction!(say_hello, module)?) |
371 | /// } |
372 | /// ``` |
373 | /// |
374 | /// Python code can then do the following: |
375 | /// |
376 | /// ```python |
377 | /// from my_module import say_hello |
378 | /// |
379 | /// say_hello() |
380 | /// ``` |
381 | /// |
382 | /// This will result in the following output: |
383 | /// |
384 | /// ```text |
385 | /// Hello world! |
386 | /// ``` |
387 | /// |
388 | /// [1]: crate::prelude::pyfunction |
389 | /// [2]: crate::wrap_pyfunction |
390 | pub fn add_function<'a>(&'a self, fun: &'a PyCFunction) -> PyResult<()> { |
391 | let name = fun.getattr(__name__(self.py()))?.extract()?; |
392 | self.add(name, fun) |
393 | } |
394 | } |
395 | |
396 | fn __all__(py: Python<'_>) -> &PyString { |
397 | intern!(py, "__all__" ) |
398 | } |
399 | |
400 | fn __name__(py: Python<'_>) -> &PyString { |
401 | intern!(py, "__name__" ) |
402 | } |
403 | |
404 | #[cfg (test)] |
405 | mod tests { |
406 | use crate::{types::PyModule, Python}; |
407 | |
408 | #[test ] |
409 | fn module_import_and_name() { |
410 | Python::with_gil(|py| { |
411 | let builtins = PyModule::import(py, "builtins" ).unwrap(); |
412 | assert_eq!(builtins.name().unwrap(), "builtins" ); |
413 | }) |
414 | } |
415 | } |
416 | |