1 | use crate::class::basic::CompareOp; |
2 | use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, PyTryFrom, ToPyObject}; |
3 | use crate::err::{PyDowncastError, PyErr, PyResult}; |
4 | use crate::exceptions::{PyAttributeError, PyTypeError}; |
5 | use crate::type_object::PyTypeInfo; |
6 | #[cfg (not(PyPy))] |
7 | use crate::types::PySuper; |
8 | use crate::types::{PyDict, PyIterator, PyList, PyString, PyTuple, PyType}; |
9 | use crate::{err, ffi, Py, PyNativeType, PyObject, Python}; |
10 | use std::cell::UnsafeCell; |
11 | use std::cmp::Ordering; |
12 | use std::os::raw::c_int; |
13 | |
14 | /// Represents any Python object. |
15 | /// |
16 | /// It currently only appears as a *reference*, `&PyAny`, |
17 | /// with a lifetime that represents the scope during which the GIL is held. |
18 | /// |
19 | /// `PyAny` has some interesting properties, which it shares |
20 | /// with the other [native Python types](crate::types): |
21 | /// |
22 | /// - It can only be obtained and used while the GIL is held, |
23 | /// therefore its API does not require a [`Python<'py>`](crate::Python) token. |
24 | /// - It can't be used in situations where the GIL is temporarily released, |
25 | /// such as [`Python::allow_threads`](crate::Python::allow_threads)'s closure. |
26 | /// - The underlying Python object, if mutable, can be mutated through any reference. |
27 | /// - It can be converted to the GIL-independent [`Py`]`<`[`PyAny`]`>`, |
28 | /// allowing it to outlive the GIL scope. However, using [`Py`]`<`[`PyAny`]`>`'s API |
29 | /// *does* require a [`Python<'py>`](crate::Python) token. |
30 | /// |
31 | /// It can be cast to a concrete type with PyAny::downcast (for native Python types only) |
32 | /// and FromPyObject::extract. See their documentation for more information. |
33 | /// |
34 | /// See [the guide](https://pyo3.rs/latest/types.html) for an explanation |
35 | /// of the different Python object types. |
36 | #[repr (transparent)] |
37 | pub struct PyAny(UnsafeCell<ffi::PyObject>); |
38 | |
39 | unsafe impl AsPyPointer for PyAny { |
40 | #[inline ] |
41 | fn as_ptr(&self) -> *mut ffi::PyObject { |
42 | self.0.get() |
43 | } |
44 | } |
45 | |
46 | #[allow (non_snake_case)] |
47 | // Copied here as the macro does not accept deprecated functions. |
48 | // Originally ffi::object::PyObject_Check, but this is not in the Python C API. |
49 | fn PyObject_Check(_: *mut ffi::PyObject) -> c_int { |
50 | 1 |
51 | } |
52 | |
53 | pyobject_native_type_base!(PyAny); |
54 | |
55 | pyobject_native_type_info!( |
56 | PyAny, |
57 | pyobject_native_static_type_object!(ffi::PyBaseObject_Type), |
58 | Some("builtins" ), |
59 | #checkfunction=PyObject_Check |
60 | ); |
61 | |
62 | pyobject_native_type_extract!(PyAny); |
63 | |
64 | pyobject_native_type_sized!(PyAny, ffi::PyObject); |
65 | |
66 | impl PyAny { |
67 | /// Returns whether `self` and `other` point to the same object. To compare |
68 | /// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq). |
69 | /// |
70 | /// This is equivalent to the Python expression `self is other`. |
71 | #[inline ] |
72 | pub fn is<T: AsPyPointer>(&self, other: &T) -> bool { |
73 | self.as_ptr() == other.as_ptr() |
74 | } |
75 | |
76 | /// Determines whether this object has the given attribute. |
77 | /// |
78 | /// This is equivalent to the Python expression `hasattr(self, attr_name)`. |
79 | /// |
80 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
81 | /// to intern `attr_name`. |
82 | /// |
83 | /// # Example: `intern!`ing the attribute name |
84 | /// |
85 | /// ``` |
86 | /// # use pyo3::{intern, pyfunction, types::PyModule, Python, PyResult}; |
87 | /// # |
88 | /// #[pyfunction] |
89 | /// fn has_version(sys: &PyModule) -> PyResult<bool> { |
90 | /// sys.hasattr(intern!(sys.py(), "version" )) |
91 | /// } |
92 | /// # |
93 | /// # Python::with_gil(|py| { |
94 | /// # let sys = py.import("sys" ).unwrap(); |
95 | /// # has_version(sys).unwrap(); |
96 | /// # }); |
97 | /// ``` |
98 | pub fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> |
99 | where |
100 | N: IntoPy<Py<PyString>>, |
101 | { |
102 | fn inner(any: &PyAny, attr_name: Py<PyString>) -> PyResult<bool> { |
103 | // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2. |
104 | // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3. |
105 | match any._getattr(attr_name) { |
106 | Ok(_) => Ok(true), |
107 | Err(err) if err.is_instance_of::<PyAttributeError>(any.py()) => Ok(false), |
108 | Err(e) => Err(e), |
109 | } |
110 | } |
111 | |
112 | inner(self, attr_name.into_py(self.py())) |
113 | } |
114 | |
115 | /// Retrieves an attribute value. |
116 | /// |
117 | /// This is equivalent to the Python expression `self.attr_name`. |
118 | /// |
119 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
120 | /// to intern `attr_name`. |
121 | /// |
122 | /// # Example: `intern!`ing the attribute name |
123 | /// |
124 | /// ``` |
125 | /// # use pyo3::{intern, pyfunction, types::PyModule, PyAny, Python, PyResult}; |
126 | /// # |
127 | /// #[pyfunction] |
128 | /// fn version(sys: &PyModule) -> PyResult<&PyAny> { |
129 | /// sys.getattr(intern!(sys.py(), "version" )) |
130 | /// } |
131 | /// # |
132 | /// # Python::with_gil(|py| { |
133 | /// # let sys = py.import("sys" ).unwrap(); |
134 | /// # version(sys).unwrap(); |
135 | /// # }); |
136 | /// ``` |
137 | pub fn getattr<N>(&self, attr_name: N) -> PyResult<&PyAny> |
138 | where |
139 | N: IntoPy<Py<PyString>>, |
140 | { |
141 | fn inner(any: &PyAny, attr_name: Py<PyString>) -> PyResult<&PyAny> { |
142 | any._getattr(attr_name) |
143 | .map(|object| object.into_ref(any.py())) |
144 | } |
145 | |
146 | inner(self, attr_name.into_py(self.py())) |
147 | } |
148 | |
149 | fn _getattr(&self, attr_name: Py<PyString>) -> PyResult<PyObject> { |
150 | unsafe { |
151 | Py::from_owned_ptr_or_err( |
152 | self.py(), |
153 | ffi::PyObject_GetAttr(self.as_ptr(), attr_name.as_ptr()), |
154 | ) |
155 | } |
156 | } |
157 | |
158 | /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still |
159 | /// binding the object to the instance. |
160 | /// |
161 | /// This is useful when trying to resolve Python's "magic" methods like `__getitem__`, which |
162 | /// are looked up starting from the type object. This returns an `Option` as it is not |
163 | /// typically a direct error for the special lookup to fail, as magic methods are optional in |
164 | /// many situations in which they might be called. |
165 | /// |
166 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
167 | /// to intern `attr_name`. |
168 | #[allow (dead_code)] // Currently only used with num-complex+abi3, so dead without that. |
169 | pub(crate) fn lookup_special<N>(&self, attr_name: N) -> PyResult<Option<&PyAny>> |
170 | where |
171 | N: IntoPy<Py<PyString>>, |
172 | { |
173 | let py = self.py(); |
174 | let self_type = self.get_type(); |
175 | let attr = if let Ok(attr) = self_type.getattr(attr_name) { |
176 | attr |
177 | } else { |
178 | return Ok(None); |
179 | }; |
180 | |
181 | // Manually resolve descriptor protocol. |
182 | if cfg!(Py_3_10) |
183 | || unsafe { ffi::PyType_HasFeature(attr.get_type_ptr(), ffi::Py_TPFLAGS_HEAPTYPE) } != 0 |
184 | { |
185 | // This is the preferred faster path, but does not work on static types (generally, |
186 | // types defined in extension modules) before Python 3.10. |
187 | unsafe { |
188 | let descr_get_ptr = ffi::PyType_GetSlot(attr.get_type_ptr(), ffi::Py_tp_descr_get); |
189 | if descr_get_ptr.is_null() { |
190 | return Ok(Some(attr)); |
191 | } |
192 | let descr_get: ffi::descrgetfunc = std::mem::transmute(descr_get_ptr); |
193 | let ret = descr_get(attr.as_ptr(), self.as_ptr(), self_type.as_ptr()); |
194 | py.from_owned_ptr_or_err(ret).map(Some) |
195 | } |
196 | } else if let Ok(descr_get) = attr.get_type().getattr(crate::intern!(py, "__get__" )) { |
197 | descr_get.call1((attr, self, self_type)).map(Some) |
198 | } else { |
199 | Ok(Some(attr)) |
200 | } |
201 | } |
202 | |
203 | /// Sets an attribute value. |
204 | /// |
205 | /// This is equivalent to the Python expression `self.attr_name = value`. |
206 | /// |
207 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
208 | /// to intern `name`. |
209 | /// |
210 | /// # Example: `intern!`ing the attribute name |
211 | /// |
212 | /// ``` |
213 | /// # use pyo3::{intern, pyfunction, types::PyModule, PyAny, Python, PyResult}; |
214 | /// # |
215 | /// #[pyfunction] |
216 | /// fn set_answer(ob: &PyAny) -> PyResult<()> { |
217 | /// ob.setattr(intern!(ob.py(), "answer" ), 42) |
218 | /// } |
219 | /// # |
220 | /// # Python::with_gil(|py| { |
221 | /// # let ob = PyModule::new(py, "empty" ).unwrap(); |
222 | /// # set_answer(ob).unwrap(); |
223 | /// # }); |
224 | /// ``` |
225 | pub fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()> |
226 | where |
227 | N: IntoPy<Py<PyString>>, |
228 | V: ToPyObject, |
229 | { |
230 | fn inner(any: &PyAny, attr_name: Py<PyString>, value: PyObject) -> PyResult<()> { |
231 | err::error_on_minusone(any.py(), unsafe { |
232 | ffi::PyObject_SetAttr(any.as_ptr(), attr_name.as_ptr(), value.as_ptr()) |
233 | }) |
234 | } |
235 | |
236 | let py = self.py(); |
237 | inner(self, attr_name.into_py(py), value.to_object(py)) |
238 | } |
239 | |
240 | /// Deletes an attribute. |
241 | /// |
242 | /// This is equivalent to the Python statement `del self.attr_name`. |
243 | /// |
244 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
245 | /// to intern `attr_name`. |
246 | pub fn delattr<N>(&self, attr_name: N) -> PyResult<()> |
247 | where |
248 | N: IntoPy<Py<PyString>>, |
249 | { |
250 | fn inner(any: &PyAny, attr_name: Py<PyString>) -> PyResult<()> { |
251 | err::error_on_minusone(any.py(), unsafe { |
252 | ffi::PyObject_DelAttr(any.as_ptr(), attr_name.as_ptr()) |
253 | }) |
254 | } |
255 | |
256 | inner(self, attr_name.into_py(self.py())) |
257 | } |
258 | |
259 | /// Returns an [`Ordering`] between `self` and `other`. |
260 | /// |
261 | /// This is equivalent to the following Python code: |
262 | /// ```python |
263 | /// if self == other: |
264 | /// return Equal |
265 | /// elif a < b: |
266 | /// return Less |
267 | /// elif a > b: |
268 | /// return Greater |
269 | /// else: |
270 | /// raise TypeError("PyAny::compare(): All comparisons returned false") |
271 | /// ``` |
272 | /// |
273 | /// # Examples |
274 | /// |
275 | /// ```rust |
276 | /// use pyo3::prelude::*; |
277 | /// use pyo3::types::PyFloat; |
278 | /// use std::cmp::Ordering; |
279 | /// |
280 | /// # fn main() -> PyResult<()> { |
281 | /// Python::with_gil(|py| -> PyResult<()> { |
282 | /// let a = PyFloat::new(py, 0_f64); |
283 | /// let b = PyFloat::new(py, 42_f64); |
284 | /// assert_eq!(a.compare(b)?, Ordering::Less); |
285 | /// Ok(()) |
286 | /// })?; |
287 | /// # Ok(())} |
288 | /// ``` |
289 | /// |
290 | /// It will return `PyErr` for values that cannot be compared: |
291 | /// |
292 | /// ```rust |
293 | /// use pyo3::prelude::*; |
294 | /// use pyo3::types::{PyFloat, PyString}; |
295 | /// |
296 | /// # fn main() -> PyResult<()> { |
297 | /// Python::with_gil(|py| -> PyResult<()> { |
298 | /// let a = PyFloat::new(py, 0_f64); |
299 | /// let b = PyString::new(py, "zero" ); |
300 | /// assert!(a.compare(b).is_err()); |
301 | /// Ok(()) |
302 | /// })?; |
303 | /// # Ok(())} |
304 | /// ``` |
305 | pub fn compare<O>(&self, other: O) -> PyResult<Ordering> |
306 | where |
307 | O: ToPyObject, |
308 | { |
309 | self._compare(other.to_object(self.py())) |
310 | } |
311 | |
312 | fn _compare(&self, other: PyObject) -> PyResult<Ordering> { |
313 | let py = self.py(); |
314 | let other = other.as_ptr(); |
315 | // Almost the same as ffi::PyObject_RichCompareBool, but this one doesn't try self == other. |
316 | // See https://github.com/PyO3/pyo3/issues/985 for more. |
317 | let do_compare = |other, op| unsafe { |
318 | PyObject::from_owned_ptr_or_err(py, ffi::PyObject_RichCompare(self.as_ptr(), other, op)) |
319 | .and_then(|obj| obj.is_true(py)) |
320 | }; |
321 | if do_compare(other, ffi::Py_EQ)? { |
322 | Ok(Ordering::Equal) |
323 | } else if do_compare(other, ffi::Py_LT)? { |
324 | Ok(Ordering::Less) |
325 | } else if do_compare(other, ffi::Py_GT)? { |
326 | Ok(Ordering::Greater) |
327 | } else { |
328 | Err(PyTypeError::new_err( |
329 | "PyAny::compare(): All comparisons returned false" , |
330 | )) |
331 | } |
332 | } |
333 | |
334 | /// Tests whether two Python objects obey a given [`CompareOp`]. |
335 | /// |
336 | /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne), |
337 | /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions |
338 | /// of this function. |
339 | /// |
340 | /// Depending on the value of `compare_op`, this is equivalent to one of the |
341 | /// following Python expressions: |
342 | /// |
343 | /// | `compare_op` | Python expression | |
344 | /// | :---: | :----: | |
345 | /// | [`CompareOp::Eq`] | `self == other` | |
346 | /// | [`CompareOp::Ne`] | `self != other` | |
347 | /// | [`CompareOp::Lt`] | `self < other` | |
348 | /// | [`CompareOp::Le`] | `self <= other` | |
349 | /// | [`CompareOp::Gt`] | `self > other` | |
350 | /// | [`CompareOp::Ge`] | `self >= other` | |
351 | /// |
352 | /// # Examples |
353 | /// |
354 | /// ```rust |
355 | /// use pyo3::class::basic::CompareOp; |
356 | /// use pyo3::prelude::*; |
357 | /// use pyo3::types::PyInt; |
358 | /// |
359 | /// # fn main() -> PyResult<()> { |
360 | /// Python::with_gil(|py| -> PyResult<()> { |
361 | /// let a: &PyInt = 0_u8.into_py(py).into_ref(py).downcast()?; |
362 | /// let b: &PyInt = 42_u8.into_py(py).into_ref(py).downcast()?; |
363 | /// assert!(a.rich_compare(b, CompareOp::Le)?.is_true()?); |
364 | /// Ok(()) |
365 | /// })?; |
366 | /// # Ok(())} |
367 | /// ``` |
368 | pub fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<&PyAny> |
369 | where |
370 | O: ToPyObject, |
371 | { |
372 | fn inner(slf: &PyAny, other: PyObject, compare_op: CompareOp) -> PyResult<&PyAny> { |
373 | unsafe { |
374 | slf.py().from_owned_ptr_or_err(ffi::PyObject_RichCompare( |
375 | slf.as_ptr(), |
376 | other.as_ptr(), |
377 | compare_op as c_int, |
378 | )) |
379 | } |
380 | } |
381 | |
382 | inner(self, other.to_object(self.py()), compare_op) |
383 | } |
384 | |
385 | /// Tests whether this object is less than another. |
386 | /// |
387 | /// This is equivalent to the Python expression `self < other`. |
388 | pub fn lt<O>(&self, other: O) -> PyResult<bool> |
389 | where |
390 | O: ToPyObject, |
391 | { |
392 | self.rich_compare(other, CompareOp::Lt)?.is_true() |
393 | } |
394 | |
395 | /// Tests whether this object is less than or equal to another. |
396 | /// |
397 | /// This is equivalent to the Python expression `self <= other`. |
398 | pub fn le<O>(&self, other: O) -> PyResult<bool> |
399 | where |
400 | O: ToPyObject, |
401 | { |
402 | self.rich_compare(other, CompareOp::Le)?.is_true() |
403 | } |
404 | |
405 | /// Tests whether this object is equal to another. |
406 | /// |
407 | /// This is equivalent to the Python expression `self == other`. |
408 | pub fn eq<O>(&self, other: O) -> PyResult<bool> |
409 | where |
410 | O: ToPyObject, |
411 | { |
412 | self.rich_compare(other, CompareOp::Eq)?.is_true() |
413 | } |
414 | |
415 | /// Tests whether this object is not equal to another. |
416 | /// |
417 | /// This is equivalent to the Python expression `self != other`. |
418 | pub fn ne<O>(&self, other: O) -> PyResult<bool> |
419 | where |
420 | O: ToPyObject, |
421 | { |
422 | self.rich_compare(other, CompareOp::Ne)?.is_true() |
423 | } |
424 | |
425 | /// Tests whether this object is greater than another. |
426 | /// |
427 | /// This is equivalent to the Python expression `self > other`. |
428 | pub fn gt<O>(&self, other: O) -> PyResult<bool> |
429 | where |
430 | O: ToPyObject, |
431 | { |
432 | self.rich_compare(other, CompareOp::Gt)?.is_true() |
433 | } |
434 | |
435 | /// Tests whether this object is greater than or equal to another. |
436 | /// |
437 | /// This is equivalent to the Python expression `self >= other`. |
438 | pub fn ge<O>(&self, other: O) -> PyResult<bool> |
439 | where |
440 | O: ToPyObject, |
441 | { |
442 | self.rich_compare(other, CompareOp::Ge)?.is_true() |
443 | } |
444 | |
445 | /// Determines whether this object appears callable. |
446 | /// |
447 | /// This is equivalent to Python's [`callable()`][1] function. |
448 | /// |
449 | /// # Examples |
450 | /// |
451 | /// ```rust |
452 | /// use pyo3::prelude::*; |
453 | /// |
454 | /// # fn main() -> PyResult<()> { |
455 | /// Python::with_gil(|py| -> PyResult<()> { |
456 | /// let builtins = PyModule::import(py, "builtins" )?; |
457 | /// let print = builtins.getattr("print" )?; |
458 | /// assert!(print.is_callable()); |
459 | /// Ok(()) |
460 | /// })?; |
461 | /// # Ok(())} |
462 | /// ``` |
463 | /// |
464 | /// This is equivalent to the Python statement `assert callable(print)`. |
465 | /// |
466 | /// Note that unless an API needs to distinguish between callable and |
467 | /// non-callable objects, there is no point in checking for callability. |
468 | /// Instead, it is better to just do the call and handle potential |
469 | /// exceptions. |
470 | /// |
471 | /// [1]: https://docs.python.org/3/library/functions.html#callable |
472 | pub fn is_callable(&self) -> bool { |
473 | unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 } |
474 | } |
475 | |
476 | /// Calls the object. |
477 | /// |
478 | /// This is equivalent to the Python expression `self(*args, **kwargs)`. |
479 | /// |
480 | /// # Examples |
481 | /// |
482 | /// ```rust |
483 | /// use pyo3::prelude::*; |
484 | /// use pyo3::types::PyDict; |
485 | /// |
486 | /// const CODE: &str = r#" |
487 | /// def function(*args, **kwargs): |
488 | /// assert args == ("hello",) |
489 | /// assert kwargs == {"cruel": "world"} |
490 | /// return "called with args and kwargs" |
491 | /// "# ; |
492 | /// |
493 | /// # fn main() -> PyResult<()> { |
494 | /// Python::with_gil(|py| { |
495 | /// let module = PyModule::from_code(py, CODE, "" , "" )?; |
496 | /// let fun = module.getattr("function" )?; |
497 | /// let args = ("hello" ,); |
498 | /// let kwargs = PyDict::new(py); |
499 | /// kwargs.set_item("cruel" , "world" )?; |
500 | /// let result = fun.call(args, Some(kwargs))?; |
501 | /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs" ); |
502 | /// Ok(()) |
503 | /// }) |
504 | /// # } |
505 | /// ``` |
506 | pub fn call( |
507 | &self, |
508 | args: impl IntoPy<Py<PyTuple>>, |
509 | kwargs: Option<&PyDict>, |
510 | ) -> PyResult<&PyAny> { |
511 | let py = self.py(); |
512 | |
513 | let args = args.into_py(py); |
514 | let kwargs = kwargs.map_or(std::ptr::null_mut(), |kwargs| kwargs.as_ptr()); |
515 | |
516 | unsafe { |
517 | let return_value = ffi::PyObject_Call(self.as_ptr(), args.as_ptr(), kwargs); |
518 | let ret = py.from_owned_ptr_or_err(return_value); |
519 | ret |
520 | } |
521 | } |
522 | |
523 | /// Calls the object without arguments. |
524 | /// |
525 | /// This is equivalent to the Python expression `self()`. |
526 | /// |
527 | /// # Examples |
528 | /// |
529 | /// ```no_run |
530 | /// use pyo3::prelude::*; |
531 | /// |
532 | /// # fn main() -> PyResult<()> { |
533 | /// Python::with_gil(|py| -> PyResult<()> { |
534 | /// let module = PyModule::import(py, "builtins" )?; |
535 | /// let help = module.getattr("help" )?; |
536 | /// help.call0()?; |
537 | /// Ok(()) |
538 | /// })?; |
539 | /// # Ok(())} |
540 | /// ``` |
541 | /// |
542 | /// This is equivalent to the Python expression `help()`. |
543 | pub fn call0(&self) -> PyResult<&PyAny> { |
544 | cfg_if::cfg_if! { |
545 | if #[cfg(all( |
546 | not(PyPy), |
547 | any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // PyObject_CallNoArgs was added to python in 3.9 but to limited API in 3.10 |
548 | ))] { |
549 | // Optimized path on python 3.9+ |
550 | unsafe { |
551 | self.py().from_owned_ptr_or_err(ffi::PyObject_CallNoArgs(self.as_ptr())) |
552 | } |
553 | } else { |
554 | self.call((), None) |
555 | } |
556 | } |
557 | } |
558 | |
559 | /// Calls the object with only positional arguments. |
560 | /// |
561 | /// This is equivalent to the Python expression `self(*args)`. |
562 | /// |
563 | /// # Examples |
564 | /// |
565 | /// ```rust |
566 | /// use pyo3::prelude::*; |
567 | /// |
568 | /// const CODE: &str = r#" |
569 | /// def function(*args, **kwargs): |
570 | /// assert args == ("hello",) |
571 | /// assert kwargs == {} |
572 | /// return "called with args" |
573 | /// "# ; |
574 | /// |
575 | /// # fn main() -> PyResult<()> { |
576 | /// Python::with_gil(|py| { |
577 | /// let module = PyModule::from_code(py, CODE, "" , "" )?; |
578 | /// let fun = module.getattr("function" )?; |
579 | /// let args = ("hello" ,); |
580 | /// let result = fun.call1(args)?; |
581 | /// assert_eq!(result.extract::<&str>()?, "called with args" ); |
582 | /// Ok(()) |
583 | /// }) |
584 | /// # } |
585 | /// ``` |
586 | pub fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> { |
587 | self.call(args, None) |
588 | } |
589 | |
590 | /// Calls a method on the object. |
591 | /// |
592 | /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. |
593 | /// |
594 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
595 | /// to intern `name`. |
596 | /// |
597 | /// # Examples |
598 | /// |
599 | /// ```rust |
600 | /// use pyo3::prelude::*; |
601 | /// use pyo3::types::PyDict; |
602 | /// |
603 | /// const CODE: &str = r#" |
604 | /// class A: |
605 | /// def method(self, *args, **kwargs): |
606 | /// assert args == ("hello",) |
607 | /// assert kwargs == {"cruel": "world"} |
608 | /// return "called with args and kwargs" |
609 | /// a = A() |
610 | /// "# ; |
611 | /// |
612 | /// # fn main() -> PyResult<()> { |
613 | /// Python::with_gil(|py| { |
614 | /// let module = PyModule::from_code(py, CODE, "" , "" )?; |
615 | /// let instance = module.getattr("a" )?; |
616 | /// let args = ("hello" ,); |
617 | /// let kwargs = PyDict::new(py); |
618 | /// kwargs.set_item("cruel" , "world" )?; |
619 | /// let result = instance.call_method("method" , args, Some(kwargs))?; |
620 | /// assert_eq!(result.extract::<&str>()?, "called with args and kwargs" ); |
621 | /// Ok(()) |
622 | /// }) |
623 | /// # } |
624 | /// ``` |
625 | pub fn call_method<N, A>(&self, name: N, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyAny> |
626 | where |
627 | N: IntoPy<Py<PyString>>, |
628 | A: IntoPy<Py<PyTuple>>, |
629 | { |
630 | let py = self.py(); |
631 | |
632 | let callee = self.getattr(name)?; |
633 | let args: Py<PyTuple> = args.into_py(py); |
634 | let kwargs = kwargs.map_or(std::ptr::null_mut(), |kwargs| kwargs.as_ptr()); |
635 | |
636 | unsafe { |
637 | let result_ptr = ffi::PyObject_Call(callee.as_ptr(), args.as_ptr(), kwargs); |
638 | let result = py.from_owned_ptr_or_err(result_ptr); |
639 | result |
640 | } |
641 | } |
642 | |
643 | /// Calls a method on the object without arguments. |
644 | /// |
645 | /// This is equivalent to the Python expression `self.name()`. |
646 | /// |
647 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
648 | /// to intern `name`. |
649 | /// |
650 | /// # Examples |
651 | /// |
652 | /// ```rust |
653 | /// use pyo3::prelude::*; |
654 | /// |
655 | /// const CODE: &str = r#" |
656 | /// class A: |
657 | /// def method(self, *args, **kwargs): |
658 | /// assert args == () |
659 | /// assert kwargs == {} |
660 | /// return "called with no arguments" |
661 | /// a = A() |
662 | /// "# ; |
663 | /// |
664 | /// # fn main() -> PyResult<()> { |
665 | /// Python::with_gil(|py| { |
666 | /// let module = PyModule::from_code(py, CODE, "" , "" )?; |
667 | /// let instance = module.getattr("a" )?; |
668 | /// let result = instance.call_method0("method" )?; |
669 | /// assert_eq!(result.extract::<&str>()?, "called with no arguments" ); |
670 | /// Ok(()) |
671 | /// }) |
672 | /// # } |
673 | /// ``` |
674 | pub fn call_method0<N>(&self, name: N) -> PyResult<&PyAny> |
675 | where |
676 | N: IntoPy<Py<PyString>>, |
677 | { |
678 | cfg_if::cfg_if! { |
679 | if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))))] { |
680 | let py = self.py(); |
681 | |
682 | // Optimized path on python 3.9+ |
683 | unsafe { |
684 | let name: Py<PyString> = name.into_py(py); |
685 | let ptr = ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()); |
686 | py.from_owned_ptr_or_err(ptr) |
687 | } |
688 | } else { |
689 | self.call_method(name, (), None) |
690 | } |
691 | } |
692 | } |
693 | |
694 | /// Calls a method on the object with only positional arguments. |
695 | /// |
696 | /// This is equivalent to the Python expression `self.name(*args)`. |
697 | /// |
698 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used |
699 | /// to intern `name`. |
700 | /// |
701 | /// # Examples |
702 | /// |
703 | /// ```rust |
704 | /// use pyo3::prelude::*; |
705 | /// |
706 | /// const CODE: &str = r#" |
707 | /// class A: |
708 | /// def method(self, *args, **kwargs): |
709 | /// assert args == ("hello",) |
710 | /// assert kwargs == {} |
711 | /// return "called with args" |
712 | /// a = A() |
713 | /// "# ; |
714 | /// |
715 | /// # fn main() -> PyResult<()> { |
716 | /// Python::with_gil(|py| { |
717 | /// let module = PyModule::from_code(py, CODE, "" , "" )?; |
718 | /// let instance = module.getattr("a" )?; |
719 | /// let args = ("hello" ,); |
720 | /// let result = instance.call_method1("method" , args)?; |
721 | /// assert_eq!(result.extract::<&str>()?, "called with args" ); |
722 | /// Ok(()) |
723 | /// }) |
724 | /// # } |
725 | /// ``` |
726 | pub fn call_method1<N, A>(&self, name: N, args: A) -> PyResult<&PyAny> |
727 | where |
728 | N: IntoPy<Py<PyString>>, |
729 | A: IntoPy<Py<PyTuple>>, |
730 | { |
731 | self.call_method(name, args, None) |
732 | } |
733 | |
734 | /// Returns whether the object is considered to be true. |
735 | /// |
736 | /// This is equivalent to the Python expression `bool(self)`. |
737 | pub fn is_true(&self) -> PyResult<bool> { |
738 | let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; |
739 | err::error_on_minusone(self.py(), v)?; |
740 | Ok(v != 0) |
741 | } |
742 | |
743 | /// Returns whether the object is considered to be None. |
744 | /// |
745 | /// This is equivalent to the Python expression `self is None`. |
746 | #[inline ] |
747 | pub fn is_none(&self) -> bool { |
748 | unsafe { ffi::Py_None() == self.as_ptr() } |
749 | } |
750 | |
751 | /// Returns whether the object is Ellipsis, e.g. `...`. |
752 | /// |
753 | /// This is equivalent to the Python expression `self is ...`. |
754 | pub fn is_ellipsis(&self) -> bool { |
755 | unsafe { ffi::Py_Ellipsis() == self.as_ptr() } |
756 | } |
757 | |
758 | /// Returns true if the sequence or mapping has a length of 0. |
759 | /// |
760 | /// This is equivalent to the Python expression `len(self) == 0`. |
761 | pub fn is_empty(&self) -> PyResult<bool> { |
762 | self.len().map(|l| l == 0) |
763 | } |
764 | |
765 | /// Gets an item from the collection. |
766 | /// |
767 | /// This is equivalent to the Python expression `self[key]`. |
768 | pub fn get_item<K>(&self, key: K) -> PyResult<&PyAny> |
769 | where |
770 | K: ToPyObject, |
771 | { |
772 | fn inner(slf: &PyAny, key: PyObject) -> PyResult<&PyAny> { |
773 | unsafe { |
774 | slf.py() |
775 | .from_owned_ptr_or_err(ffi::PyObject_GetItem(slf.as_ptr(), key.as_ptr())) |
776 | } |
777 | } |
778 | |
779 | inner(self, key.to_object(self.py())) |
780 | } |
781 | |
782 | /// Sets a collection item value. |
783 | /// |
784 | /// This is equivalent to the Python expression `self[key] = value`. |
785 | pub fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()> |
786 | where |
787 | K: ToPyObject, |
788 | V: ToPyObject, |
789 | { |
790 | fn inner(slf: &PyAny, key: PyObject, value: PyObject) -> PyResult<()> { |
791 | err::error_on_minusone(slf.py(), unsafe { |
792 | ffi::PyObject_SetItem(slf.as_ptr(), key.as_ptr(), value.as_ptr()) |
793 | }) |
794 | } |
795 | |
796 | let py = self.py(); |
797 | inner(self, key.to_object(py), value.to_object(py)) |
798 | } |
799 | |
800 | /// Deletes an item from the collection. |
801 | /// |
802 | /// This is equivalent to the Python expression `del self[key]`. |
803 | pub fn del_item<K>(&self, key: K) -> PyResult<()> |
804 | where |
805 | K: ToPyObject, |
806 | { |
807 | fn inner(slf: &PyAny, key: PyObject) -> PyResult<()> { |
808 | err::error_on_minusone(slf.py(), unsafe { |
809 | ffi::PyObject_DelItem(slf.as_ptr(), key.as_ptr()) |
810 | }) |
811 | } |
812 | |
813 | inner(self, key.to_object(self.py())) |
814 | } |
815 | |
816 | /// Takes an object and returns an iterator for it. |
817 | /// |
818 | /// This is typically a new iterator but if the argument is an iterator, |
819 | /// this returns itself. |
820 | pub fn iter(&self) -> PyResult<&PyIterator> { |
821 | PyIterator::from_object(self) |
822 | } |
823 | |
824 | /// Returns the Python type object for this object's type. |
825 | pub fn get_type(&self) -> &PyType { |
826 | unsafe { PyType::from_type_ptr(self.py(), ffi::Py_TYPE(self.as_ptr())) } |
827 | } |
828 | |
829 | /// Returns the Python type pointer for this object. |
830 | #[inline ] |
831 | pub fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { |
832 | unsafe { ffi::Py_TYPE(self.as_ptr()) } |
833 | } |
834 | |
835 | /// Downcast this `PyAny` to a concrete Python type or pyclass. |
836 | /// |
837 | /// Note that you can often avoid downcasting yourself by just specifying |
838 | /// the desired type in function or method signatures. |
839 | /// However, manual downcasting is sometimes necessary. |
840 | /// |
841 | /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). |
842 | /// |
843 | /// # Example: Downcasting to a specific Python object |
844 | /// |
845 | /// ```rust |
846 | /// use pyo3::prelude::*; |
847 | /// use pyo3::types::{PyDict, PyList}; |
848 | /// |
849 | /// Python::with_gil(|py| { |
850 | /// let dict = PyDict::new(py); |
851 | /// assert!(dict.is_instance_of::<PyAny>()); |
852 | /// let any: &PyAny = dict.as_ref(); |
853 | /// |
854 | /// assert!(any.downcast::<PyDict>().is_ok()); |
855 | /// assert!(any.downcast::<PyList>().is_err()); |
856 | /// }); |
857 | /// ``` |
858 | /// |
859 | /// # Example: Getting a reference to a pyclass |
860 | /// |
861 | /// This is useful if you want to mutate a `PyObject` that |
862 | /// might actually be a pyclass. |
863 | /// |
864 | /// ```rust |
865 | /// # fn main() -> Result<(), pyo3::PyErr> { |
866 | /// use pyo3::prelude::*; |
867 | /// |
868 | /// #[pyclass] |
869 | /// struct Class { |
870 | /// i: i32, |
871 | /// } |
872 | /// |
873 | /// Python::with_gil(|py| { |
874 | /// let class: &PyAny = Py::new(py, Class { i: 0 }).unwrap().into_ref(py); |
875 | /// |
876 | /// let class_cell: &PyCell<Class> = class.downcast()?; |
877 | /// |
878 | /// class_cell.borrow_mut().i += 1; |
879 | /// |
880 | /// // Alternatively you can get a `PyRefMut` directly |
881 | /// let class_ref: PyRefMut<'_, Class> = class.extract()?; |
882 | /// assert_eq!(class_ref.i, 1); |
883 | /// Ok(()) |
884 | /// }) |
885 | /// # } |
886 | /// ``` |
887 | #[inline ] |
888 | pub fn downcast<'p, T>(&'p self) -> Result<&'p T, PyDowncastError<'_>> |
889 | where |
890 | T: PyTryFrom<'p>, |
891 | { |
892 | <T as PyTryFrom>::try_from(self) |
893 | } |
894 | |
895 | /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it). |
896 | /// |
897 | /// It is almost always better to use [`PyAny::downcast`] because it accounts for Python |
898 | /// subtyping. Use this method only when you do not want to allow subtypes. |
899 | /// |
900 | /// The advantage of this method over [`PyAny::downcast`] is that it is faster. The implementation |
901 | /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas |
902 | /// `downcast` uses `isinstance(self, T)`. |
903 | /// |
904 | /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). |
905 | /// |
906 | /// # Example: Downcasting to a specific Python object but not a subtype |
907 | /// |
908 | /// ```rust |
909 | /// use pyo3::prelude::*; |
910 | /// use pyo3::types::{PyBool, PyLong}; |
911 | /// |
912 | /// Python::with_gil(|py| { |
913 | /// let b = PyBool::new(py, true); |
914 | /// assert!(b.is_instance_of::<PyBool>()); |
915 | /// let any: &PyAny = b.as_ref(); |
916 | /// |
917 | /// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int` |
918 | /// // but `downcast_exact` will not. |
919 | /// assert!(any.downcast::<PyLong>().is_ok()); |
920 | /// assert!(any.downcast_exact::<PyLong>().is_err()); |
921 | /// |
922 | /// assert!(any.downcast_exact::<PyBool>().is_ok()); |
923 | /// }); |
924 | /// ``` |
925 | #[inline ] |
926 | pub fn downcast_exact<'p, T>(&'p self) -> Result<&'p T, PyDowncastError<'_>> |
927 | where |
928 | T: PyTryFrom<'p>, |
929 | { |
930 | <T as PyTryFrom>::try_from_exact(self) |
931 | } |
932 | |
933 | /// Converts this `PyAny` to a concrete Python type without checking validity. |
934 | /// |
935 | /// # Safety |
936 | /// |
937 | /// Callers must ensure that the type is valid or risk type confusion. |
938 | #[inline ] |
939 | pub unsafe fn downcast_unchecked<'p, T>(&'p self) -> &'p T |
940 | where |
941 | T: PyTryFrom<'p>, |
942 | { |
943 | <T as PyTryFrom>::try_from_unchecked(self) |
944 | } |
945 | |
946 | /// Extracts some type from the Python object. |
947 | /// |
948 | /// This is a wrapper function around [`FromPyObject::extract()`]. |
949 | pub fn extract<'a, D>(&'a self) -> PyResult<D> |
950 | where |
951 | D: FromPyObject<'a>, |
952 | { |
953 | FromPyObject::extract(self) |
954 | } |
955 | |
956 | /// Returns the reference count for the Python object. |
957 | pub fn get_refcnt(&self) -> isize { |
958 | unsafe { ffi::Py_REFCNT(self.as_ptr()) } |
959 | } |
960 | |
961 | /// Computes the "repr" representation of self. |
962 | /// |
963 | /// This is equivalent to the Python expression `repr(self)`. |
964 | pub fn repr(&self) -> PyResult<&PyString> { |
965 | unsafe { |
966 | self.py() |
967 | .from_owned_ptr_or_err(ffi::PyObject_Repr(self.as_ptr())) |
968 | } |
969 | } |
970 | |
971 | /// Computes the "str" representation of self. |
972 | /// |
973 | /// This is equivalent to the Python expression `str(self)`. |
974 | pub fn str(&self) -> PyResult<&PyString> { |
975 | unsafe { |
976 | self.py() |
977 | .from_owned_ptr_or_err(ffi::PyObject_Str(self.as_ptr())) |
978 | } |
979 | } |
980 | |
981 | /// Retrieves the hash code of self. |
982 | /// |
983 | /// This is equivalent to the Python expression `hash(self)`. |
984 | pub fn hash(&self) -> PyResult<isize> { |
985 | let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) }; |
986 | crate::err::error_on_minusone(self.py(), v)?; |
987 | Ok(v) |
988 | } |
989 | |
990 | /// Returns the length of the sequence or mapping. |
991 | /// |
992 | /// This is equivalent to the Python expression `len(self)`. |
993 | pub fn len(&self) -> PyResult<usize> { |
994 | let v = unsafe { ffi::PyObject_Size(self.as_ptr()) }; |
995 | crate::err::error_on_minusone(self.py(), v)?; |
996 | Ok(v as usize) |
997 | } |
998 | |
999 | /// Returns the list of attributes of this object. |
1000 | /// |
1001 | /// This is equivalent to the Python expression `dir(self)`. |
1002 | pub fn dir(&self) -> &PyList { |
1003 | unsafe { self.py().from_owned_ptr(ffi::PyObject_Dir(self.as_ptr())) } |
1004 | } |
1005 | |
1006 | /// Checks whether this object is an instance of type `ty`. |
1007 | /// |
1008 | /// This is equivalent to the Python expression `isinstance(self, ty)`. |
1009 | #[inline ] |
1010 | pub fn is_instance(&self, ty: &PyAny) -> PyResult<bool> { |
1011 | let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) }; |
1012 | err::error_on_minusone(self.py(), result)?; |
1013 | Ok(result == 1) |
1014 | } |
1015 | |
1016 | /// Checks whether this object is an instance of exactly type `ty` (not a subclass). |
1017 | /// |
1018 | /// This is equivalent to the Python expression `type(self) is ty`. |
1019 | #[inline ] |
1020 | pub fn is_exact_instance(&self, ty: &PyAny) -> bool { |
1021 | self.get_type().is(ty) |
1022 | } |
1023 | |
1024 | /// Checks whether this object is an instance of type `T`. |
1025 | /// |
1026 | /// This is equivalent to the Python expression `isinstance(self, T)`, |
1027 | /// if the type `T` is known at compile time. |
1028 | #[inline ] |
1029 | pub fn is_instance_of<T: PyTypeInfo>(&self) -> bool { |
1030 | T::is_type_of(self) |
1031 | } |
1032 | |
1033 | /// Checks whether this object is an instance of exactly type `T`. |
1034 | /// |
1035 | /// This is equivalent to the Python expression `type(self) is T`, |
1036 | /// if the type `T` is known at compile time. |
1037 | #[inline ] |
1038 | pub fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool { |
1039 | T::is_exact_type_of(self) |
1040 | } |
1041 | |
1042 | /// Determines if self contains `value`. |
1043 | /// |
1044 | /// This is equivalent to the Python expression `value in self`. |
1045 | pub fn contains<V>(&self, value: V) -> PyResult<bool> |
1046 | where |
1047 | V: ToPyObject, |
1048 | { |
1049 | self._contains(value.to_object(self.py())) |
1050 | } |
1051 | |
1052 | fn _contains(&self, value: PyObject) -> PyResult<bool> { |
1053 | match unsafe { ffi::PySequence_Contains(self.as_ptr(), value.as_ptr()) } { |
1054 | 0 => Ok(false), |
1055 | 1 => Ok(true), |
1056 | _ => Err(PyErr::fetch(self.py())), |
1057 | } |
1058 | } |
1059 | |
1060 | /// Returns a GIL marker constrained to the lifetime of this type. |
1061 | #[inline ] |
1062 | pub fn py(&self) -> Python<'_> { |
1063 | PyNativeType::py(self) |
1064 | } |
1065 | |
1066 | /// Returns the raw FFI pointer represented by self. |
1067 | /// |
1068 | /// # Safety |
1069 | /// |
1070 | /// Callers are responsible for ensuring that the pointer does not outlive self. |
1071 | /// |
1072 | /// The reference is borrowed; callers should not decrease the reference count |
1073 | /// when they are finished with the pointer. |
1074 | #[inline ] |
1075 | pub fn as_ptr(&self) -> *mut ffi::PyObject { |
1076 | self as *const PyAny as *mut ffi::PyObject |
1077 | } |
1078 | |
1079 | /// Returns an owned raw FFI pointer represented by self. |
1080 | /// |
1081 | /// # Safety |
1082 | /// |
1083 | /// The reference is owned; when finished the caller should either transfer ownership |
1084 | /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). |
1085 | #[inline ] |
1086 | pub fn into_ptr(&self) -> *mut ffi::PyObject { |
1087 | // Safety: self.as_ptr() returns a valid non-null pointer |
1088 | unsafe { ffi::_Py_NewRef(self.as_ptr()) } |
1089 | } |
1090 | |
1091 | /// Return a proxy object that delegates method calls to a parent or sibling class of type. |
1092 | /// |
1093 | /// This is equivalent to the Python expression `super()` |
1094 | #[cfg (not(PyPy))] |
1095 | pub fn py_super(&self) -> PyResult<&PySuper> { |
1096 | PySuper::new(self.get_type(), self) |
1097 | } |
1098 | } |
1099 | |
1100 | #[cfg (test)] |
1101 | mod tests { |
1102 | use crate::{ |
1103 | types::{IntoPyDict, PyAny, PyBool, PyList, PyLong, PyModule}, |
1104 | Python, ToPyObject, |
1105 | }; |
1106 | |
1107 | #[test ] |
1108 | fn test_lookup_special() { |
1109 | Python::with_gil(|py| { |
1110 | let module = PyModule::from_code( |
1111 | py, |
1112 | r#" |
1113 | class CustomCallable: |
1114 | def __call__(self): |
1115 | return 1 |
1116 | |
1117 | class SimpleInt: |
1118 | def __int__(self): |
1119 | return 1 |
1120 | |
1121 | class InheritedInt(SimpleInt): pass |
1122 | |
1123 | class NoInt: pass |
1124 | |
1125 | class NoDescriptorInt: |
1126 | __int__ = CustomCallable() |
1127 | |
1128 | class InstanceOverrideInt: |
1129 | def __int__(self): |
1130 | return 1 |
1131 | instance_override = InstanceOverrideInt() |
1132 | instance_override.__int__ = lambda self: 2 |
1133 | |
1134 | class ErrorInDescriptorInt: |
1135 | @property |
1136 | def __int__(self): |
1137 | raise ValueError("uh-oh!") |
1138 | |
1139 | class NonHeapNonDescriptorInt: |
1140 | # A static-typed callable that doesn't implement `__get__`. These are pretty hard to come by. |
1141 | __int__ = int |
1142 | "# , |
1143 | "test.py" , |
1144 | "test" , |
1145 | ) |
1146 | .unwrap(); |
1147 | |
1148 | let int = crate::intern!(py, "__int__" ); |
1149 | let eval_int = |
1150 | |obj: &PyAny| obj.lookup_special(int)?.unwrap().call0()?.extract::<u32>(); |
1151 | |
1152 | let simple = module.getattr("SimpleInt" ).unwrap().call0().unwrap(); |
1153 | assert_eq!(eval_int(simple).unwrap(), 1); |
1154 | let inherited = module.getattr("InheritedInt" ).unwrap().call0().unwrap(); |
1155 | assert_eq!(eval_int(inherited).unwrap(), 1); |
1156 | let no_descriptor = module.getattr("NoDescriptorInt" ).unwrap().call0().unwrap(); |
1157 | assert_eq!(eval_int(no_descriptor).unwrap(), 1); |
1158 | let missing = module.getattr("NoInt" ).unwrap().call0().unwrap(); |
1159 | assert!(missing.lookup_special(int).unwrap().is_none()); |
1160 | // Note the instance override should _not_ call the instance method that returns 2, |
1161 | // because that's not how special lookups are meant to work. |
1162 | let instance_override = module.getattr("instance_override" ).unwrap(); |
1163 | assert_eq!(eval_int(instance_override).unwrap(), 1); |
1164 | let descriptor_error = module |
1165 | .getattr("ErrorInDescriptorInt" ) |
1166 | .unwrap() |
1167 | .call0() |
1168 | .unwrap(); |
1169 | assert!(descriptor_error.lookup_special(int).is_err()); |
1170 | let nonheap_nondescriptor = module |
1171 | .getattr("NonHeapNonDescriptorInt" ) |
1172 | .unwrap() |
1173 | .call0() |
1174 | .unwrap(); |
1175 | assert_eq!(eval_int(nonheap_nondescriptor).unwrap(), 0); |
1176 | }) |
1177 | } |
1178 | |
1179 | #[test ] |
1180 | fn test_call_for_non_existing_method() { |
1181 | Python::with_gil(|py| { |
1182 | let a = py.eval("42" , None, None).unwrap(); |
1183 | a.call_method0("__str__" ).unwrap(); // ok |
1184 | assert!(a.call_method("nonexistent_method" , (1,), None).is_err()); |
1185 | assert!(a.call_method0("nonexistent_method" ).is_err()); |
1186 | assert!(a.call_method1("nonexistent_method" , (1,)).is_err()); |
1187 | }); |
1188 | } |
1189 | |
1190 | #[test ] |
1191 | fn test_call_with_kwargs() { |
1192 | Python::with_gil(|py| { |
1193 | let list = vec![3, 6, 5, 4, 7].to_object(py); |
1194 | let dict = vec![("reverse" , true)].into_py_dict(py); |
1195 | list.call_method(py, "sort" , (), Some(dict)).unwrap(); |
1196 | assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3]); |
1197 | }); |
1198 | } |
1199 | |
1200 | #[test ] |
1201 | fn test_call_method0() { |
1202 | Python::with_gil(|py| { |
1203 | let module = PyModule::from_code( |
1204 | py, |
1205 | r#" |
1206 | class SimpleClass: |
1207 | def foo(self): |
1208 | return 42 |
1209 | "# , |
1210 | file!(), |
1211 | "test_module" , |
1212 | ) |
1213 | .expect("module creation failed" ); |
1214 | |
1215 | let simple_class = module.getattr("SimpleClass" ).unwrap().call0().unwrap(); |
1216 | assert_eq!( |
1217 | simple_class |
1218 | .call_method0("foo" ) |
1219 | .unwrap() |
1220 | .extract::<u32>() |
1221 | .unwrap(), |
1222 | 42 |
1223 | ); |
1224 | }) |
1225 | } |
1226 | |
1227 | #[test ] |
1228 | fn test_type() { |
1229 | Python::with_gil(|py| { |
1230 | let obj = py.eval("42" , None, None).unwrap(); |
1231 | assert_eq!(obj.get_type().as_type_ptr(), obj.get_type_ptr()); |
1232 | }); |
1233 | } |
1234 | |
1235 | #[test ] |
1236 | fn test_dir() { |
1237 | Python::with_gil(|py| { |
1238 | let obj = py.eval("42" , None, None).unwrap(); |
1239 | let dir = py |
1240 | .eval("dir(42)" , None, None) |
1241 | .unwrap() |
1242 | .downcast::<PyList>() |
1243 | .unwrap(); |
1244 | let a = obj |
1245 | .dir() |
1246 | .into_iter() |
1247 | .map(|x| x.extract::<String>().unwrap()); |
1248 | let b = dir.into_iter().map(|x| x.extract::<String>().unwrap()); |
1249 | assert!(a.eq(b)); |
1250 | }); |
1251 | } |
1252 | |
1253 | #[test ] |
1254 | fn test_hasattr() { |
1255 | Python::with_gil(|py| { |
1256 | let x = 5.to_object(py).into_ref(py); |
1257 | assert!(x.is_instance_of::<PyLong>()); |
1258 | |
1259 | assert!(x.hasattr("to_bytes" ).unwrap()); |
1260 | assert!(!x.hasattr("bbbbbbytes" ).unwrap()); |
1261 | }) |
1262 | } |
1263 | |
1264 | #[cfg (feature = "macros" )] |
1265 | #[test ] |
1266 | fn test_hasattr_error() { |
1267 | use crate::exceptions::PyValueError; |
1268 | use crate::prelude::*; |
1269 | |
1270 | #[pyclass(crate = "crate" )] |
1271 | struct GetattrFail; |
1272 | |
1273 | #[pymethods(crate = "crate" )] |
1274 | impl GetattrFail { |
1275 | fn __getattr__(&self, attr: PyObject) -> PyResult<PyObject> { |
1276 | Err(PyValueError::new_err(attr)) |
1277 | } |
1278 | } |
1279 | |
1280 | Python::with_gil(|py| { |
1281 | let obj = Py::new(py, GetattrFail).unwrap(); |
1282 | let obj = obj.as_ref(py).as_ref(); |
1283 | |
1284 | assert!(obj |
1285 | .hasattr("foo" ) |
1286 | .unwrap_err() |
1287 | .is_instance_of::<PyValueError>(py)); |
1288 | }) |
1289 | } |
1290 | |
1291 | #[test ] |
1292 | fn test_nan_eq() { |
1293 | Python::with_gil(|py| { |
1294 | let nan = py.eval("float('nan')" , None, None).unwrap(); |
1295 | assert!(nan.compare(nan).is_err()); |
1296 | }); |
1297 | } |
1298 | |
1299 | #[test ] |
1300 | fn test_any_is_instance_of() { |
1301 | Python::with_gil(|py| { |
1302 | let x = 5.to_object(py).into_ref(py); |
1303 | assert!(x.is_instance_of::<PyLong>()); |
1304 | |
1305 | let l = vec![x, x].to_object(py).into_ref(py); |
1306 | assert!(l.is_instance_of::<PyList>()); |
1307 | }); |
1308 | } |
1309 | |
1310 | #[test ] |
1311 | fn test_any_is_instance() { |
1312 | Python::with_gil(|py| { |
1313 | let l = vec![1u8, 2].to_object(py).into_ref(py); |
1314 | assert!(l.is_instance(py.get_type::<PyList>()).unwrap()); |
1315 | }); |
1316 | } |
1317 | |
1318 | #[test ] |
1319 | fn test_any_is_exact_instance_of() { |
1320 | Python::with_gil(|py| { |
1321 | let x = 5.to_object(py).into_ref(py); |
1322 | assert!(x.is_exact_instance_of::<PyLong>()); |
1323 | |
1324 | let t = PyBool::new(py, true); |
1325 | assert!(t.is_instance_of::<PyLong>()); |
1326 | assert!(!t.is_exact_instance_of::<PyLong>()); |
1327 | assert!(t.is_exact_instance_of::<PyBool>()); |
1328 | |
1329 | let l = vec![x, x].to_object(py).into_ref(py); |
1330 | assert!(l.is_exact_instance_of::<PyList>()); |
1331 | }); |
1332 | } |
1333 | |
1334 | #[test ] |
1335 | fn test_any_is_exact_instance() { |
1336 | Python::with_gil(|py| { |
1337 | let t = PyBool::new(py, true); |
1338 | assert!(t.is_instance(py.get_type::<PyLong>()).unwrap()); |
1339 | assert!(!t.is_exact_instance(py.get_type::<PyLong>())); |
1340 | assert!(t.is_exact_instance(py.get_type::<PyBool>())); |
1341 | }); |
1342 | } |
1343 | |
1344 | #[test ] |
1345 | fn test_any_contains() { |
1346 | Python::with_gil(|py| { |
1347 | let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8]; |
1348 | let ob = v.to_object(py).into_ref(py); |
1349 | |
1350 | let bad_needle = 7i32.to_object(py); |
1351 | assert!(!ob.contains(&bad_needle).unwrap()); |
1352 | |
1353 | let good_needle = 8i32.to_object(py); |
1354 | assert!(ob.contains(&good_needle).unwrap()); |
1355 | |
1356 | let type_coerced_needle = 8f32.to_object(py); |
1357 | assert!(ob.contains(&type_coerced_needle).unwrap()); |
1358 | |
1359 | let n: u32 = 42; |
1360 | let bad_haystack = n.to_object(py).into_ref(py); |
1361 | let irrelevant_needle = 0i32.to_object(py); |
1362 | assert!(bad_haystack.contains(&irrelevant_needle).is_err()); |
1363 | }); |
1364 | } |
1365 | |
1366 | // This is intentionally not a test, it's a generic function used by the tests below. |
1367 | fn test_eq_methods_generic<T>(list: &[T]) |
1368 | where |
1369 | T: PartialEq + PartialOrd + ToPyObject, |
1370 | { |
1371 | Python::with_gil(|py| { |
1372 | for a in list { |
1373 | for b in list { |
1374 | let a_py = a.to_object(py).into_ref(py); |
1375 | let b_py = b.to_object(py).into_ref(py); |
1376 | |
1377 | assert_eq!( |
1378 | a.lt(b), |
1379 | a_py.lt(b_py).unwrap(), |
1380 | " {} < {} should be {}." , |
1381 | a_py, |
1382 | b_py, |
1383 | a.lt(b) |
1384 | ); |
1385 | assert_eq!( |
1386 | a.le(b), |
1387 | a_py.le(b_py).unwrap(), |
1388 | " {} <= {} should be {}." , |
1389 | a_py, |
1390 | b_py, |
1391 | a.le(b) |
1392 | ); |
1393 | assert_eq!( |
1394 | a.eq(b), |
1395 | a_py.eq(b_py).unwrap(), |
1396 | " {} == {} should be {}." , |
1397 | a_py, |
1398 | b_py, |
1399 | a.eq(b) |
1400 | ); |
1401 | assert_eq!( |
1402 | a.ne(b), |
1403 | a_py.ne(b_py).unwrap(), |
1404 | " {} != {} should be {}." , |
1405 | a_py, |
1406 | b_py, |
1407 | a.ne(b) |
1408 | ); |
1409 | assert_eq!( |
1410 | a.gt(b), |
1411 | a_py.gt(b_py).unwrap(), |
1412 | " {} > {} should be {}." , |
1413 | a_py, |
1414 | b_py, |
1415 | a.gt(b) |
1416 | ); |
1417 | assert_eq!( |
1418 | a.ge(b), |
1419 | a_py.ge(b_py).unwrap(), |
1420 | " {} >= {} should be {}." , |
1421 | a_py, |
1422 | b_py, |
1423 | a.ge(b) |
1424 | ); |
1425 | } |
1426 | } |
1427 | }); |
1428 | } |
1429 | |
1430 | #[test ] |
1431 | fn test_eq_methods_integers() { |
1432 | let ints = [-4, -4, 1, 2, 0, -100, 1_000_000]; |
1433 | test_eq_methods_generic(&ints); |
1434 | } |
1435 | |
1436 | #[test ] |
1437 | fn test_eq_methods_strings() { |
1438 | let strings = ["Let's" , "test" , "some" , "eq" , "methods" ]; |
1439 | test_eq_methods_generic(&strings); |
1440 | } |
1441 | |
1442 | #[test ] |
1443 | fn test_eq_methods_floats() { |
1444 | let floats = [ |
1445 | -1.0, |
1446 | 2.5, |
1447 | 0.0, |
1448 | 3.0, |
1449 | std::f64::consts::PI, |
1450 | 10.0, |
1451 | 10.0 / 3.0, |
1452 | -1_000_000.0, |
1453 | ]; |
1454 | test_eq_methods_generic(&floats); |
1455 | } |
1456 | |
1457 | #[test ] |
1458 | fn test_eq_methods_bools() { |
1459 | let bools = [true, false]; |
1460 | test_eq_methods_generic(&bools); |
1461 | } |
1462 | |
1463 | #[test ] |
1464 | fn test_is_ellipsis() { |
1465 | Python::with_gil(|py| { |
1466 | let v = py |
1467 | .eval("..." , None, None) |
1468 | .map_err(|e| e.display(py)) |
1469 | .unwrap(); |
1470 | |
1471 | assert!(v.is_ellipsis()); |
1472 | |
1473 | let not_ellipsis = 5.to_object(py).into_ref(py); |
1474 | assert!(!not_ellipsis.is_ellipsis()); |
1475 | }); |
1476 | } |
1477 | } |
1478 | |